You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2006/12/23 12:21:45 UTC
svn commit: r489880 - in /directory/trunks/shared/ldap: ./ src/main/antlr/
src/main/java/org/apache/directory/shared/ldap/schema/syntax/
src/main/java/org/apache/directory/shared/ldap/subtree/
src/test/java/org/apache/directory/shared/ldap/schema/syntax/
Author: ersiner
Date: Sat Dec 23 03:21:43 2006
New Revision: 489880
URL: http://svn.apache.org/viewvc?view=rev&rev=489880
Log:
Implemented the SubtreeSpecificationChecker (with all Antlr plumbing) which only parses a SubtreeSpecification but does not populate any beans.
Updated SubtreeSpecificationSyntaxChecker and its tests to use the new checker.
Added:
directory/trunks/shared/ldap/src/main/antlr/SubtreeSpecificationChecker.g
directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationChecker.java
directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java
directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationChecker.java
Modified:
directory/trunks/shared/ldap/pom.xml
directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java
directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxCheckerTest.java
Modified: directory/trunks/shared/ldap/pom.xml
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/pom.xml?view=diff&rev=489880&r1=489879&r2=489880
==============================================================================
--- directory/trunks/shared/ldap/pom.xml (original)
+++ directory/trunks/shared/ldap/pom.xml Sat Dec 23 03:21:43 2006
@@ -116,7 +116,7 @@
<artifactId>maven-antlr-plugin</artifactId>
<configuration>
<!--grammars>filter-value-lexer.g filter-lexer.g filter-lexer.g filter-value-parser.g filter-parser.g *.gsubtree-specification.g ACIItem.g TriggerSpecification.g schema.g</grammars-->
- <grammars>filter-value-lexer.g filter-lexer.g filter-lexer.g filter-value-parser.g filter-parser.g ACIItem.g ACIItemChecker.g schema-extension.g schema-qdstring.g schema-value.g schema.g subtree-specification.g TriggerSpecification.g</grammars>
+ <grammars>filter-value-lexer.g filter-lexer.g filter-lexer.g filter-value-parser.g filter-parser.g ACIItem.g ACIItemChecker.g schema-extension.g schema-qdstring.g schema-value.g schema.g subtree-specification.g SubtreeSpecificationChecker.g TriggerSpecification.g</grammars>
</configuration>
<executions>
<execution>
Added: directory/trunks/shared/ldap/src/main/antlr/SubtreeSpecificationChecker.g
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/antlr/SubtreeSpecificationChecker.g?view=auto&rev=489880
==============================================================================
--- directory/trunks/shared/ldap/src/main/antlr/SubtreeSpecificationChecker.g (added)
+++ directory/trunks/shared/ldap/src/main/antlr/SubtreeSpecificationChecker.g Sat Dec 23 03:21:43 2006
@@ -0,0 +1,436 @@
+header
+{
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.shared.ldap.subtree;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.ArrayList;
+
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.filter.AssertionEnum;
+import org.apache.directory.shared.ldap.util.ComponentsMonitor;
+import org.apache.directory.shared.ldap.util.OptionalComponentsMonitor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The antlr generated subtree specification parser.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+class AntlrSubtreeSpecificationChecker extends Parser;
+
+
+// ----------------------------------------------------------------------------
+// parser options
+// ----------------------------------------------------------------------------
+
+options
+{
+ k = 1;
+ defaultErrorHandler = false;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser initialization
+// ----------------------------------------------------------------------------
+
+{
+ private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationChecker.class );
+
+ private ComponentsMonitor subtreeSpecificationComponentsMonitor = null;
+
+ /**
+ * Does nothing.
+ */
+ public void init()
+ {
+ }
+
+
+ private int token2Integer( Token token ) throws RecognitionException
+ {
+ int i = 0;
+
+ try
+ {
+ i = Integer.parseInt( token.getText());
+ }
+ catch ( NumberFormatException e )
+ {
+ throw new RecognitionException( "Value of INTEGER token " +
+ token.getText() +
+ " cannot be converted to an Integer" );
+ }
+
+ return i;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// parser productions
+// ----------------------------------------------------------------------------
+
+wrapperEntryPoint
+{
+ log.debug( "entered wrapperEntryPoint()" );
+} :
+ subtreeSpecification "end"
+ ;
+
+subtreeSpecification
+{
+ log.debug( "entered subtreeSpecification()" );
+ subtreeSpecificationComponentsMonitor = new OptionalComponentsMonitor(
+ new String [] { "base", "specificExclusions", "minimum", "maximum", "specificationFilter" } );
+}
+ :
+ OPEN_CURLY ( SP )*
+ ( subtreeSpecificationComponent ( SP )*
+ ( SEP ( SP )* subtreeSpecificationComponent ( SP )* )* )?
+ CLOSE_CURLY
+ ;
+
+subtreeSpecificationComponent
+{
+ log.debug( "entered subtreeSpecification()" );
+}
+ :
+ ss_base
+ {
+ subtreeSpecificationComponentsMonitor.useComponent( "base" );
+ }
+ | ss_specificExclusions
+ {
+ subtreeSpecificationComponentsMonitor.useComponent( "specificExclusions" );
+ }
+ | ss_minimum
+ {
+ subtreeSpecificationComponentsMonitor.useComponent( "minimum" );
+ }
+ | ss_maximum
+ {
+ subtreeSpecificationComponentsMonitor.useComponent( "maximum" );
+ }
+ | ss_specificationFilter
+ {
+ subtreeSpecificationComponentsMonitor.useComponent( "specificationFilter" );
+ }
+ ;
+ exception
+ catch [IllegalArgumentException e]
+ {
+ throw new RecognitionException( e.getMessage() );
+ }
+
+ss_base
+{
+ log.debug( "entered ss_base()" );
+}
+ :
+ ID_base ( SP )+ distinguishedName
+ ;
+
+ss_specificExclusions
+{
+ log.debug( "entered ss_specificExclusions()" );
+}
+ :
+ ID_specificExclusions ( SP )+ specificExclusions
+ ;
+
+specificExclusions
+{
+ log.debug( "entered specificExclusions()" );
+}
+ :
+ OPEN_CURLY ( SP )*
+ ( specificExclusion ( SP )*
+ ( SEP ( SP )* specificExclusion ( SP )* )*
+ )?
+ CLOSE_CURLY
+ ;
+
+specificExclusion
+{
+ log.debug( "entered specificExclusion()" );
+}
+ :
+ chopBefore | chopAfter
+ ;
+
+chopBefore
+{
+ log.debug( "entered chopBefore()" );
+}
+ :
+ ID_chopBefore ( SP )* COLON ( SP )* distinguishedName
+ ;
+
+chopAfter
+{
+ log.debug( "entered chopAfter()" );
+}
+ :
+ ID_chopAfter ( SP )* COLON ( SP )* distinguishedName
+ ;
+
+ss_minimum
+{
+ log.debug( "entered ss_minimum()" );
+}
+ :
+ ID_minimum ( SP )+ baseDistance
+ ;
+
+ss_maximum
+{
+ log.debug( "entered ss_maximum()" );
+}
+ :
+ ID_maximum ( SP )+ baseDistance
+ ;
+
+ss_specificationFilter
+{
+ log.debug( "entered ss_specificationFilter()" );
+}
+ :
+ ID_specificationFilter ( SP )+ refinement
+ ;
+
+distinguishedName
+{
+ log.debug( "entered distinguishedName()" );
+}
+ :
+ token:SAFEUTF8STRING
+ {
+ new LdapDN( token.getText() );
+ log.debug( "recognized a DistinguishedName: " + token.getText() );
+ }
+ ;
+ exception
+ catch [Exception e]
+ {
+ throw new RecognitionException( "dnParser failed for " + token.getText() + " " + e.getMessage() );
+ }
+
+baseDistance
+{
+ log.debug( "entered baseDistance()" );
+}
+ :
+ token:INTEGER
+ {
+ token2Integer(token);
+ }
+ ;
+
+oid
+{
+ log.debug( "entered oid()" );
+ Token token = null;
+}
+ :
+ { token = LT( 1 ); } // an interesting trick goes here ;-)
+ ( DESCR | NUMERICOID )
+ {
+ log.debug( "recognized an oid: " + token.getText() );
+ }
+ ;
+
+refinement
+{
+ log.debug( "entered refinement()" );
+}
+ :
+ item | and | or | not
+ ;
+
+item
+{
+ log.debug( "entered item()" );
+}
+ :
+ ID_item ( SP )* COLON ( SP )* oid
+ ;
+
+and
+{
+ log.debug( "entered and()" );
+}
+ :
+ ID_and ( SP )* COLON ( SP )* refinements
+ ;
+
+or
+{
+ log.debug( "entered or()" );
+}
+ :
+ ID_or ( SP )* COLON ( SP )* refinements
+ ;
+
+not
+{
+ log.debug( "entered not()" );
+}
+ :
+ ID_not ( SP )* COLON ( SP )* refinements
+ ;
+
+refinements
+{
+ log.debug( "entered refinements()" );
+}
+ :
+ OPEN_CURLY ( SP )*
+ (
+ refinement ( SP )*
+ ( SEP ( SP )* refinement ( SP )* )*
+ )? CLOSE_CURLY
+ ;
+
+
+// ----------------------------------------------------------------------------
+// lexer class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The parser's primary lexer.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+class AntlrSubtreeSpecificationCheckerLexer extends Lexer;
+
+
+// ----------------------------------------------------------------------------
+// lexer options
+// ----------------------------------------------------------------------------
+
+options
+{
+ k = 2;
+
+ charVocabulary = '\u0001'..'\u0127';
+}
+
+tokens
+{
+ ID_base = "base";
+ ID_specificExclusions = "specificExclusions";
+ ID_chopBefore = "chopBefore";
+ ID_chopAfter = "chopAfter";
+ ID_minimum = "minimum";
+ ID_maximum = "maximum";
+ ID_specificationFilter = "specificationFilter";
+ ID_item = "item";
+ ID_and = "and";
+ ID_or = "or";
+ ID_not = "not";
+}
+
+
+//----------------------------------------------------------------------------
+// lexer initialization
+//----------------------------------------------------------------------------
+
+{
+ private static final Logger log = LoggerFactory.getLogger( AntlrSubtreeSpecificationLexer.class );
+}
+
+
+// ----------------------------------------------------------------------------
+// attribute description lexer rules from models
+// ----------------------------------------------------------------------------
+
+SP : ' ';
+
+COLON : ':' { log.debug( "matched COLON(':')" ); } ;
+
+OPEN_CURLY : '{' { log.debug( "matched LBRACKET('{')" ); } ;
+
+CLOSE_CURLY : '}' { log.debug( "matched RBRACKET('}')" ); } ;
+
+SEP : ',' { log.debug( "matched SEP(',')" ); } ;
+
+SAFEUTF8STRING : '"'! ( SAFEUTF8CHAR )* '"'! { log.debug( "matched SAFEUTF8CHAR: \"" + getText() + "\"" ); } ;
+
+DESCR : ALPHA ( ALPHA | DIGIT | '-' )* { log.debug( "matched DESCR" ); } ;
+
+INTEGER_OR_NUMERICOID
+ :
+ ( INTEGER DOT ) => NUMERICOID
+ {
+ $setType( NUMERICOID );
+ }
+ |
+ INTEGER
+ {
+ $setType( INTEGER );
+ }
+ ;
+
+protected INTEGER: DIGIT | ( LDIGIT ( DIGIT )+ ) { log.debug( "matched INTEGER: " + getText() ); } ;
+
+protected NUMERICOID: INTEGER ( DOT INTEGER )+ { log.debug( "matched NUMERICOID: " + getText() ); } ;
+
+protected DOT: '.' ;
+
+protected DIGIT: '0' | LDIGIT ;
+
+protected LDIGIT: '1'..'9' ;
+
+protected ALPHA: 'A'..'Z' | 'a'..'z' ;
+
+// This is all messed up - could not figure out how to get antlr to represent
+// the safe UTF-8 character set from RFC 3642 for production SafeUTF8Character
+
+protected SAFEUTF8CHAR:
+ '\u0001'..'\u0021' |
+ '\u0023'..'\u007F' |
+ '\u00c0'..'\u00d6' |
+ '\u00d8'..'\u00f6' |
+ '\u00f8'..'\u00ff' |
+ '\u0100'..'\u1fff' |
+ '\u3040'..'\u318f' |
+ '\u3300'..'\u337f' |
+ '\u3400'..'\u3d2d' |
+ '\u4e00'..'\u9fff' |
+ '\uf900'..'\ufaff' ;
Modified: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java?view=diff&rev=489880&r1=489879&r2=489880
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java (original)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java Sat Dec 23 03:21:43 2006
@@ -19,6 +19,12 @@
*/
package org.apache.directory.shared.ldap.schema.syntax;
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.aci.ACIItemChecker;
+import org.apache.directory.shared.ldap.subtree.SubtreeSpecificationChecker;
+import org.apache.directory.shared.ldap.util.StringTools;
+
/**
* A SyntaxChecker which verifies that a value is a subtree specification.
@@ -28,11 +34,12 @@
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev: 488616 $
*/
-public class SubtreeSpecificationSyntaxChecker extends BinarySyntaxChecker
+public class SubtreeSpecificationSyntaxChecker extends AbstractSyntaxChecker
{
/** the Apache assigned internal OID for this syntax checker */
private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.45";
+ private SubtreeSpecificationChecker checker = new SubtreeSpecificationChecker();
/**
* Private default constructor to prevent unnecessary instantiation.
@@ -59,6 +66,42 @@
*/
public boolean isValidSyntax( Object value )
{
- return true;
+ String strValue;
+
+ if ( value == null )
+ {
+ return false;
+ }
+
+ if ( value instanceof String )
+ {
+ strValue = ( String ) value;
+ }
+ else if ( value instanceof byte[] )
+ {
+ strValue = StringTools.utf8ToString( ( byte[] ) value );
+ }
+ else
+ {
+ strValue = value.toString();
+ }
+
+ if ( strValue.length() == 0 )
+ {
+ return false;
+ }
+
+ try
+ {
+ synchronized( checker )
+ {
+ checker.parse( strValue );
+ }
+ return true;
+ }
+ catch ( ParseException pe )
+ {
+ return false;
+ }
}
}
Added: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationChecker.java?view=auto&rev=489880
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationChecker.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationChecker.java Sat Dec 23 03:21:43 2006
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.shared.ldap.subtree;
+
+
+import org.apache.directory.shared.ldap.subtree.AntlrSubtreeSpecificationChecker;
+
+import antlr.TokenStream;
+
+
+/**
+ * A reusable parser class extended from antlr generated parser for an LDAP
+ * subtree specification as defined by <a
+ * href="http://www.faqs.org/rfcs/rfc3672.html"> RFC 3672</a>. This class
+ * enables the reuse of the antlr parser without having to recreate the it every
+ * time as stated in <a
+ * href="http://www.antlr.org:8080/pipermail/antlr-interest/2003-April/003631.html">
+ * a Antlr Interest Group mail</a> .
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437007 $
+ */
+class ReusableAntlrSubtreeSpecificationChecker extends AntlrSubtreeSpecificationChecker
+{
+ /**
+ * Creates a ReusableAntlrSubtreeSpecificationParser instance.
+ */
+ public ReusableAntlrSubtreeSpecificationChecker(TokenStream lexer)
+ {
+ super( lexer );
+ }
+
+
+ /**
+ * Resets the state of an antlr parser.
+ */
+ public void resetState()
+ {
+ // no set method for this protected field.
+ this.traceDepth = 0;
+
+ this.getInputState().reset();
+ }
+}
Added: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java?view=auto&rev=489880
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/ReusableAntlrSubtreeSpecificationCheckerLexer.java Sat Dec 23 03:21:43 2006
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.shared.ldap.subtree;
+
+
+import java.io.Reader;
+
+import org.apache.directory.shared.ldap.subtree.AntlrSubtreeSpecificationCheckerLexer;
+
+import antlr.CharBuffer;
+import antlr.LexerSharedInputState;
+
+
+/**
+ * A reusable lexer class extended from antlr generated lexer for an LDAP
+ * subtree specification as defined by <a
+ * href="http://www.faqs.org/rfcs/rfc3672.html"> RFC 3672</a>. This class
+ * enables the reuse of the antlr lexer without having to recreate the it every
+ * time as stated in <a
+ * href="http://www.antlr.org:8080/pipermail/antlr-interest/2003-April/003631.html">
+ * a Antlr Interest Group mail</a> .
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437007 $
+ */
+public class ReusableAntlrSubtreeSpecificationCheckerLexer extends AntlrSubtreeSpecificationCheckerLexer
+{
+ private boolean savedCaseSensitive;
+
+ private boolean savedCaseSensitiveLiterals;
+
+
+ /**
+ * Creates a ReusableAntlrSubtreeSpecificationLexer instance.
+ *
+ * @param in
+ * the input to the lexer
+ */
+ public ReusableAntlrSubtreeSpecificationCheckerLexer(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;
+ }
+}
Added: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationChecker.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationChecker.java?view=auto&rev=489880
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationChecker.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationChecker.java Sat Dec 23 03:21:43 2006
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.directory.shared.ldap.subtree;
+
+
+import java.io.StringReader;
+import java.text.ParseException;
+import java.util.Map;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+
+/**
+ * A reusable wrapper around the antlr generated parser for an LDAP subtree
+ * specification as defined by <a href="http://www.faqs.org/rfcs/rfc3672.html">
+ * RFC 3672</a>. This class enables the reuse of the antlr parser/lexer pair
+ * without having to recreate the pair every time.
+ *
+ * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437007 $
+ */
+public class SubtreeSpecificationChecker
+{
+ /** the antlr generated parser being wrapped */
+ private ReusableAntlrSubtreeSpecificationChecker parser;
+
+ /** the antlr generated lexer being wrapped */
+ private ReusableAntlrSubtreeSpecificationCheckerLexer lexer;
+
+
+ /**
+ * Creates a subtree specification parser.
+ */
+ public SubtreeSpecificationChecker( Map oidsMap )
+ {
+ StringReader in = new StringReader( "" ); // place holder for the
+ // first input
+ this.lexer = new ReusableAntlrSubtreeSpecificationCheckerLexer( in );
+ this.parser = new ReusableAntlrSubtreeSpecificationChecker( lexer );
+ this.parser.init(); // this method MUST be called while we cannot do
+ // constructor overloading for antlr generated parser
+ }
+
+
+ /**
+ * Creates a normalizing subtree specification parser.
+ */
+ public SubtreeSpecificationChecker()
+ {
+ StringReader in = new StringReader( "" ); // place holder for the
+ // first input
+ this.lexer = new ReusableAntlrSubtreeSpecificationCheckerLexer( in );
+ this.parser = new ReusableAntlrSubtreeSpecificationChecker( lexer );
+ this.parser.init(); // this method MUST be called while we cannot do
+ // constructor overloading for antlr generated parser
+ }
+
+
+ /**
+ * Initializes the plumbing by creating a pipe and coupling the parser/lexer
+ * pair with it. param spec the specification to be parsed
+ */
+ private synchronized void reset( String spec )
+ {
+ StringReader in = new StringReader( spec + "end" ); // append end of
+ // input token
+ this.lexer.prepareNextInput( in );
+ this.parser.resetState();
+ }
+
+
+ /**
+ * Parses a subtree specification without exhausting the parser.
+ *
+ * @param spec
+ * the specification to be parsed
+ * @return the specification bean
+ * @throws ParseException
+ * if there are any recognition errors (bad syntax)
+ */
+ public synchronized void parse( String spec ) throws ParseException
+ {
+ if ( spec == null || spec.trim().equals( "" ) )
+ {
+ return;
+ }
+
+ reset( spec ); // reset and initialize the parser / lexer pair
+
+ try
+ {
+ this.parser.wrapperEntryPoint();
+ }
+ catch ( TokenStreamException e )
+ {
+ String msg = "Parser failure on subtree specification:\n\t" + spec;
+ msg += "\nAntlr exception trace:\n" + e.getMessage();
+ throw new ParseException( msg, 0 );
+ }
+ catch ( RecognitionException e )
+ {
+ String msg = "Parser failure on subtree specification:\n\t" + spec;
+ msg += "\nAntlr exception trace:\n" + e.getMessage();
+ throw new ParseException( msg, e.getColumn() );
+ }
+ catch ( Exception e )
+ {
+ String msg = "Parser failure on subtree specification:\n\t" + spec;
+ msg += "\nAntlr exception trace:\n" + e.getMessage();
+ throw new ParseException( msg, 0 );
+ }
+ }
+
+}
Modified: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxCheckerTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxCheckerTest.java?view=diff&rev=489880&r1=489879&r2=489880
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxCheckerTest.java (original)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxCheckerTest.java Sat Dec 23 03:21:43 2006
@@ -19,6 +19,15 @@
*/
package org.apache.directory.shared.ldap.schema.syntax;
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.filter.AssertionEnum;
+import org.apache.directory.shared.ldap.filter.BranchNode;
+import org.apache.directory.shared.ldap.filter.SimpleNode;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
+import org.apache.directory.shared.ldap.subtree.SubtreeSpecificationParser;
+
import junit.framework.TestCase;
/**
@@ -34,13 +43,13 @@
public void testNullString()
{
- assertTrue( checker.isValidSyntax( null ) );
+ assertFalse( checker.isValidSyntax( null ) );
}
public void testEmptyString()
{
- assertTrue( checker.isValidSyntax( "" ) );
+ assertFalse( checker.isValidSyntax( "" ) );
}
public void testOid()
@@ -50,7 +59,173 @@
public void testCorrectCase()
{
- assertTrue( checker.isValidSyntax( "FALSE" ) );
- assertTrue( checker.isValidSyntax( new byte[]{0x01, (byte)0xFF} ) );
+ }
+
+ /** A valid empty specification with single white space between brackets */
+ private static final String EMPTY_SPEC = "{ }";
+
+ /** A valid specification only with base set */
+ private static final String SPEC_WITH_BASE = "{ base \"ou=system\" }";
+
+ /** An invalid specification with missing white space and base set */
+ private static final String INVALID_SPEC_WITH_BASE_AND_MISSING_WS = "{ base\"ou=system\"}";
+
+ /** A valid specification with some specific exclusions set */
+ private static final String SPEC_WITH_SPECIFICEXCLUSIONS = "{ specificExclusions { chopAfter:\"ef=gh\", chopBefore:\"ab=cd\" } }";
+
+ /** A valid specification with empty specific exclusions set */
+ private static final String SPEC_WITH_EMPTY_SPECIFICEXCLUSIONS = "{ specificExclusions { } }";
+
+ /** A valid specification with minimum and maximum set */
+ private static final String SPEC_WITH_MINIMUM_AND_MAXIMUM = "{ minimum 1, maximum 2 }";
+
+ /** A valid specification with base and minimum and maximum set */
+ private static final String SPEC_WITH_BASE_AND_MINIMUM_AND_MAXIMUM = "{ base \"ou=ORGANIZATION UNIT\", minimum 1, maximum 2 }";
+
+ /**
+ * A valid specification with base and specific exclusions and minimum and
+ * maximum set
+ */
+ private static final String SPEC_WITH_BASE_AND_SPECIFICEXCLUSIONS_AND_MINIMUM_AND_MAXIMUM = "{ base \"ou=people\", specificExclusions { chopBefore:\"x=y\""
+ + ", chopAfter:\"k=l\", chopBefore:\"y=z\", chopAfter:\"l=m\" }, minimum 7, maximum 77 }";
+
+ /** A valid specification with refinement set */
+ private static final String SPEC_WITH_REFINEMENT = "{ base \"ou=system\", specificationFilter and:{ and:{ item:1.2.3"
+ + ", or:{ item:4.5.6, item:person-7 } }, not:{ item:10.11.12 } } }";
+
+ /** A valid specification with base and an empty refinement set */
+ private static final String SPEC_WITH_BASE_AND_EMPTY_REFINEMENT = "{ base \"ou=system\", specificationFilter and:{ } }";
+
+ /** A valid specification with ALL IN ONE */
+ private static final String SPEC_WITH_ALL_IN_ONE = "{ base \"ou=departments\""
+ + ", specificExclusions { chopBefore:\"x=y\", chopAfter:\"k=l\", chopBefore:\"y=z\", chopAfter:\"l=m\" }"
+ + ", minimum 7, maximum 77"
+ + ", specificationFilter and:{ and:{ item:1.2.3, or:{ item:4.5.6, item:7.8.9 } }, not:{ item:10.11.12 } } }";
+
+ /** An valid specification with unordinary component order */
+ private static final String SPEC_ORDER_OF_COMPONENTS_DOES_NOT_MATTER = "{ base \"ou=system\", minimum 3, specificExclusions { chopBefore:\"x=y\" } }";
+
+ /** An invalid specification with completely unrelated content */
+ private static final String INVALID_SILLY_THING = "How much wood would a wood chuck chuck if a wood chuck would chuck wood?";
+
+ /**
+ * Tests the parser with a valid empty specification.
+ */
+ public void testEmptySpec() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( EMPTY_SPEC ) );
+
+ // try a second time
+ assertTrue( checker.isValidSyntax( EMPTY_SPEC ) );
+
+ // try a third time
+ assertTrue( checker.isValidSyntax( EMPTY_SPEC ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with base set.
+ */
+ public void testSpecWithBase() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_BASE ) );
+ }
+
+
+ /**
+ * Tests the parser with an invalid specification with missing white spaces
+ * and base set.
+ */
+ public void testInvalidSpecWithBaseAndMissingWS() throws Exception
+ {
+ assertFalse( checker.isValidSyntax( INVALID_SPEC_WITH_BASE_AND_MISSING_WS ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with some specific exclusions
+ * set.
+ */
+ public void testSpecWithSpecificExclusions() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_SPECIFICEXCLUSIONS ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with an empty specific
+ * exclusions set.
+ */
+ public void testSpecWithEmptySpecificExclusions() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_EMPTY_SPECIFICEXCLUSIONS ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with minimum and maximum set.
+ */
+ public void testSpecWithMinimumAndMaximum() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_MINIMUM_AND_MAXIMUM ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with base and minimum and
+ * maximum set.
+ */
+ public void testWithBaseAndMinimumAndMaximum() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_BASE_AND_MINIMUM_AND_MAXIMUM ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with base and specific
+ * exclusions and minimum and maximum set.
+ */
+ public void testSpecWithBaseAndSpecificExclusionsAndMinimumAndMaximum() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_BASE_AND_SPECIFICEXCLUSIONS_AND_MINIMUM_AND_MAXIMUM ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with refinement set.
+ */
+ public void testSpecWithRefinement() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_REFINEMENT ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with base and empty
+ * refinement set.
+ */
+ public void testSpecWithBaseAndEmptyRefinement() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_BASE_AND_EMPTY_REFINEMENT ) );
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with all components set.
+ */
+ public void testSpecWithAllInOne() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_WITH_ALL_IN_ONE ) );
+
+ }
+
+
+ /**
+ * Tests the parser with a valid specification with unordinary component
+ * order.
+ */
+ public void testSpecOrderOfComponentsDoesNotMatter() throws Exception
+ {
+ assertTrue( checker.isValidSyntax( SPEC_ORDER_OF_COMPONENTS_DOES_NOT_MATTER ) );
}
}