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/04/29 08:34:16 UTC

svn commit: r398097 - in /directory/trunks/shared/ldap: ./ src/main/antlr/ src/main/java/org/apache/directory/shared/ldap/trigger/ src/test/java/org/apache/directory/shared/ldap/trigger/

Author: ersiner
Date: Fri Apr 28 23:34:14 2006
New Revision: 398097

URL: http://svn.apache.org/viewcvs?rev=398097&view=rev
Log:
Added the first version of LDAP Trigger parser without bean population.

Added:
    directory/trunks/shared/ldap/src/main/antlr/TriggerSpecification.g
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationLexer.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationParser.java
    directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParser.java
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/
    directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java
Modified:
    directory/trunks/shared/ldap/pom.xml

Modified: directory/trunks/shared/ldap/pom.xml
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/pom.xml?rev=398097&r1=398096&r2=398097&view=diff
==============================================================================
--- directory/trunks/shared/ldap/pom.xml (original)
+++ directory/trunks/shared/ldap/pom.xml Fri Apr 28 23:34:14 2006
@@ -121,7 +121,7 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-antlr-plugin</artifactId>
         <configuration>
-          <grammars>valuelexer.g valueparser.g typelexer.g dnparser.g filter-value-lexer.g filter-lexer.g filter-lexer.g filter-value-parser.g filter-parser.g subtree-specification.g ACIItem.g</grammars>
+          <grammars>valuelexer.g valueparser.g typelexer.g dnparser.g filter-value-lexer.g filter-lexer.g filter-lexer.g filter-value-parser.g filter-parser.g subtree-specification.g ACIItem.g TriggerSpecification.g</grammars>
         </configuration>
         <executions>
            <execution>

