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