You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2010/06/29 18:56:09 UTC

svn commit: r959029 [3/4] - in /directory/shared/trunk/ldap-aci: ./ .settings/ src/ src/main/ src/main/antlr/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/shared/ src...

Added: directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/AttributeValueItem.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/AttributeValueItem.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/AttributeValueItem.java (added)
+++ directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/AttributeValueItem.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,122 @@
+/*
+ *  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.aci.protectedItem;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.naming.directory.Attribute;
+
+import org.apache.directory.shared.ldap.aci.ProtectedItem;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+
+/**
+ * A specific value of specific attributes.
+ */
+public class AttributeValueItem extends ProtectedItem
+{
+    private final Set<EntryAttribute> attributes;
+
+
+    /**
+     * Creates a new instance.
+     * 
+     * @param attributes the collection of {@link Attribute}s.
+     */
+    public AttributeValueItem( Set<EntryAttribute> attributes )
+    {
+        this.attributes = Collections.unmodifiableSet( attributes );
+    }
+
+
+    /**
+     * Returns an iterator of all {@link Attribute}s.
+     */
+    public Iterator<EntryAttribute> iterator()
+    {
+        return attributes.iterator();
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode()
+    {
+        int hash = 37;
+        hash = hash * 17 + attributes.hashCode();
+        return hash;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+
+        if ( o == null )
+        {
+            return false;
+        }
+
+        if ( o instanceof AttributeValueItem )
+        {
+            AttributeValueItem that = ( AttributeValueItem ) o;
+            
+            return this.attributes.equals( that.attributes );
+        }
+
+        return false;
+    }
+
+
+    // This will suppress PMD.EmptyCatchBlock warnings in this method
+    public String toString()
+    {
+        StringBuilder buf = new StringBuilder();
+
+        buf.append( "attributeValue {" );
+
+        for ( Iterator<EntryAttribute> it = attributes.iterator(); it.hasNext(); )
+        {
+            EntryAttribute attribute = it.next();
+            buf.append( attribute.getId() );
+            buf.append( '=' );
+            buf.append( attribute.get( 0 ) );
+
+            if ( it.hasNext() )
+            {
+                buf.append( ", " );
+            }
+        }
+
+        buf.append( " }" );
+
+        return buf.toString();
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/SelfValueItem.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/SelfValueItem.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/SelfValueItem.java (added)
+++ directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/aci/protectedItem/SelfValueItem.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,50 @@
+/*
+ *  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.aci.protectedItem;
+
+import java.util.Set;
+
+/**
+ * The attribute value assertion corresponding to the current requestor. The
+ * protected item selfValue applies only when the access controls are to be
+ * applied with respect to a specific authenticated user. It can only apply
+ * in the specific case where the attribute specified is of DN and the
+ * attribute value within the specified attribute matches the DN of the
+ * originator of the operation.
+ */
+public class SelfValueItem extends AbstractAttributeTypeProtectedItem
+{
+    /**
+     * Creates a new instance.
+     * 
+     * @param attributeTypes the collection of attribute IDs.
+     */
+    public SelfValueItem( Set<String> attributeTypes )
+    {
+        super( attributeTypes );
+    }
+
+
+    public String toString()
+    {
+        return "selfValue " + super.toString();
+    }
+}
+

Added: directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/schema/syntaxCheckers/ACIItemSyntaxChecker.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/schema/syntaxCheckers/ACIItemSyntaxChecker.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/schema/syntaxCheckers/ACIItemSyntaxChecker.java (added)
+++ directory/shared/trunk/ldap-aci/src/main/java/org/apache/directory/shared/ldap/schema/syntaxCheckers/ACIItemSyntaxChecker.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,106 @@
+/*
+ *  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.schema.syntaxCheckers;
+
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.aci.ACIItemChecker;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.schema.SyntaxChecker;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A SyntaxChecker which verifies that a value is a valid ACIItem.
+ * 
+ *  
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ACIItemSyntaxChecker extends SyntaxChecker
+{
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( ACIItemSyntaxChecker.class );
+
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 1L;
+
+    /** An instance of ACI Item Checker */
+    private static final ACIItemChecker ACI_ITEM_CHECKER = new ACIItemChecker();
+
+    /**
+     * Creates a new instance of ACIItemSyntaxChecker
+     */
+    public ACIItemSyntaxChecker()
+    {
+        super( SchemaConstants.ACI_ITEM_SYNTAX );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isValidSyntax( Object value )
+    {
+        String strValue = null;
+
+        if ( value == null )
+        {
+            LOG.debug( "Syntax invalid for '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 )
+        {
+            LOG.debug( "Syntax invalid for '{}'", value );
+            return false;
+        }
+
+        try
+        {
+            synchronized( ACI_ITEM_CHECKER )
+            {
+                ACI_ITEM_CHECKER.parse( strValue );
+            }
+            
+            LOG.debug( "Syntax valid for '{}'", value );
+            return true;
+        }
+        catch ( ParseException pe )
+        {
+            LOG.debug( "Syntax invalid for '{}'", value );
+            return false;
+        }
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemChekerTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemChekerTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemChekerTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemChekerTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,312 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.fail;
+
+import java.text.ParseException;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class for ACIItem checker (wrapper).
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ACIItemChekerTest
+{
+
+    /** the ACIItem checker wrapper */
+    ACIItemChecker checker;
+
+
+    /**
+     * Creates a ACIItemParserTest instance.
+     */
+    public ACIItemChekerTest()
+    {
+        super();
+        checker = new ACIItemChecker();
+    }
+
+
+    /**
+     * Tests the checker with an ACIItem of ItemFirst main component.
+     */
+    @Test
+    public void testItemFirst() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { entry  , attributeType { 1.2.3    , ou }  , "
+            + " attributeValue { ou=people  , cn=Ersin  }  , rangeOfValues (cn=ErsinEr) , "
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        checker.parse( spec );
+    }
+
+
+    /**
+     * Tests the checker with an ACIItem of UserFirst main component.
+     */
+    @Test
+    public void testUserFirst() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testAllowAddAllUsers() throws Exception
+    {
+        String spec = "{ identificationTag \"addAci\", " + "precedence 14, " + "authenticationLevel none, "
+            + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
+            + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testCombo() throws Exception
+    {
+        String spec = "{ identificationTag \"addAci\", " + "precedence 14, " + "authenticationLevel none, "
+            + "itemOrUserFirst userFirst: { " + "userClasses { allUsers, name { \"ou=blah\" } }, "
+            + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testOrderOfProtectedItemsDoesNotMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testOrderOfUserClassesDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  name { \"ou=people,cn=ersin\" }, allUsers, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testItemPermissionComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { grantsAndDenials  {  denyCompare  , grantModify }, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testUserPermissionComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { grantsAndDenials { grantBrowse }, protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  } } }  }   ";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testOrderOfMainACIComponentsDoesNotMatter() throws Exception
+    {
+        String spec = "{   itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }, "
+            + " identificationTag \"id2\"   , authenticationLevel none, precedence 14 }   ";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testRestrictedValueComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\"}, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , "
+            + "maxValueCount { { type 10.11.12, maxCount 10 }, { maxCount 20, type 11.12.13  } } "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        checker.parse( spec );
+    }
+
+
+    @Test
+    public void testMaxValueCountComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , "
+            + "restrictedBy { { type 10.11.12, valuesIn ou }, { valuesIn cn, type 11.12.13  } } "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        checker.parse( spec );
+    }
+
+
+    /**
+     * Test case for DIRSERVER-891
+     */
+    @Test
+    public void testInvalidAttributeValue()
+    {
+        String spec;
+        
+        // no name-value-pair
+        spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue { must_be_a_name_value_pair } , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } }, userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ minimum 7, maximum 9, base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + " maximum   2, minimum  1 } } }  }  }   ";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, invalid protected item 'attributeValue { must_be_a_name_value_pair }'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        // no name-value-pair
+        spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue { x=y,m=n,k=l,x } , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } }, userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ minimum 7, maximum 9, base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + " maximum   2, minimum  1 } } }  }  }   ";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, invalid protected item 'attributeValue { must_be_a_name_value_pair }'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+    }
+    
+    
+    /**
+     * Test case for DIRSERVER-891
+     */
+    @Test
+    public void testIncomplete()
+    {
+        String spec;
+        
+        spec = "{ }";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\" }";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\", precedence 14 } ";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\", precedence 14, authenticationLevel none } ";
+        try
+        {
+            checker.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,578 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.text.ParseException;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Unit tests class for ACIItem parser (wrapper).
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ACIItemParserTest
+{
+
+    /** the ACIItem parser wrapper */
+    ACIItemParser parser;
+
+
+    /**
+     * Creates a ACIItemParserTest instance.
+     */
+    public ACIItemParserTest()
+    {
+        super();
+        parser = new ACIItemParser( null );
+    }
+
+
+    private void checkItemToString( String spec, ACIItem item ) throws Exception
+    {
+        // try to parse the result of item.toString() again
+        parser.parse( item.toString() );
+    }
+
+
+    /**
+     * Tests the parser with a rangeOfValues with a nested filter.
+     */
+    @Test
+    public void testRangeOfValues() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  "
+            + "{ rangeOfValues (&(&(|(|(cn=ccc)(!(cn=ddd))(&(cn=aaa)(cn=bbb)))))) " + "}  , itemPermissions {  } } }";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+        
+        
+        spec = " { identificationTag \"id8\", precedence 0, authenticationLevel simple "
+            + ", itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { "
+            + " { protectedItems { rangeOfValues (&(cn=test)(sn=test)) }, grantsAndDenials { grantAdd } }, "
+            + "{ protectedItems { rangeOfValues (|(!(cn=aaa))(sn=bbb)) }, grantsAndDenials { grantAdd } } "
+            + " } } }";
+        
+        item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    /**
+     * Tests the parser with an ACIItem of ItemFirst main component.
+     */
+    @Test
+    public void testItemFirst() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { entry  , attributeType { 1.2.3    , ou }  , "
+            + " attributeValue { ou=people  , cn=Ersin  }  , rangeOfValues (cn=ErsinEr) , "
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    /**
+     * Tests the parser with an ACIItem of UserFirst main component.
+     */
+    @Test 
+    public void testUserFirst() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testAllowAddAllUsers() throws Exception
+    {
+        String spec = "{ identificationTag \"addAci\", " + "precedence 14, " + "authenticationLevel none, "
+            + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
+            + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testCombo() throws Exception
+    {
+        String spec = "{ identificationTag \"addAci\", " + "precedence 14, " + "authenticationLevel none, "
+            + "itemOrUserFirst userFirst: { " + "userClasses { allUsers, name { \"ou=blah\" } }, "
+            + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testOrderOfProtectedItemsDoesNotMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testOrderOfUserClassesDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  name { \"ou=people,cn=ersin\" }, allUsers, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testOrderOfProtectedItemsDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testItemFirstOrderOfProtectedItemsDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testOrderOfUserClassesDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  name { \"ou=people,cn=ersin\" }, allUsers, allUsers, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testUserFirstOrderOfUserClassesDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testItemPermissionComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { grantsAndDenials  {  denyCompare  , grantModify }, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testItemPermissionComponentsOrderDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = " {  identificationTag  \"id1\" , precedence 114  , authenticationLevel simple  , "
+            + "itemOrUserFirst itemFirst  :{ protectedItems  { attributeType { 1.2.3    , ou }, entry , "
+            + " rangeOfValues (cn=ErsinEr) , attributeValue { ou=people  , cn=Ersin  },"
+            + "classes and : { item: xyz , or:{item:X,item:Y}   }}  , "
+            + "itemPermissions { { userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }, grantsAndDenials  {  denyCompare  , grantModify }, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   },"
+            + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
+            + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testItemPermissionComponentsOrderDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testUserPermissionComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { grantsAndDenials { grantBrowse }, protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testUserPermissionComponentsOrderDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { grantsAndDenials { grantBrowse }, grantsAndDenials { grantBrowse }, protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  } } }  }   ";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testUserPermissionComponentsOrderDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testOrderOfMainACIComponentsDoesNotMatter() throws Exception
+    {
+        String spec = "{   itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }, "
+            + " identificationTag \"id2\"   , authenticationLevel none, precedence 14 }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testOrderOfMainACIComponentsDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = "{   itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }, "
+            + " identificationTag \"id2\"   , authenticationLevel none, authenticationLevel simple, precedence 14 }   ";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testOrderOfMainACIComponentsDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testOrderOfMainACIComponentsDoesNotMatterButMissingsMatter() throws Exception
+    {
+        String spec = "{   itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }, "
+            + " identificationTag \"id2\"   , precedence 14 }   ";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testOrderOfMainACIComponentsDoesNotMatterButMissingsMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testGrantAndDenialBitsOrderDoesNotMatterButDuplicatesMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers }  , "
+            + "userPermissions { { protectedItems{ entry  }  , grantsAndDenials { grantBrowse, grantInvoke, denyAdd, grantBrowse } } } }  }";
+
+        try
+        {
+            parser.parse( spec );
+            fail( "testGrantAndDenialBitsOrderDoesNotMatterButDuplicatesMatter() should not have run this line." );
+        }
+        catch ( ParseException e )
+        {
+            assertNotNull( e );
+        }
+    }
+
+
+    @Test 
+    public void testMaxValueCountComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\"}, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , "
+            + "maxValueCount { { type 10.11.12, maxCount 10 }, { maxCount 20, type 11.12.13  } } "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testRestrictedValueComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , "
+            + "restrictedBy { { type 10.11.12, valuesIn ou }, { valuesIn cn, type 11.12.13  } } "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    @Test 
+    public void testMaxImmSubComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , maxImmSub 5 "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+        
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+    
+    
+    /**
+     * Test case for DIRSERVER-891
+     */
+    @Test 
+    public void testInvalidAttributeValue()
+    {
+        String spec;
+        
+        // no name-value-pair
+        spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue { must_be_a_name_value_pair } , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } }, userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ minimum 7, maximum 9, base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + " maximum   2, minimum  1 } } }  }  }   ";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, invalid protected item 'attributeValue { must_be_a_name_value_pair }'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        // no name-value-pair
+        spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue { x=y,m=n,k=l,x } , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } }, userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ minimum 7, maximum 9, base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + " maximum   2, minimum  1 } } }  }  }   ";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, invalid protected item 'attributeValue { x=y,m=n,k=l,x }'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+    }
+    
+    @Test 
+    public void testUserClassParentOfEntry() throws Exception
+    {
+        String spec = "{ identificationTag \"id\"   , precedence 10, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  parentOfEntry  , name { \"cn=ersin,ou=people\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
+            + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
+            + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+
+
+    /**
+     * Test case for DIRSTUDIO-440
+     */
+    @Test 
+    public void testPrecedenceOfUserFirst() throws Exception
+    {
+        String spec = "{ identificationTag \"test\", precedence 14, authenticationLevel simple, "
+            + "itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { "
+            + "precedence 1, protectedItems { attributeType { userPassword } }, grantsAndDenials "
+            + "{ denyRead, denyReturnDN, denyBrowse } }, { precedence 2, protectedItems "
+            + "{ entry, allUserAttributeTypesAndValues }, grantsAndDenials "
+            + "{ grantReturnDN, grantRead, grantBrowse } } } } }";
+
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+
+        UserFirstACIItem userFirstItem = ( UserFirstACIItem ) item;
+        int aciPrecedence = userFirstItem.getPrecedence();
+        assertEquals( 14, aciPrecedence );
+        for ( UserPermission permission : userFirstItem.getUserPermission() )
+        {
+            int precedence = permission.getPrecedence();
+            if ( precedence == 1 )
+            {
+                assertEquals( 1, precedence );
+            }
+            else if ( precedence == 2 )
+            {
+                assertEquals( 2, precedence );
+            }
+            else
+            {
+                fail( "Got precedence " + precedence + ", expected precedence 1 or 2." );
+            }
+        }
+    }
+
+
+    /**
+     * Test case for DIRSERVER-891
+     */
+    @Test 
+    public void testIncomplete()
+    {
+        String spec;
+        
+        spec = "{ }";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\" }";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\", precedence 14 } ";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+        
+        spec = "{ identificationTag \"id2\", precedence 14, authenticationLevel none } ";
+        try
+        {
+            parser.parse( spec );
+            fail("Expected ParseException, ACIItem is incomplete'");
+        }
+        catch ( ParseException e )
+        {
+            // Expected
+        }
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AllAttributeValuesTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AllAttributeValuesTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AllAttributeValuesTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AllAttributeValuesTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,139 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.protectedItem.AllAttributeValuesItem;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.AllAttributeValues.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_AllAttributeValuesTest
+{
+    AllAttributeValuesItem allAttributeValuesA;
+    AllAttributeValuesItem allAttributeValuesACopy;
+    AllAttributeValuesItem allAttributeValuesB;
+    AllAttributeValuesItem allAttributeValuesC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+        Set<String> colA = new HashSet<String>();
+        colA.add( "aa" );
+        colA.add( "bb" );
+        colA.add( "cc" );
+        Set<String> colB = new HashSet<String>();
+        colB.add( "aa" );
+        colB.add( "bb" );
+        colB.add( "cc" );
+        Set<String> colC = new HashSet<String>();
+        colC.add( "bb" );
+        colC.add( "cc" );
+        colC.add( "dd" );
+
+        allAttributeValuesA = new AllAttributeValuesItem( colA );
+        allAttributeValuesACopy = new AllAttributeValuesItem( colA );
+        allAttributeValuesB = new AllAttributeValuesItem( colB );
+        allAttributeValuesC = new AllAttributeValuesItem( colC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( allAttributeValuesA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( allAttributeValuesA, allAttributeValuesA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( allAttributeValuesA.hashCode(), allAttributeValuesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( allAttributeValuesA, allAttributeValuesACopy );
+        assertEquals( allAttributeValuesACopy, allAttributeValuesA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( allAttributeValuesA.hashCode(), allAttributeValuesACopy.hashCode() );
+        assertEquals( allAttributeValuesACopy.hashCode(), allAttributeValuesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( allAttributeValuesA, allAttributeValuesACopy );
+        assertEquals( allAttributeValuesACopy, allAttributeValuesB );
+        assertEquals( allAttributeValuesA, allAttributeValuesB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( allAttributeValuesA.hashCode(), allAttributeValuesACopy.hashCode() );
+        assertEquals( allAttributeValuesACopy.hashCode(), allAttributeValuesB.hashCode() );
+        assertEquals( allAttributeValuesA.hashCode(), allAttributeValuesB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( allAttributeValuesA.equals( allAttributeValuesC ) );
+        assertFalse( allAttributeValuesC.equals( allAttributeValuesA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeTypeTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeTypeTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeTypeTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeTypeTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,139 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.protectedItem.AttributeTypeItem;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.AttributeType.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_AttributeTypeTest
+{
+    AttributeTypeItem attributeTypeA;
+    AttributeTypeItem attributeTypeACopy;
+    AttributeTypeItem attributeTypeB;
+    AttributeTypeItem attributeTypeC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+        Set<String> colA = new HashSet<String>();
+        colA.add( "aa" );
+        colA.add( "bb" );
+        colA.add( "cc" );
+        Set<String> colB = new HashSet<String>();
+        colB.add( "aa" );
+        colB.add( "bb" );
+        colB.add( "cc" );
+        Set<String> colC = new HashSet<String>();
+        colC.add( "bb" );
+        colC.add( "cc" );
+        colC.add( "dd" );
+
+        attributeTypeA = new AttributeTypeItem( colA );
+        attributeTypeACopy = new AttributeTypeItem( colA );
+        attributeTypeB = new AttributeTypeItem( colB );
+        attributeTypeC = new AttributeTypeItem( colC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( attributeTypeA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( attributeTypeA, attributeTypeA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( attributeTypeA.hashCode(), attributeTypeA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( attributeTypeA, attributeTypeACopy );
+        assertEquals( attributeTypeACopy, attributeTypeA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( attributeTypeA.hashCode(), attributeTypeACopy.hashCode() );
+        assertEquals( attributeTypeACopy.hashCode(), attributeTypeA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( attributeTypeA, attributeTypeACopy );
+        assertEquals( attributeTypeACopy, attributeTypeB );
+        assertEquals( attributeTypeA, attributeTypeB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( attributeTypeA.hashCode(), attributeTypeACopy.hashCode() );
+        assertEquals( attributeTypeACopy.hashCode(), attributeTypeB.hashCode() );
+        assertEquals( attributeTypeA.hashCode(), attributeTypeB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( attributeTypeA.equals( attributeTypeC ) );
+        assertFalse( attributeTypeC.equals( attributeTypeA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeValueTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeValueTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeValueTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_AttributeValueTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,151 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.protectedItem.AttributeValueItem;
+import org.apache.directory.shared.ldap.entry.DefaultEntryAttribute;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.AttributeValue.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_AttributeValueTest
+{
+    AttributeValueItem attributeValueA;
+    AttributeValueItem attributeValueACopy;
+    AttributeValueItem attributeValueB;
+    AttributeValueItem attributeValueC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+
+        EntryAttribute attrA = new DefaultEntryAttribute( "aa" );
+        attrA.add( "aa" );
+        EntryAttribute attrB = new DefaultEntryAttribute( "bb" );
+        attrB.add( "bb" );
+        EntryAttribute attrC = new DefaultEntryAttribute( "cc" );
+        attrC.add( "cc" );
+        EntryAttribute attrD = new DefaultEntryAttribute( "dd" );
+        attrD.add( "dd" );
+
+        Set<EntryAttribute> colA = new HashSet<EntryAttribute>();
+        colA.add( attrA );
+        colA.add( attrB );
+        colA.add( attrC );
+        Set<EntryAttribute> colB = new HashSet<EntryAttribute>();
+        colB.add( attrA );
+        colB.add( attrB );
+        colB.add( attrC );
+        Set<EntryAttribute> colC = new HashSet<EntryAttribute>();
+        colC.add( attrB );
+        colC.add( attrC );
+        colC.add( attrD );
+
+        attributeValueA = new AttributeValueItem( colA );
+        attributeValueACopy = new AttributeValueItem( colA );
+        attributeValueB = new AttributeValueItem( colB );
+        attributeValueC = new AttributeValueItem( colC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( attributeValueA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( attributeValueA, attributeValueA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( attributeValueA.hashCode(), attributeValueA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( attributeValueA, attributeValueACopy );
+        assertEquals( attributeValueACopy, attributeValueA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( attributeValueA.hashCode(), attributeValueACopy.hashCode() );
+        assertEquals( attributeValueACopy.hashCode(), attributeValueA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( attributeValueA, attributeValueACopy );
+        assertEquals( attributeValueACopy, attributeValueB );
+        assertEquals( attributeValueA, attributeValueB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( attributeValueA.hashCode(), attributeValueACopy.hashCode() );
+        assertEquals( attributeValueACopy.hashCode(), attributeValueB.hashCode() );
+        assertEquals( attributeValueA.hashCode(), attributeValueB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( attributeValueA.equals( attributeValueC ) );
+        assertFalse( attributeValueC.equals( attributeValueA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_ClassesTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_ClassesTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_ClassesTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_ClassesTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,128 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.Classes;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.Classes.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_ClassesTest
+{
+    Classes classesA;
+    Classes classesACopy;
+    Classes classesB;
+    Classes classesC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+        ExprNode filterA = FilterParser.parse( "(&(cn=test)(sn=test))" );
+        ExprNode filterB = FilterParser.parse( "(&(cn=test)(sn=test))" );
+        ExprNode filterC = FilterParser.parse( "(&(cn=sample)(sn=sample))" );
+        classesA = new Classes( filterA );
+        classesACopy = new Classes( filterA );
+        classesB = new Classes( filterB );
+        classesC = new Classes( filterC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( classesA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( classesA, classesA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( classesA.hashCode(), classesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( classesA, classesACopy );
+        assertEquals( classesACopy, classesA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( classesA.hashCode(), classesACopy.hashCode() );
+        assertEquals( classesACopy.hashCode(), classesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( classesA, classesACopy );
+        assertEquals( classesACopy, classesB );
+        assertEquals( classesA, classesB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( classesA.hashCode(), classesACopy.hashCode() );
+        assertEquals( classesACopy.hashCode(), classesB.hashCode() );
+        assertEquals( classesA.hashCode(), classesB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( classesA.equals( classesC ) );
+        assertFalse( classesC.equals( classesA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxImmSubTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxImmSubTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxImmSubTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxImmSubTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,128 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.MaxImmSub;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.MaxImmSub.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_MaxImmSubTest
+{
+    MaxImmSub maxValueCountA;
+    MaxImmSub maxValueCountACopy;
+    MaxImmSub maxValueCountB;
+    MaxImmSub maxValueCountC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+
+        MaxImmSub misA = new MaxImmSub( 1 );
+        MaxImmSub misB = new MaxImmSub( 1 );
+        MaxImmSub misC = new MaxImmSub( 2 );
+
+        maxValueCountA = misA;
+        maxValueCountACopy = misA;
+        maxValueCountB = misB;
+        maxValueCountC = misC;
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( maxValueCountA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountACopy );
+        assertEquals( maxValueCountACopy, maxValueCountA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountACopy.hashCode() );
+        assertEquals( maxValueCountACopy.hashCode(), maxValueCountA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountACopy );
+        assertEquals( maxValueCountACopy, maxValueCountB );
+        assertEquals( maxValueCountA, maxValueCountB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountACopy.hashCode() );
+        assertEquals( maxValueCountACopy.hashCode(), maxValueCountB.hashCode() );
+        assertEquals( maxValueCountA.hashCode(), maxValueCountB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( maxValueCountA.equals( maxValueCountC ) );
+        assertFalse( maxValueCountC.equals( maxValueCountA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxValueCountTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxValueCountTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxValueCountTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_MaxValueCountTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,146 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.MaxValueCount;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.MaxValueCountItem;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.MaxValueCount.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_MaxValueCountTest
+{
+    MaxValueCount maxValueCountA;
+    MaxValueCount maxValueCountACopy;
+    MaxValueCount maxValueCountB;
+    MaxValueCount maxValueCountC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+
+        MaxValueCountItem mvciA = new MaxValueCountItem( "aa", 1 );
+        MaxValueCountItem mvciB = new MaxValueCountItem( "bb", 2 );
+        MaxValueCountItem mvciC = new MaxValueCountItem( "cc", 3 );
+        MaxValueCountItem mvciD = new MaxValueCountItem( "dd", 4 );
+
+        Set<MaxValueCountItem> colA = new HashSet<MaxValueCountItem>();
+        colA.add( mvciA );
+        colA.add( mvciB );
+        colA.add( mvciC );
+        Set<MaxValueCountItem> colB = new HashSet<MaxValueCountItem>();
+        colB.add( mvciA );
+        colB.add( mvciB );
+        colB.add( mvciC );
+        Set<MaxValueCountItem> colC = new HashSet<MaxValueCountItem>();
+        colC.add( mvciB );
+        colC.add( mvciC );
+        colC.add( mvciD );
+
+        maxValueCountA = new MaxValueCount( colA );
+        maxValueCountACopy = new MaxValueCount( colA );
+        maxValueCountB = new MaxValueCount( colB );
+        maxValueCountC = new MaxValueCount( colC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( maxValueCountA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountACopy );
+        assertEquals( maxValueCountACopy, maxValueCountA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountACopy.hashCode() );
+        assertEquals( maxValueCountACopy.hashCode(), maxValueCountA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( maxValueCountA, maxValueCountACopy );
+        assertEquals( maxValueCountACopy, maxValueCountB );
+        assertEquals( maxValueCountA, maxValueCountB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( maxValueCountA.hashCode(), maxValueCountACopy.hashCode() );
+        assertEquals( maxValueCountACopy.hashCode(), maxValueCountB.hashCode() );
+        assertEquals( maxValueCountA.hashCode(), maxValueCountB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( maxValueCountA.equals( maxValueCountC ) );
+        assertFalse( maxValueCountC.equals( maxValueCountA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RangeOfValuesTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RangeOfValuesTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RangeOfValuesTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RangeOfValuesTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,130 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.RangeOfValues;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.RangeOfValues.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_RangeOfValuesTest
+{
+    RangeOfValues rangeOfValuesA;
+    RangeOfValues rangeOfValuesACopy;
+    RangeOfValues rangeOfValuesB;
+    RangeOfValues rangeOfValuesC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+
+        ExprNode filterA = FilterParser.parse( "(&(cn=test)(sn=test))" );
+        ExprNode filterB = FilterParser.parse( "(&(cn=test)(sn=test))" );
+        ExprNode filterC = FilterParser.parse( "(&(cn=sample)(sn=sample))" );
+
+        rangeOfValuesA = new RangeOfValues( filterA );
+        rangeOfValuesACopy = new RangeOfValues( filterA );
+        rangeOfValuesB = new RangeOfValues( filterB );
+        rangeOfValuesC = new RangeOfValues( filterC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( rangeOfValuesA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( rangeOfValuesA, rangeOfValuesA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( rangeOfValuesA.hashCode(), rangeOfValuesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( rangeOfValuesA, rangeOfValuesACopy );
+        assertEquals( rangeOfValuesACopy, rangeOfValuesA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( rangeOfValuesA.hashCode(), rangeOfValuesACopy.hashCode() );
+        assertEquals( rangeOfValuesACopy.hashCode(), rangeOfValuesA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( rangeOfValuesA, rangeOfValuesACopy );
+        assertEquals( rangeOfValuesACopy, rangeOfValuesB );
+        assertEquals( rangeOfValuesA, rangeOfValuesB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( rangeOfValuesA.hashCode(), rangeOfValuesACopy.hashCode() );
+        assertEquals( rangeOfValuesACopy.hashCode(), rangeOfValuesB.hashCode() );
+        assertEquals( rangeOfValuesA.hashCode(), rangeOfValuesB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( rangeOfValuesA.equals( rangeOfValuesC ) );
+        assertFalse( rangeOfValuesC.equals( rangeOfValuesA ) );
+    }
+}

Added: directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RestrictedByTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RestrictedByTest.java?rev=959029&view=auto
==============================================================================
--- directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RestrictedByTest.java (added)
+++ directory/shared/trunk/ldap-aci/src/test/java/org/apache/directory/shared/ldap/aci/ProtectedItem_RestrictedByTest.java Tue Jun 29 16:56:07 2010
@@ -0,0 +1,145 @@
+/*
+ *  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.aci;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.junit.tools.Concurrent;
+import org.apache.directory.junit.tools.ConcurrentJunitRunner;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.RestrictedBy;
+import org.apache.directory.shared.ldap.aci.ProtectedItem.RestrictedByItem;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Unit tests class ProtectedItem.RestrictedBy.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrent()
+public class ProtectedItem_RestrictedByTest
+{
+    RestrictedBy restrictedByA;
+    RestrictedBy restrictedByACopy;
+    RestrictedBy restrictedByB;
+    RestrictedBy restrictedByC;
+
+
+    /**
+     * Initialize name instances
+     */
+    @Before
+    public void initNames() throws Exception
+    {
+        RestrictedByItem rbiA = new RestrictedByItem( "aa", "aa" );
+        RestrictedByItem rbiB = new RestrictedByItem( "bb", "bb" );
+        RestrictedByItem rbiC = new RestrictedByItem( "cc", "cc" );
+        RestrictedByItem rbiD = new RestrictedByItem( "dd", "dd" );
+
+        Set<RestrictedByItem> colA = new HashSet<RestrictedByItem>();
+        colA.add( rbiA );
+        colA.add( rbiB );
+        colA.add( rbiC );
+        Set<RestrictedByItem> colB = new HashSet<RestrictedByItem>();
+        colB.add( rbiA );
+        colB.add( rbiB );
+        colB.add( rbiC );
+        Set<RestrictedByItem> colC = new HashSet<RestrictedByItem>();
+        colC.add( rbiB );
+        colC.add( rbiC );
+        colC.add( rbiD );
+
+        restrictedByA = new RestrictedBy( colA );
+        restrictedByACopy = new RestrictedBy( colA );
+        restrictedByB = new RestrictedBy( colB );
+        restrictedByC = new RestrictedBy( colC );
+    }
+
+
+    @Test
+    public void testEqualsNull() throws Exception
+    {
+        assertFalse( restrictedByA.equals( null ) );
+    }
+
+
+    @Test
+    public void testEqualsReflexive() throws Exception
+    {
+        assertEquals( restrictedByA, restrictedByA );
+    }
+
+
+    @Test
+    public void testHashCodeReflexive() throws Exception
+    {
+        assertEquals( restrictedByA.hashCode(), restrictedByA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsSymmetric() throws Exception
+    {
+        assertEquals( restrictedByA, restrictedByACopy );
+        assertEquals( restrictedByACopy, restrictedByA );
+    }
+
+
+    @Test
+    public void testHashCodeSymmetric() throws Exception
+    {
+        assertEquals( restrictedByA.hashCode(), restrictedByACopy.hashCode() );
+        assertEquals( restrictedByACopy.hashCode(), restrictedByA.hashCode() );
+    }
+
+
+    @Test
+    public void testEqualsTransitive() throws Exception
+    {
+        assertEquals( restrictedByA, restrictedByACopy );
+        assertEquals( restrictedByACopy, restrictedByB );
+        assertEquals( restrictedByA, restrictedByB );
+    }
+
+
+    @Test
+    public void testHashCodeTransitive() throws Exception
+    {
+        assertEquals( restrictedByA.hashCode(), restrictedByACopy.hashCode() );
+        assertEquals( restrictedByACopy.hashCode(), restrictedByB.hashCode() );
+        assertEquals( restrictedByA.hashCode(), restrictedByB.hashCode() );
+    }
+
+
+    @Test
+    public void testNotEqualDiffValue() throws Exception
+    {
+        assertFalse( restrictedByA.equals( restrictedByC ) );
+        assertFalse( restrictedByC.equals( restrictedByA ) );
+    }
+}