Added: directory/trunks/shared/ldap/src/main/antlr/TriggerSpecification.g
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/src/main/antlr/TriggerSpecification.g?rev=398097&view=auto
==============================================================================
--- directory/trunks/shared/ldap/src/main/antlr/TriggerSpecification.g (added)
+++ directory/trunks/shared/ldap/src/main/antlr/TriggerSpecification.g Fri Apr 28 23:34:14 2006
@@ -0,0 +1,757 @@
+header
+{
+/*
+ *   Copyright 2006 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.directory.shared.ldap.trigger;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.name.DnParser;
+import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+}
+
+
+// ----------------------------------------------------------------------------
+// parser class definition
+// ----------------------------------------------------------------------------
+
+/**
+ * The ANTLR generated TriggerSpecification parser.
+ * 
+ * @see http://docs.safehaus.org/display/APACHEDS/Grammar+for+Triggers
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$ $Date$
+ */
+class AntlrTriggerSpecificationParser extends Parser;
+
+
+// ----------------------------------------------------------------------------
+// parser options
+// ----------------------------------------------------------------------------
+
+options
+{
+    k = 1;
+    defaultErrorHandler = false;
+}
+
+
+// ----------------------------------------------------------------------------
+// parser initialization
+// ----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrTriggerSpecificationParser.class );
+    
+    // subordinate parser instances
+    private DnParser dnParser;
+    
+    private boolean isNormalizing = false;
+    private NameComponentNormalizer normalizer;
+    
+    /**
+     * Creates a (normalizing) subordinate DnParser for parsing Names.
+     * This method MUST be called for each instance while we cannot do
+     * constructor overloading for this class.
+     *
+     * @return the DnParser to be used for parsing Names
+     */
+    public void init()
+    {
+        try
+        {
+            if( isNormalizing )
+            {
+                dnParser = new DnParser( normalizer );
+            }
+            else
+            {
+                dnParser = new DnParser();
+            }
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed to initialize the subordinate DnParser for this AntlrTriggerSpecificationParser";
+
+            // We throw a NPE since this variable cannot be null for proper operation
+            // so we can catch the null pointer before the dnParser is even used.
+
+            throw new NullPointerException( "dnParser is null: " + msg );
+        }
+    }
+
+    /**
+     * Sets the NameComponentNormalizer for this parser's dnParser.
+     */
+    public void setNormalizer(NameComponentNormalizer normalizer)
+    {
+        this.normalizer = normalizer;
+        this.isNormalizing = true;
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+//  parser productions
+// ----------------------------------------------------------------------------
+
+wrapperEntryPoint
+{
+    log.debug( "entered wrapperEntryPoint()" );
+}
+    :
+    ( SP )* triggerSpecification ( SP )* EOF
+    ;
+
+// -----------------------------------------------------------------------------
+//  main rules
+// -----------------------------------------------------------------------------
+
+triggerSpecification
+{
+    log.debug( "entered triggerSpecification()" );
+}
+    :
+    actionTime ( SP )+ ldapOperationAndStoredProcedureCall
+    ;
+    
+actionTime
+{
+    log.debug( "entered actionTime()" );
+}
+    : ID_BEFORE
+    | ID_AFTER
+    | ID_INSTEADOF
+    ;
+    
+ldapOperationAndStoredProcedureCall
+{
+    log.debug( "entered ldapOperationAndStoredProcedureCall()" );
+}
+    : bindOperationAndStoredProcedureCall
+    | unbindOperationAndStoredProcedureCall
+    | searchOperationAndStoredProcedureCall
+    | modifyOperationAndStoredProcedureCall
+    | addOperationAndStoredProcedureCall
+    | delOperationAndStoredProcedureCall
+    | modDNOperationAndStoredProcedureCall
+    | compareOperationAndStoredProcedureCall
+    | abandonOperationAndStoredProcedureCall
+    | extendedOperationAndStoredProcedureCall
+    ;
+
+// -----------------------------------------------------------------------------
+//  XXXOperationAndStoredProcedureCall
+// -----------------------------------------------------------------------------
+
+bindOperationAndStoredProcedureCall
+{
+    log.debug( "entered bindOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_bind theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( bindStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+unbindOperationAndStoredProcedureCall
+{
+    log.debug( "entered unbindOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_unbind theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( unbindStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+searchOperationAndStoredProcedureCall
+{
+    log.debug( "entered searchOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_search theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( searchStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+modifyOperationAndStoredProcedureCall
+{
+    log.debug( "entered modifyOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_modify theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( modifyStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+addOperationAndStoredProcedureCall
+{
+    log.debug( "entered addOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_add theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( addStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+delOperationAndStoredProcedureCall
+{
+    log.debug( "entered delOperationAndStoredProcedureCall()" );
+}
+    :
+    ( ID_del | ID_delete ) theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( delStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+modDNOperationAndStoredProcedureCall
+{
+    log.debug( "entered modDNOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_modDN theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( modDNStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+compareOperationAndStoredProcedureCall
+{
+    log.debug( "entered compareOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_compare theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( compareStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+abandonOperationAndStoredProcedureCall
+{
+    log.debug( "entered abandonOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_abandon theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( abandonStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+extendedOperationAndStoredProcedureCall
+{
+    log.debug( "entered extendedOperationAndStoredProcedureCall()" );
+}
+    :
+    ID_extended theCompositeRuleForCallAndSPNameAndSPOptionList
+    OPEN_PARAN ( SP )*
+        ( extendedStoredProcedureParameterList )?
+    CLOSE_PARAN
+    ;
+
+// -----------------------------------------------------------------------------
+// The following rule does not make any sense semantically. Just placed for
+// reducing repetition. All OperationAndStoredProcedureCall type are heavily
+// context sensitive where their StoredProcedureParameterList depends on their
+// Operation type. Other elements that sit between these two dependend elements
+// are repeated for all OperationAndStoredProcedureCall type rules. So the
+// the fallowing rule is for the part falling between those two dependend parts.
+// -----------------------------------------------------------------------------
+
+theCompositeRuleForCallAndSPNameAndSPOptionList
+{
+    log.debug( "entered theCompositeRuleForCallAndSPNameAndSPOptionList()" );
+}
+    :
+    ( SP )+ ID_CALL ( SP )+ fullyQualifiedStoredProcedureName ( SP )*
+        ( genericStoredProcedureOptionList ( SP )* )?
+    ;
+
+// -----------------------------------------------------------------------------
+//  XXXStoredProcedureParameterList
+// -----------------------------------------------------------------------------
+
+bindStoredProcedureParameterList
+{
+    log.debug( "entered bindStoredProcedureParameterList()" );
+}
+    :
+    bindStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* bindStoredProcedureParameter ( SP )* )*
+    ;
+
+unbindStoredProcedureParameterList
+{
+    log.debug( "entered unbindStoredProcedureParameterList()" );
+}
+    :
+    unbindStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* unbindStoredProcedureParameter ( SP )* )*
+    ;
+
+searchStoredProcedureParameterList
+{
+    log.debug( "entered searchStoredProcedureParameterList()" );
+}
+    :
+    searchStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* searchStoredProcedureParameter ( SP )* )*
+    ;
+
+modifyStoredProcedureParameterList
+{
+    log.debug( "entered modifyStoredProcedureParameterList()" );
+}
+    :
+    modifyStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* modifyStoredProcedureParameter ( SP )* )*
+    ;
+
+addStoredProcedureParameterList
+{
+    log.debug( "entered addStoredProcedureParameterList()" );
+}
+    :
+    addStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* addStoredProcedureParameter ( SP )* )*
+    ;
+
+delStoredProcedureParameterList
+{
+    log.debug( "entered delStoredProcedureParameterList()" );
+}
+    :
+    delStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* delStoredProcedureParameter ( SP )* )*
+    ;
+
+modDNStoredProcedureParameterList
+{
+    log.debug( "entered modDNStoredProcedureParameterList()" );
+}
+    :
+    modDNStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* modDNStoredProcedureParameter ( SP )* )*
+    ;
+
+compareStoredProcedureParameterList
+{
+    log.debug( "entered compareStoredProcedureParameterList()" );
+}
+    :
+    compareStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* compareStoredProcedureParameter ( SP )* )*
+    ;
+
+abandonStoredProcedureParameterList
+{
+    log.debug( "entered abandonStoredProcedureParameterList()" );
+}
+    :
+    abandonStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* abandonStoredProcedureParameter ( SP )* )*
+    ;
+
+extendedStoredProcedureParameterList
+{
+    log.debug( "entered extendedStoredProcedureParameterList()" );
+}
+    :
+    extendedStoredProcedureParameter ( SP )*
+        ( SEP ( SP )* extendedStoredProcedureParameter ( SP )* )*
+    ;
+
+// -----------------------------------------------------------------------------
+// XXXStoredProcedureParameter
+// -----------------------------------------------------------------------------
+
+bindStoredProcedureParameter
+{
+    log.debug( "entered bindStoredProcedureParameter()" );
+}
+    : ID_version
+    | ID_name
+    | ID_authentication
+    | genericStoredProcedureParameter
+    ;
+
+unbindStoredProcedureParameter
+{
+    log.debug( "entered unbindStoredProcedureParameter()" );
+}
+    : genericStoredProcedureParameter
+    ;
+
+searchStoredProcedureParameter
+{
+    log.debug( "entered searchStoredProcedureParameter()" );
+}
+    : ID_baseObject
+    | ID_scope
+    | ID_derefAliases
+    | ID_sizeLimit
+    | ID_timeLimit
+    | ID_typesOnly
+    | ID_filter
+    | ID_attributes
+    | genericStoredProcedureParameter
+    ;
+
+modifyStoredProcedureParameter
+{
+    log.debug( "entered modifyStoredProcedureParameter()" );
+}
+    : ID_object
+    | ID_modification
+    | ID_oldEntry
+    | ID_newEntry
+    | genericStoredProcedureParameter
+    ;
+
+addStoredProcedureParameter
+{
+    log.debug( "entered addStoredProcedureParameter()" );
+}
+    : ID_entry
+    | ID_attributes
+    | genericStoredProcedureParameter
+    ;
+
+delStoredProcedureParameter
+{
+    log.debug( "entered delStoredProcedureParameter()" );
+}
+    : ID_name
+    | ID_deletedEntry
+    | genericStoredProcedureParameter
+    ;
+
+modDNStoredProcedureParameter
+{
+    log.debug( "entered modDNStoredProcedureParameter()" );
+}
+    : ID_entry
+    | ID_newrdn
+    | ID_deleteoldrdn
+    | ID_newSuperior
+    | genericStoredProcedureParameter
+    ;
+
+compareStoredProcedureParameter
+{
+    log.debug( "entered compareStoredProcedureParameter()" );
+}
+    : ID_entry
+    | ID_ava
+    | genericStoredProcedureParameter
+    ;
+
+abandonStoredProcedureParameter
+{
+    log.debug( "entered abandonStoredProcedureParameter()" );
+}
+    : ID_messageId
+    | genericStoredProcedureParameter
+    ;
+    
+extendedStoredProcedureParameter
+{
+    log.debug( "entered extendedStoredProcedureParameter()" );
+}
+    : ID_requestName
+    | ID_requestValue
+    | genericStoredProcedureParameter
+    ;
+
+// -----------------------------------------------------------------------------
+
+genericStoredProcedureParameter
+{
+    log.debug( "entered genericStoredProcedureParameter()" );
+}
+    :
+    ID_operationTime | ID_operationPrincipal
+    ;
+
+// -----------------------------------------------------------------------------
+
+genericStoredProcedureOptionList
+{
+    log.debug( "entered genericStoredProcedureOptionList()" );
+}
+    :
+    OPEN_CURLY ( SP )* ( genericStoredProcedureOption ( SP )*
+        ( SEP ( SP )* genericStoredProcedureOption ( SP )* )* )* CLOSE_CURLY
+    ;
+
+genericStoredProcedureOption
+{
+    log.debug( "entered genericStoredProcedureOption()" );
+}
+    :
+    storedProcedureLanguageOption | storedProcedureSearchContextOption
+    ;
+
+storedProcedureLanguageOption
+{
+    log.debug( "entered storedProcedureLanguageOption()" );
+}
+    :
+    ID_language ( SP )+ languageToken:UTF8String
+    ;
+
+storedProcedureSearchContextOption
+{
+    log.debug( "entered storedProcedureSearchContextOption()" );
+}
+    :
+    ID_searchContext ( SP )+
+        ( OPEN_CURLY ( SP )*
+            ( ID_search_scope ( SP )+ storedProcedureSearchScope ( SP )* )?
+        CLOSE_CURLY ( SP )+ )?
+    storedProcedureSearchContext
+    ;
+
+storedProcedureSearchScope
+{
+    log.debug( "entered storedProcedureSearchScope()" );
+}
+    : ID_scope_base
+    | ID_scope_one
+    | ID_scope_subtree
+    ;
+
+storedProcedureSearchContext
+{
+    log.debug( "entered storedProcedureSearchContext()" );
+}
+    : distinguishedName
+    ;
+
+// -----------------------------------------------------------------------------
+
+fullyQualifiedStoredProcedureName
+{
+    log.debug( "entered fullyQualifiedStoredProcedureName()" );
+}
+    :
+    spNameToken:UTF8String
+    ;
+
+distinguishedName returns [ Name name ] 
+{
+    log.debug( "entered distinguishedName()" );
+    name = null;
+}
+    :
+    nameToken:UTF8String
+    {
+        name = dnParser.parse( nameToken.getText() );
+    }
+    ;
+    exception
+    catch [Exception e]
+    {
+        throw new RecognitionException( "name parser failed for " + nameToken.getText() + " " + e.getMessage() );
+    }
+
+// -----------------------------------------------------------------------------
+//  lexer class definition
+// -----------------------------------------------------------------------------
+
+/**
+  * The parser's primary lexer.
+  *
+  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+  * @version $Rev$
+  */
+class AntlrTriggerSpecificationLexer extends Lexer;
+
+
+// -----------------------------------------------------------------------------
+//  lexer options
+// -----------------------------------------------------------------------------
+
+options
+{
+    k = 1;
+    defaultErrorHandler = false;
+    charVocabulary = '\3'..'\377';
+    // the grammar is case-insensitive
+    caseSensitive = false;
+    caseSensitiveLiterals = false;
+}
+
+
+// -----------------------------------------------------------------------------
+//  tokens
+// -----------------------------------------------------------------------------
+
+tokens
+{
+    // action time identifiers
+    ID_BEFORE = "before";
+    ID_AFTER = "after";
+    ID_INSTEADOF = "insteadof";
+    
+    // operation identifiers
+    ID_bind = "bind";
+    ID_unbind = "unbind";
+    ID_search  = "search";
+    ID_modify  = "modify";
+    ID_add = "add";
+    ID_del = "del";
+    ID_delete = "delete";
+    ID_modDN = "moddn";
+    ID_compare = "compare";
+    ID_abandon = "abandon";
+    ID_extended = "extended";
+    
+    // bind specific parameters
+    ID_version = "$version";
+    ID_name = "$name";
+    ID_authentication = "$authentication";
+    
+    // unbind specific parameters
+    // there is non currently
+    
+    // search specific parameters
+    ID_baseObject = "$baseobject";
+    ID_scope = "$scope";
+    ID_derefAliases = "$derefaliases";
+    ID_sizeLimit = "$sizelimit";
+    ID_timeLimit = "$timelimit";
+    ID_typesOnly = "$typesonly";
+    ID_filter = "$filter";
+    ID_attributes = "$attributes";
+    
+    // modify specific parameters
+    ID_object = "$object";
+    ID_modification = "$modification";
+    ID_oldEntry = "$oldentry";
+    ID_newEntry = "$newentry";
+    
+    // add specific parameters
+    ID_entry = "$entry";
+    // ID_attributes = "$attributes"; // defined before
+    
+    // del specific parameters
+    // ID_name = "$name"; // defined before
+    ID_deletedEntry = "$deletedentry";
+    
+    // modDN specific parameters
+    // ID_entry = "$entry"; // defined before
+    ID_newrdn = "$newrdn";
+    ID_deleteoldrdn = "$deleteoldrdn";
+    ID_newSuperior = "$newsuperior";
+    
+    // compare specific parameters
+    // ID_entry = "$entry"; // defined before
+    ID_ava = "$ava";
+    
+    // abandon specific parameters
+    ID_messageId = "$messageid";
+    
+    // extended specific parameters
+    ID_requestName = "$requestname";
+    ID_requestValue = "$requestvalue";
+    
+    // generic parameters
+    ID_operationTime = "$operationtime";
+    ID_operationPrincipal = "$operationprincipal";
+    
+    ID_CALL = "call";
+    
+    ID_language = "language";
+    ID_searchContext = "searchcontext";
+    ID_search_scope = "scope";
+    ID_scope_base = "base";
+    ID_scope_one = "one";
+    ID_scope_subtree = "subtree";
+}
+
+
+// -----------------------------------------------------------------------------
+//  lexer initialization
+// -----------------------------------------------------------------------------
+
+{
+    private static final Logger log = LoggerFactory.getLogger( AntlrTriggerSpecificationLexer.class );
+}
+
+
+// -----------------------------------------------------------------------------
+//  attribute description lexer rules from models
+// -----------------------------------------------------------------------------
+
+OPEN_PARAN : '(' ;
+
+CLOSE_PARAN : ')' ;
+
+OPEN_CURLY : '{' ;
+
+CLOSE_CURLY : '}' ;
+
+SEP : ',' ;
+
+SP
+    : ' '
+    | '\t'
+    | '\n' { newline(); }
+    | '\r' ('\n')? { newline(); }
+    ;
+
+UTF8String : '"'! ( SAFEUTF8CHAR )* '"'! ;
+
+//  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'
+    ;
+
+COMMENT
+    : '#'
+    (~('\n'|'\r'))* (('\n'|'\r'('\n')?){newline();})?
+    {$setType(Token.SKIP);}
+    ;
+
+IDENTIFIER : ALPHA ( ALPHA )* ; // A MUST HAVE although we do not use explicitly
+
+protected ALPHA : 'a'..'z' | '$' ;
\ No newline at end of file

Added: directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationLexer.java
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationLexer.java?rev=398097&view=auto
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationLexer.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationLexer.java Fri Apr 28 23:34:14 2006
@@ -0,0 +1,79 @@
+/*
+ *   Copyright 2006 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.directory.shared.ldap.trigger;
+
+
+import java.io.Reader;
+
+import antlr.CharBuffer;
+import antlr.LexerSharedInputState;
+
+
+/**
+ * A reusable lexer class extended from antlr generated lexer for an LDAP
+ * Trigger Specification as defined at <a
+ * http://docs.safehaus.org/display/APACHEDS/Grammar+for+Triggers">
+ * The ABNF grammar for LDAP Triggers</a>.
+ * 
+ * <p>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">
+ * an ANTLR Interest Group mail</a> .
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev:$
+ */
+class ReusableAntlrTriggerSpecificationLexer extends AntlrTriggerSpecificationLexer
+{
+    private boolean savedCaseSensitive;
+
+    private boolean savedCaseSensitiveLiterals;
+
+
+    /**
+     * Creates a ReusableAntlrTriggerSpecificationLexer instance.
+     * 
+     * @param in
+     *            the input to the lexer
+     */
+    public ReusableAntlrTriggerSpecificationLexer( 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/trigger/ReusableAntlrTriggerSpecificationParser.java
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationParser.java?rev=398097&view=auto
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationParser.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ReusableAntlrTriggerSpecificationParser.java Fri Apr 28 23:34:14 2006
@@ -0,0 +1,59 @@
+/*
+ *   Copyright 2006 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.directory.shared.ldap.trigger;
+
+
+import antlr.TokenStream;
+
+
+/**
+ * A reusable lexer class extended from antlr generated parser for an LDAP
+ * Trigger Specification as defined at <a
+ * http://docs.safehaus.org/display/APACHEDS/Grammar+for+Triggers">
+ * The ABNF grammar for LDAP Triggers</a>.
+ * 
+ * <p>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">
+ * an ANTLR Interest Group mail</a> .
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev:$
+ */
+class ReusableAntlrTriggerSpecificationParser extends AntlrTriggerSpecificationParser
+{
+    /**
+     * Creates a ReusableAntlrTriggerSpecificationParser instance.
+     */
+    public ReusableAntlrTriggerSpecificationParser(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/trigger/TriggerSpecificationParser.java
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParser.java?rev=398097&view=auto
==============================================================================
--- directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParser.java (added)
+++ directory/trunks/shared/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParser.java Fri Apr 28 23:34:14 2006
@@ -0,0 +1,140 @@
+/*
+ *   Copyright 2005 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.directory.shared.ldap.trigger;
+
+
+import java.io.StringReader;
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+
+/**
+ * A reusable wrapper around the antlr generated parser for an ACIItem as
+ * defined by X.501. This class enables the reuse of the antlr parser/lexer pair
+ * without having to recreate them every time.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 379008 $
+ */
+public class TriggerSpecificationParser
+{
+    /** the antlr generated parser being wrapped */
+    private ReusableAntlrTriggerSpecificationParser parser;
+
+    /** the antlr generated lexer being wrapped */
+    private ReusableAntlrTriggerSpecificationLexer lexer;
+
+    private final boolean isNormalizing;
+
+
+    /**
+     * Creates a ACIItem parser.
+     */
+    public TriggerSpecificationParser()
+    {
+        this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) );
+        this.parser = new ReusableAntlrTriggerSpecificationParser( lexer );
+
+        this.parser.init(); // this method MUST be called while we cannot do
+        // constructor overloading for antlr generated parser
+        this.isNormalizing = false;
+    }
+
+
+    /**
+     * Creates a normalizing ACIItem parser.
+     */
+    public TriggerSpecificationParser(NameComponentNormalizer normalizer)
+    {
+        this.lexer = new ReusableAntlrTriggerSpecificationLexer( new StringReader( "" ) );
+        this.parser = new ReusableAntlrTriggerSpecificationParser( lexer );
+
+        this.parser.setNormalizer( normalizer );
+        this.parser.init(); // this method MUST be called while we cannot do
+        // constructor overloading for antlr generated parser
+        this.isNormalizing = true;
+    }
+
+
+    /**
+     * 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 );
+        this.lexer.prepareNextInput( in );
+        this.parser.resetState();
+    }
+
+
+    /**
+     * Parses an ACIItem 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 = "TokenStreamException: Parser failure on ACIItem:\n\t" + spec;
+            msg += "\nAntlr exception trace:\n";
+            e.printStackTrace();
+            throw new ParseException( msg, 0 );
+        }
+        catch ( RecognitionException e )
+        {
+            String msg = "RecognitionException: Parser failure on ACIItem:\n\t" + spec;
+            msg += "\nAntlr exception trace:\n";
+            e.printStackTrace();
+            throw new ParseException( msg, e.getColumn() );
+        }
+
+    }
+
+
+    /**
+     * Tests to see if this parser is normalizing.
+     * 
+     * @return true if it normalizes false otherwise
+     */
+    public boolean isNormizing()
+    {
+        return this.isNormalizing;
+    }
+}

Added: directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java
URL: http://svn.apache.org/viewcvs/directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java?rev=398097&view=auto
==============================================================================
--- directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java (added)
+++ directory/trunks/shared/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java Fri Apr 28 23:34:14 2006
@@ -0,0 +1,87 @@
+/*
+ *   Copyright 2006 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.directory.shared.ldap.trigger;
+
+
+import junit.framework.TestCase;
+
+
+/**
+ * Unit tests for {@link org.apache.directory.shared.ldap.trigger.TriggerSpecificationParser}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class TriggerSpecificationParserTest extends TestCase
+{
+
+    /** The Trigger Specification parser */
+    TriggerSpecificationParser parser;
+
+    
+    /**
+     * Creates a TriggerSpecificationParserTest instance.
+     */
+    public TriggerSpecificationParserTest()
+    {
+        super();
+        parser = new TriggerSpecificationParser();
+    }
+
+
+    /**
+     * Creates a TriggerSpecificationParserTest instance.
+     */
+    public TriggerSpecificationParserTest(String s)
+    {
+        super( s );
+        parser = new TriggerSpecificationParser();
+    }
+
+    public void testWithOperationParameters() throws Exception
+    {
+        String spec = "BEFORE delete CALL \"BackupUtilities.backupDeletedEntry\" ($name, $deletedEntry)";
+
+        parser.parse( spec );
+    }
+    
+    public void testWithGenericParameters() throws Exception
+    {
+        String spec = "AFTER add CALL \"Logger.logAddOperation\" ($entry, $attributes, $operationPrincipal)";
+
+        parser.parse( spec );
+    }
+    
+    public void testWithLanguageOptionAndComments() throws Exception
+    {
+        String spec = "INSTEADOF search # do not do search \n" +
+            "CALL \"RestrictionUtilities.searchNoWay\"{language \"Java\"}() # but run a procedure";
+
+        parser.parse( spec );
+    }
+    
+    public void testWithSearchContextOption() throws Exception
+    {
+        String spec = "BEFORE bind  # Action Time and Operation \n" +
+            "CALL \"AuthUtilities.beforeBind\"  # Stored Procedure Call \n" +
+            "{ searchContext { scope one } \"cn=Auth,cn=System Stored Procedures,ou=system\" }  # Stored Procedure Call Options \n" +
+            "($name)  # Stored Procedure Parameter(s)";
+
+        parser.parse( spec );
+    }
+    
+}