Index: common/src/java/org/apache/ldap/common/name/ReusableAntlrValueLexer.java =================================================================== --- common/src/java/org/apache/ldap/common/name/ReusableAntlrValueLexer.java (revision 0) +++ common/src/java/org/apache/ldap/common/name/ReusableAntlrValueLexer.java (revision 0) @@ -0,0 +1,63 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.ldap.common.name; + + +import antlr.LexerSharedInputState; + + +/** + * A reusable lexer class extended from antlr generated antlrValueLexer + * + * @author Apache Directory Project + * @version $Rev$ + */ +public class ReusableAntlrValueLexer extends antlrValueLexer +{ + private boolean savedCaseSensitive; + private boolean savedCaseSensitiveLiterals; + + /** + * Creates a ReusableAntlrValueLexer instance. + * + * @param in the input to the lexer + */ + public ReusableAntlrValueLexer( LexerSharedInputState inputState ) + { + super( inputState ); + savedCaseSensitive = getCaseSensitive(); + savedCaseSensitiveLiterals = getCaseSensitiveLiterals(); + } + + + /** + * Resets the state of an antlr lexer and initializes it with new input. + * + * @param in the input to the lexer + */ + public void prepareNextInput( LexerSharedInputState inputState ) + { + this.setInputState( inputState ); + + this.setCaseSensitive(savedCaseSensitive); + + // no set method for this protected field. + this.caseSensitiveLiterals = savedCaseSensitiveLiterals; + } +} Index: common/src/java/org/apache/ldap/common/name/ReusableAntlrNameParser.java =================================================================== --- common/src/java/org/apache/ldap/common/name/ReusableAntlrNameParser.java (revision 0) +++ common/src/java/org/apache/ldap/common/name/ReusableAntlrNameParser.java (revision 0) @@ -0,0 +1,58 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.ldap.common.name; + + +import antlr.TokenStreamSelector; + + +/** + * A reusable parser class extended from antlr generated parser for an LDAP + * subtree specification as defined by + * RFC 3672. This class enables the reuse of the antlr parser without having to + * recreate the it every time as stated in + * + * a Antlr Interest Group mail . + * + * @see RFC 3672 + * @author Apache Directory Project + * @version $Rev$ + */ +class ReusableAntlrNameParser extends antlrNameParser +{ + /** + * Creates a ReusableAntlrNameParser instance. + */ + public ReusableAntlrNameParser( TokenStreamSelector selector ) + { + super( selector ); + } + + + /** + * Resets the state of an antlr parser. + */ + public void resetState() + { + // no set method for this protected field. + this.traceDepth = 0; + + this.getInputState().reset(); + } +} Index: common/src/java/org/apache/ldap/common/name/ReusableAntlrTypeLexer.java =================================================================== --- common/src/java/org/apache/ldap/common/name/ReusableAntlrTypeLexer.java (revision 0) +++ common/src/java/org/apache/ldap/common/name/ReusableAntlrTypeLexer.java (revision 0) @@ -0,0 +1,68 @@ +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.ldap.common.name; + + +import java.io.Reader; + +import antlr.CharBuffer; +import antlr.LexerSharedInputState; + + +/** + * A reusable lexer class extended from antlr generated antlrTypelexer + * + * @author Apache Directory Project + * @version $Rev$ + */ +public class ReusableAntlrTypeLexer extends antlrTypeLexer +{ + private boolean savedCaseSensitive; + private boolean savedCaseSensitiveLiterals; + + /** + * Creates a ReusableAntlrValueLexer instance. + * + * @param in the input to the lexer + */ + public ReusableAntlrTypeLexer( Reader in ) + { + super( in ); + savedCaseSensitive = getCaseSensitive(); + savedCaseSensitiveLiterals = getCaseSensitiveLiterals(); + } + + + /** + * Resets the state of an antlr lexer and initializes it with new input. + * + * @param in the input to the lexer + */ + public void prepareNextInput( Reader in ) + { + CharBuffer buf = new CharBuffer( in ); + LexerSharedInputState state = new LexerSharedInputState( buf ); + this.setInputState(state); + + this.setCaseSensitive(savedCaseSensitive); + + // no set method for this protected field. + this.caseSensitiveLiterals = savedCaseSensitiveLiterals; + } +} Index: common/src/java/org/apache/ldap/common/name/DnParser.java =================================================================== --- common/src/java/org/apache/ldap/common/name/DnParser.java (revision 263906) +++ common/src/java/org/apache/ldap/common/name/DnParser.java (working copy) @@ -19,8 +19,7 @@ import java.io.IOException ; -import java.io.PipedInputStream ; -import java.io.PipedOutputStream ; +import java.io.StringReader; import javax.naming.Name ; import javax.naming.NameParser ; @@ -28,7 +27,6 @@ import org.apache.ldap.common.util.ExceptionUtils ; import org.apache.ldap.common.util.NestableRuntimeException ; -import org.apache.ldap.common.util.ParserPipedInputStream; import org.apache.ldap.common.exception.LdapNamingException; import org.apache.ldap.common.exception.LdapInvalidNameException; import org.apache.ldap.common.message.ResultCodeEnum; @@ -46,16 +44,17 @@ */ public class DnParser implements NameParser { - /** */ - private PipedOutputStream m_parserIn ; - /** */ private TokenStreamSelector m_selector ; - /** */ + private final boolean m_isNormalizing ; - /** */ - private antlrNameParser m_parser ; + private ReusableAntlrNameParser m_parser ; + + private ReusableAntlrTypeLexer typeLexer ; + + private ReusableAntlrValueLexer valueLexer ; + /** * Creates a regular non normalizing name parser. * @@ -122,25 +121,31 @@ */ private void init() throws IOException { - // Create selector and piped plumbing to feed the parser. - this.m_parserIn = new PipedOutputStream() ; this.m_selector = new TokenStreamSelector() ; - PipedInputStream in = new ParserPipedInputStream() ; - this.m_parserIn.connect( in ) ; // Create lexers and add them to the selector. - antlrTypeLexer typeLexer = new antlrTypeLexer( in ) ; - this.m_selector.addInputStream( typeLexer, antlrTypeLexer.LEXER_KEY ) ; + typeLexer = new ReusableAntlrTypeLexer( new StringReader( "" ) ) ; + this.m_selector.addInputStream( typeLexer, ReusableAntlrTypeLexer.LEXER_KEY ) ; - antlrValueLexer valueLexer = new antlrValueLexer( typeLexer.getInputState() ) ; - this.m_selector.addInputStream( valueLexer, antlrValueLexer.LEXER_KEY ) ; + valueLexer = new ReusableAntlrValueLexer( typeLexer.getInputState() ) ; + this.m_selector.addInputStream( valueLexer, ReusableAntlrValueLexer.LEXER_KEY ) ; // Set selector on lexers, select initial lexer and initalize parser typeLexer.setSelector( this.m_selector ) ; valueLexer.setSelector( this.m_selector ) ; - this.m_selector.select( antlrTypeLexer.LEXER_KEY ) ; - this.m_parser = new antlrNameParser( m_selector ) ; + this.m_selector.select( ReusableAntlrTypeLexer.LEXER_KEY ) ; + this.m_parser = new ReusableAntlrNameParser( m_selector ) ; } + + /** + * Resets the parser and lexers to be reused with new input + */ + private synchronized void reset( String name ) + { + this.typeLexer.prepareNextInput( new StringReader( name + "#\n" ) ); + this.valueLexer.prepareNextInput( typeLexer.getInputState() ); + this.m_parser.resetState(); + } /** @@ -152,7 +157,7 @@ * @throws NamingException if a_name is invalid or the parsers plumbing * breaks */ - public Name parse( String name, LdapName emptyName ) throws NamingException + public synchronized Name parse( String name, LdapName emptyName ) throws NamingException { // Handle the empty name basis case. if ( name == null || name.trim().equals( "" ) ) @@ -162,53 +167,22 @@ try { - synchronized ( m_parserIn ) + if ( null == emptyName ) { - m_parserIn.write( name.getBytes() ) ; - m_parserIn.write( '#' ) ; - m_parserIn.write( '\n' ) ; - m_parserIn.flush() ; - - if ( null == emptyName ) - { - emptyName = new LdapName( m_parser.name() ) ; - } - else - { - emptyName.setList( m_parser.name() ) ; - } + reset( name ); + emptyName = new LdapName( m_parser.name() ) ; } - } - catch ( IOException e ) - { - String msg = "Parser failure on name:\n\t" + name ; - msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e ) ; - - try + else { - init() ; + reset( name ); + emptyName.setList( m_parser.name() ) ; } - catch ( IOException initError ) - { - throw new LdapNamingException( "Failed to reinitialize dn parser", ResultCodeEnum.OTHER ); - } - - throw new LdapNamingException( msg, ResultCodeEnum.OTHER ) ; } catch ( RecognitionException e ) { String msg = "Parser failure on name:\n\t" + name ; msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e ) ; - try - { - init() ; - } - catch ( IOException initError ) - { - throw new LdapNamingException( "Failed to reinitialize dn parser", ResultCodeEnum.OTHER ); - } - throw new LdapInvalidNameException( msg, ResultCodeEnum.INVALIDDNSYNTAX ) ; } catch ( TokenStreamException e2 ) @@ -216,15 +190,6 @@ String msg = "Parser failure on name:\n\t" + name ; msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e2 ) ; - try - { - init() ; - } - catch ( IOException initError ) - { - throw new LdapNamingException( "Failed to reinitialize dn parser", ResultCodeEnum.OTHER ); - } - throw new LdapInvalidNameException( msg, ResultCodeEnum.INVALIDDNSYNTAX ) ; } catch ( NestableRuntimeException e ) @@ -247,7 +212,6 @@ /** * Parses a name as a String into a Name object. - * * @see javax.naming.NameParser#parse(java.lang.String) */ public Name parse( String name ) throws NamingException