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 2007/01/24 19:31:35 UTC

svn commit: r499513 - in /directory/apacheds/trunk/core/src: main/java/org/apache/directory/server/core/authz/ main/java/org/apache/directory/server/core/collective/ main/java/org/apache/directory/server/core/configuration/ main/java/org/apache/directo...

Author: elecharny
Date: Wed Jan 24 10:31:33 2007
New Revision: 499513

URL: http://svn.apache.org/viewvc?view=rev&rev=499513
Log:
Porting fix from ADS 1.0.1 to 1.5 : fixing DIRSERVER-758 and some problems with referrals.

Modified:
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/TupleCache.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/MutablePartitionConfiguration.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/PartitionConfiguration.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/partition/DefaultPartitionNexus.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/referral/ReferralService.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryService.java
    directory/apacheds/trunk/core/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java Wed Jan 24 10:31:33 2007
@@ -35,6 +35,7 @@
 import org.apache.directory.shared.ldap.filter.SimpleNode;
 import org.apache.directory.shared.ldap.message.ModificationItemImpl;
 import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -186,12 +187,12 @@
             return null;
         }
 
-        if ( oc.contains( GROUPOFNAMES_OC ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, GROUPOFNAMES_OC ) )
         {
             return entry.get( MEMBER_ATTR );
         }
 
-        if ( oc.contains( GROUPOFUNIQUENAMES_OC ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, GROUPOFUNIQUENAMES_OC ) )
         {
             return entry.get( UNIQUEMEMBER_ATTR );
         }
@@ -358,13 +359,13 @@
         String memberAttrId = null;
         Attribute oc = entry.get( OC_ATTR );
 
-        if ( oc.contains( GROUPOFNAMES_OC ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, GROUPOFNAMES_OC ) )
         {
             members = entry.get( MEMBER_ATTR );
             memberAttrId = MEMBER_ATTR;
         }
 
-        if ( oc.contains( GROUPOFUNIQUENAMES_OC ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, GROUPOFUNIQUENAMES_OC ) )
         {
             members = entry.get( UNIQUEMEMBER_ATTR );
             memberAttrId = UNIQUEMEMBER_ATTR;

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/TupleCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/TupleCache.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/TupleCache.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/TupleCache.java Wed Jan 24 10:31:33 2007
@@ -52,6 +52,7 @@
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -153,17 +154,22 @@
     {
         // only do something if the entry contains prescriptiveACI
         Attribute aci = entry.get( ACI_ATTR );
-        if ( aci == null && entry.get( OC_ATTR ).contains( ACSUBENTRY_OC ) )
-        {
-            // should not be necessary because of schema interceptor but schema checking
-            // can be turned off and in this case we must protect against being able to
-            // add access control information to anything other than an AC subentry
-            throw new LdapSchemaViolationException( "", ResultCodeEnum.OBJECT_CLASS_VIOLATION );
-        }
-        else if ( aci == null )
+
+        if ( aci == null )
         {
-            return false;
+            if ( AttributeUtils.containsValueCaseIgnore( entry.get( OC_ATTR ), ACSUBENTRY_OC ) )
+            {
+                // should not be necessary because of schema interceptor but schema checking
+                // can be turned off and in this case we must protect against being able to
+                // add access control information to anything other than an AC subentry
+                throw new LdapSchemaViolationException( "", ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+            }
+            else
+            {
+                return false;
+            }
         }
+        
         return true;
     }
 

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java Wed Jan 24 10:31:33 2007
@@ -34,6 +34,7 @@
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.SchemaUtils;
+import org.apache.directory.shared.ldap.util.AttributeUtils;
 
 
 /**
@@ -56,7 +57,8 @@
     public void checkAdd( LdapDN normName, Attributes entry ) throws LdapSchemaViolationException, NamingException
     {
         Attribute objectClass = entry.get( "objectClass" );
-        if ( objectClass.contains( "collectiveAttributeSubentry" ) )
+        
+        if ( AttributeUtils.containsValueCaseIgnore( objectClass, "collectiveAttributeSubentry" ) )
         {
             return;
         }
@@ -94,7 +96,7 @@
         Attributes targetEntry = SchemaUtils.getTargetEntry( mods, originalEntry );
         Attribute targetObjectClasses = targetEntry.get( "objectClass" );
         
-        if ( targetObjectClasses.contains( "collectiveAttributeSubentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( targetObjectClasses, "collectiveAttributeSubentry" ) )
         {
             return;
         }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/MutablePartitionConfiguration.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/MutablePartitionConfiguration.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/MutablePartitionConfiguration.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/MutablePartitionConfiguration.java Wed Jan 24 10:31:33 2007
@@ -51,7 +51,7 @@
     }
 
 
-    public void setIndexedAttributes( Set indexedAttributes )
+    public void setIndexedAttributes( Set<String> indexedAttributes )
     {
         super.setIndexedAttributes( indexedAttributes );
     }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/PartitionConfiguration.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/PartitionConfiguration.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/PartitionConfiguration.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/configuration/PartitionConfiguration.java Wed Jan 24 10:31:33 2007
@@ -61,7 +61,7 @@
      */
     protected PartitionConfiguration()
     {
-        setIndexedAttributes( new HashSet() );
+        setIndexedAttributes( new HashSet<String>() );
     }
 
 
@@ -99,7 +99,7 @@
     /**
      * Sets the set of attribute type strings to create an index on.
      */
-    protected void setIndexedAttributes( Set indexedAttributes )
+    protected void setIndexedAttributes( Set<String> indexedAttributes )
     {
         this.indexedAttributes = indexedAttributes;
     }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/partition/DefaultPartitionNexus.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/partition/DefaultPartitionNexus.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/partition/DefaultPartitionNexus.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/partition/DefaultPartitionNexus.java Wed Jan 24 10:31:33 2007
@@ -282,9 +282,9 @@
             Set<String> indexOids = new HashSet<String>();
             OidRegistry registry = factoryCfg.getRegistries().getOidRegistry();
             
-            for ( Object index : indices )
+            for ( String index : indices )
             {
-                indexOids.add( registry.getOid( index.toString() ) );
+                indexOids.add( registry.getOid( index ) );
             }
             
             if ( ! indexOids.contains( Oid.ALIAS ) )

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/referral/ReferralService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/referral/ReferralService.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/referral/ReferralService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/referral/ReferralService.java Wed Jan 24 10:31:33 2007
@@ -181,7 +181,8 @@
     public void doReferralException( LdapDN farthest, LdapDN targetUpdn, Attribute refs ) throws NamingException
     {
         // handle referral here
-        List list = new ArrayList( refs.size() );
+        List<String> list = new ArrayList<String>( refs.size() );
+        
         for ( int ii = 0; ii < refs.size(); ii++ )
         {
             String val = ( String ) refs.get( ii );
@@ -244,9 +245,10 @@
                 buf.append( ldapUrl.getPort() );
             }
             buf.append( "/" );
-            buf.append( urlDn.getUpName() );
+            buf.append( LdapURL.urlEncode( urlDn.getUpName(), false ) );
             list.add( buf.toString() );
         }
+        
         LdapReferralException lre = new LdapReferralException( list );
         throw lre;
     }
@@ -1007,7 +1009,7 @@
                 buf.append( ldapUrl.getPort() );
             }
             buf.append( "/" );
-            buf.append( ldapUrl.getDn() );
+            buf.append( LdapURL.urlEncode( ldapUrl.getDn().getUpName(), false ) );
             buf.append( "??" );
 
             switch ( scope )
@@ -1078,7 +1080,7 @@
                 buf.append( ldapUrl.getPort() );
             }
             buf.append( "/" );
-            buf.append( urlDn.getUpName() );
+            buf.append( LdapURL.urlEncode( urlDn.getUpName(), false ) );
             buf.append( "??" );
 
             switch ( scope )

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java Wed Jan 24 10:31:33 2007
@@ -26,6 +26,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 import java.util.Set;
 
 import javax.naming.NamingEnumeration;
@@ -54,7 +55,6 @@
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeIdentifierException;
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
-import org.apache.directory.shared.ldap.exception.LdapNamingException;
 import org.apache.directory.shared.ldap.exception.LdapNoSuchAttributeException;
 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
 import org.apache.directory.shared.ldap.filter.AssertionEnum;
@@ -75,6 +75,7 @@
 import org.apache.directory.shared.ldap.schema.ObjectClass;
 import org.apache.directory.shared.ldap.schema.SchemaUtils;
 import org.apache.directory.shared.ldap.schema.Syntax;
+import org.apache.directory.shared.ldap.schema.UsageEnum;
 import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.apache.directory.shared.ldap.util.DateUtils;
 import org.apache.directory.shared.ldap.util.SingletonEnumeration;
@@ -94,7 +95,6 @@
 {
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
     private static final String BINARY_KEY = "java.naming.ldap.attributes.binary";
-    private static final AttributeType[] EMPTY_ATTRIBUTE_TYPE_ARRAY = new AttributeType[0];
 
     /** The LoggerFactory used by this Interceptor */
     private static Logger log = LoggerFactory.getLogger( SchemaService.class );
@@ -138,6 +138,17 @@
     // the base DN (normalized) of the schema partition
     private LdapDN schemaBaseDN;
     
+    /** A map used to store all the objectClasses superiors */
+    private Map superiors;
+
+    /** A map used to store all the objectClasses may attributes */
+    private Map allMay;
+
+    /** A map used to store all the objectClasses must */
+    private Map allMust;
+
+    /** A map used to store all the objectClasses allowed attributes (may + must) */
+    private Map allowed;
 
     /**
      * Creates a schema service interceptor.
@@ -175,8 +186,173 @@
         String subschemaSubentry = ( String ) nexus.getRootDSE().get( "subschemaSubentry" ).get();
         subschemaSubentryDn = new LdapDN( subschemaSubentry );
         subschemaSubentryDn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
+
+        computeSuperiors();
+
+        if ( IS_DEBUG )
+        {
+            log.debug( "SchemaService Initialized !" );
+        }
+    }
+
+    /**
+     * Compute the MUST attributes for an objectClass. This method gather all the
+     * MUST from all the objectClass and its superors.
+     */
+    private void computeMustAttributes( ObjectClass objectClass, Set atSeen ) throws NamingException
+    {
+        List parents = (List)superiors.get( objectClass.getOid() );
+
+        List mustList = new ArrayList();
+        List allowedList = new ArrayList();
+        Set mustSeen = new HashSet();
+
+        allMust.put( objectClass.getOid(), mustList );
+        allowed.put( objectClass.getOid(), allowedList );
+
+        Iterator objectClasses = parents.iterator();
+
+        while ( objectClasses.hasNext() )
+        {
+            ObjectClass parent = (ObjectClass)objectClasses.next();
+
+            AttributeType[] mustParent = parent.getMustList();
+
+            if ( ( mustParent != null ) && ( mustParent.length != 0 ) )
+            {
+                for ( int i = 0; i < mustParent.length; i++ )
+                {
+                    AttributeType attributeType = mustParent[i];
+                    String oid = attributeType.getOid();
+
+                    if ( !mustSeen.contains( oid ) )
+                    {
+                        mustSeen.add(  oid  );
+                        mustList.add( attributeType );
+                        allowedList.add( attributeType );
+                        atSeen.add( attributeType.getOid() );
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Compute the MAY attributes for an objectClass. This method gather all the
+     * MAY from all the objectClass and its superors.
+     *
+     * The allowed attributes is also computed, it's the union of MUST and MAY
+     */
+    private void computeMayAttributes( ObjectClass objectClass, Set atSeen ) throws NamingException
+    {
+        List parents = (List)superiors.get( objectClass.getOid() );
+
+        List mayList = new ArrayList();
+        Set maySeen = new HashSet();
+        List allowedList = (List)allowed.get( objectClass.getOid() );
+
+
+        allMay.put( objectClass.getOid(), mayList );
+
+        Iterator objectClasses = parents.iterator();
+
+        while ( objectClasses.hasNext() )
+        {
+            ObjectClass parent = (ObjectClass)objectClasses.next();
+
+            AttributeType[] mustParent = parent.getMustList();
+
+            if ( ( mustParent != null ) && ( mustParent.length != 0 ) )
+            {
+                for ( int i = 0; i < mustParent.length; i++ )
+                {
+                    AttributeType attributeType = mustParent[i];
+                    String oid = attributeType.getOid();
+
+                    if ( !maySeen.contains( oid ) )
+                    {
+                        maySeen.add(  oid  );
+                        mayList.add( attributeType );
+
+                        if ( !atSeen.contains( oid ) )
+                        {
+                            allowedList.add( attributeType );
+                        }
+                    }
+                }
+            }
+        }
     }
 
+    /**
+     * Recursively compute all the superiors of an object class. For instance, considering
+     * 'inetOrgPerson', it's direct superior is 'organizationalPerson', which direct superior
+     * is 'Person', which direct superior is 'top'.
+     *
+     * As a result, we will gather all of these three ObjectClasses in 'inetOrgPerson' ObjectClasse
+     * superiors.
+     */
+    private void computeOCSuperiors( ObjectClass objectClass, List superiors, Set ocSeen ) throws NamingException
+    {
+        ObjectClass[] parents = objectClass.getSuperClasses();
+
+        // Loop on all the objectClass superiors
+        if ( ( parents != null ) && ( parents.length != 0 ) )
+        {
+            for ( int i = 0; i < parents.length; i++ )
+            {
+                ObjectClass parent = parents[i];
+
+                // Top is not added
+                if ( "top".equals( parent.getName() ) )
+                {
+                    continue;
+                }
+
+                // For each one, recurse
+                computeOCSuperiors( parent, superiors, ocSeen );
+
+                String oid = parents[i].getOid();
+
+                if ( !ocSeen.contains( oid ) )
+                {
+                    superiors.add( parent );
+                    ocSeen.add( oid );
+                }
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * Compute all ObjectClasses superiors, MAY and MUST attributes.
+     * @throws NamingException
+     */
+    private void computeSuperiors() throws NamingException
+    {
+        Iterator objectClasses = registries.getObjectClassRegistry().iterator();
+        superiors = new HashMap();
+        allMust = new HashMap();
+        allMay = new HashMap();
+        allowed = new HashMap();
+
+        while ( objectClasses.hasNext() )
+        {
+            List ocSuperiors = new ArrayList();
+
+            ObjectClass objectClass = (ObjectClass)objectClasses.next();
+            superiors.put( objectClass.getOid(), ocSuperiors );
+
+            computeOCSuperiors( objectClass, ocSuperiors, new HashSet() );
+
+            Set atSeen = new HashSet();
+            computeMustAttributes( objectClass, atSeen );
+            computeMayAttributes( objectClass, atSeen );
+
+            superiors.put( objectClass.getName(), ocSuperiors );
+        }
+    }
 
     /**
      * Check if an attribute stores binary values.
@@ -460,13 +636,13 @@
 
 
     /**
-     * 
+     * Search for an entry, using its DN. Binary attributes and ObjectClass attribute are removed.
      */
     public Attributes lookup( NextInterceptor nextInterceptor, LdapDN name ) throws NamingException
     {
         Attributes result = nextInterceptor.lookup( name );
         filterBinaryAttributes( result );
-        filterTop( result );
+        filterObjectClass( result );
         return result;
     }
 
@@ -482,11 +658,39 @@
         }
 
         filterBinaryAttributes( result );
-        filterTop( result );
+        // filterTop( result );
+        filterObjectClass( result );
+
         return result;
     }
 
 
+    private void getSuperiors( ObjectClass oc, Set ocSeen, List result ) throws NamingException
+    {
+        ObjectClass[] superiors = oc.getSuperClasses();
+
+        for ( int i = 0; i < superiors.length; i++ )
+        {
+            ObjectClass parent = superiors[i];
+
+            // Skip 'top'
+            if ( "top".equals( parent.getName() ) )
+            {
+                continue;
+            }
+
+            if ( !ocSeen.contains( parent.getOid() ) )
+            {
+                ocSeen.add( parent.getOid() );
+                result.add( parent );
+            }
+
+            // Recurse on the parent
+            getSuperiors( parent, ocSeen, result );
+        }
+
+    }
+
     /**
      * Checks to see if an attribute is required by as determined from an entry's
      * set of objectClass attribute values.
@@ -523,7 +727,6 @@
         return false;
     }
 
-
     /**
      * Checks to see if removing a set of attributes from an entry completely removes
      * that attribute's values.  If change has zero size then all attributes are
@@ -555,6 +758,7 @@
         return changedEntryAttr.size() == 0;
     }
 
+    
     /**
      * 
      * @param modOp
@@ -598,6 +802,104 @@
     }
 
 
+    private boolean getObjectClasses( Attribute objectClasses, List result ) throws NamingException
+    {
+        Set ocSeen = new HashSet();
+        ObjectClassRegistry registry = registries.getObjectClassRegistry();
+
+        // We must select all the ObjectClasses, except 'top',
+        // but including all the inherited ObjectClasses
+        NamingEnumeration ocs = objectClasses.getAll();
+        boolean hasExtensibleObject = false;
+
+
+        while ( ocs.hasMoreElements() )
+        {
+            String objectClassName = (String)ocs.nextElement();
+
+            if ( "top".equals( objectClassName ) )
+            {
+                continue;
+            }
+
+            if ( "extensibleObject".equalsIgnoreCase( objectClassName ) )
+            {
+                hasExtensibleObject = true;
+            }
+
+            ObjectClass oc = registry.lookup( objectClassName );
+
+            // Add all unseen objectclasses to the list, except 'top'
+            if ( !ocSeen.contains( oc.getOid() ) )
+            {
+                ocSeen.add( oc.getOid() );
+                result.add( oc );
+            }
+
+            // Find all current OC parents
+            getSuperiors( oc, ocSeen, result );
+        }
+
+        return hasExtensibleObject;
+    }
+
+    private Set getAllMust( NamingEnumeration objectClasses ) throws NamingException
+    {
+        Set must = new HashSet();
+
+        // Loop on all objectclasses
+        while ( objectClasses.hasMoreElements() )
+        {
+            String ocName = (String)objectClasses.nextElement();
+            ObjectClass oc = registries.getObjectClassRegistry().lookup( ocName );
+
+            AttributeType[] types = oc.getMustList();
+
+            // For each objectClass, loop on all MUST attributeTypes, if any
+            if ( ( types != null ) && ( types.length > 0 ) )
+            {
+                for ( int j = 0; j < types.length; j++ )
+                {
+                    String oid = types[j].getOid();
+
+                    must.add( oid );
+                }
+            }
+        }
+
+        return must;
+    }
+
+    private Set getAllAllowed( NamingEnumeration objectClasses, Set must ) throws NamingException
+    {
+        Set allowed = new HashSet( must );
+
+        // Add the 'ObjectClass' attribute ID
+        allowed.add( registries.getOidRegistry().getOid( "ObjectClass" ) );
+
+        // Loop on all objectclasses
+        while ( objectClasses.hasMoreElements() )
+        {
+            String ocName = (String)objectClasses.nextElement();
+            ObjectClass oc = registries.getObjectClassRegistry().lookup( ocName );
+
+            AttributeType[] types = oc.getMayList();
+
+            // For each objectClass, loop on all MUST attributeTypes, if any
+            if ( ( types != null ) && ( types.length > 0 ) )
+            {
+                for ( int j = 0; j < types.length; j++ )
+                {
+                    String oid = types[j].getOid();
+
+                    allowed.add( oid );
+                }
+            }
+        }
+
+        return allowed;
+    }
+
     /**
      * Given the objectClasses for an entry, this method adds missing ancestors 
      * in the hierarchy except for top which it removes.  This is used for this
@@ -607,46 +909,59 @@
      * @param objectClassAttr the objectClass attribute to modify
      * @throws NamingException if there are problems 
      */
-    public static void alterObjectClasses( Attribute objectClassAttr, ObjectClassRegistry registry )
-        throws NamingException
+    private void alterObjectClasses( Attribute objectClassAttr ) throws NamingException
     {
-        if ( !objectClassAttr.getID().equalsIgnoreCase( "objectClass" ) )
-        {
-            throw new LdapNamingException( "Expecting an objectClass attribute but got " + objectClassAttr.getID(),
-                ResultCodeEnum.OPERATIONS_ERROR );
-        }
-
         Set<String> objectClasses = new HashSet<String>();
-        for ( int ii = 0; ii < objectClassAttr.size(); ii++ )
-        {
-            String val = ( String ) objectClassAttr.get( ii );
-            if ( !val.equalsIgnoreCase( "top" ) )
-            {
-                objectClasses.add( val.toLowerCase() );
-            }
-        }
 
-        for ( int ii = 0; ii < objectClassAttr.size(); ii++ )
+        // Init the objectClass list with 'top'
+        objectClasses.add( "top" );
+        
+        // Construct the new list of ObjectClasses
+        NamingEnumeration ocList = objectClassAttr.getAll();
+
+        while ( ocList.hasMoreElements() )
         {
-            String val = ( String ) objectClassAttr.get( ii );
-            if ( val.equalsIgnoreCase( "top" ) )
+            String ocName = ( String ) ocList.nextElement();
+
+            if ( !ocName.equalsIgnoreCase( "top" ) )
             {
-                objectClassAttr.remove( val );
-            }
+                String ocLowerName = ocName.toLowerCase();
 
-            ObjectClass objectClass = registry.lookup( val );
+                ObjectClass objectClass = registries.getObjectClassRegistry().lookup( ocLowerName );
 
-            // cannot use Collections.addAll(Collection, Object[]) since it's 1.5
-            ObjectClass top = registry.lookup( "top" );
-            ObjectClass[] superiors = objectClass.getSuperClasses();
-            for ( int jj = 0; jj < superiors.length; jj++ )
-            {
-                if ( superiors[jj] != top && !objectClasses.contains( superiors[jj].getName().toLowerCase() ) )
+                if ( !objectClasses.contains( ocLowerName ) )
                 {
-                    objectClassAttr.add( superiors[jj].getName() );
+                    objectClasses.add( ocLowerName );
+                }
+
+                List ocSuperiors = (List)superiors.get( objectClass.getOid() );
+
+                if ( ocSuperiors != null )
+                {
+                    Iterator iter = ocSuperiors.iterator();
+
+                    while ( iter.hasNext() )
+                    {
+                        ObjectClass oc = (ObjectClass)iter.next();
+
+                        if ( !objectClasses.contains( oc.getName().toLowerCase() ) )
+                        {
+                            objectClasses.add( oc.getName() );
+                        }
+                    }
                 }
             }
         }
+
+        // Now, reset the ObjectClass attribute and put the new list into it
+        objectClassAttr.clear();
+
+        Iterator iter = objectClasses.iterator();
+
+        while ( iter.hasNext() )
+        {
+            objectClassAttr.add( iter.next() );
+        }
     }
 
     /**
@@ -750,7 +1065,7 @@
         if ( mods.get( "objectClass" ) != null )
         {
             Attribute alteredObjectClass = ( Attribute ) objectClass.clone();
-            alterObjectClasses( alteredObjectClass, ocRegistry );
+            alterObjectClasses( alteredObjectClass );
 
             if ( !alteredObjectClass.equals( objectClass ) )
             {
@@ -865,7 +1180,7 @@
         ModificationItemImpl objectClassMod = null;
         
         // Check that we don't have two times the same modification.
-        // This is somehow useless, has modification operations are supposed to
+        // This is somehow useless, as modification operations are supposed to
         // be atomic, so we may have a sucession of Add, DEL, ADD operations
         // for the same attribute, and this will be legal.
         // @TODO : check if we can remove this test.
@@ -898,8 +1213,8 @@
             
             if ( !modset.add( keybuf.toString() ) && mods[ii].getModificationOp() == DirContext.ADD_ATTRIBUTE )
             {
-                throw new LdapAttributeInUseException( "found two copies of the following modification item: "
-                    + mods[ii] );
+                throw new LdapAttributeInUseException( "found two copies of the following modification item: " +
+                 mods[ii] );
             }
         }
         
@@ -980,15 +1295,49 @@
                         throw new LdapNoSuchAttributeException();
                     }
 
-                    // for required attributes we need to check if all values are removed
-                    // if so then we have a schema violation that must be thrown
-                    if ( isRequired( change.getID(), objectClass ) && isCompleteRemoval( change, entry ) )
+                    // We may have to remove the attribute or only some values
+                    if ( change.size() == 0 )
                     {
-                        log.error( "Trying to remove a required attribute: " + change.getID() );
-                        throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        // No value : we have to remove the entire attribute
+                        // Check that we aren't removing a MUST attribute
+                        if ( isRequired( change.getID(), objectClass ) )
+                        {
+                            log.error( "Trying to remove a required attribute: " + change.getID() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+                    }
+                    else
+                    {
+                        // for required attributes we need to check if all values are removed
+                        // if so then we have a schema violation that must be thrown
+                        if ( isRequired( change.getID(), objectClass ) && isCompleteRemoval( change, entry ) )
+                        {
+                            log.error( "Trying to remove a required attribute: " + change.getID() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+
+                        // Now remove the attribute and all its values
+                        Attribute modified = tmpEntry.remove( change.getID() );
+                        
+                        // And inject back the values except the ones to remove
+                        NamingEnumeration values = change.getAll();
+                        
+                        while ( values.hasMoreElements() )
+                        {
+                            modified.remove( values.next() );
+                        }
+                        
+                        // ok, done. Last check : if the attribute does not content any more value;
+                        // and if it's a MUST one, we should thow an exception
+                        if ( ( modified.size() == 0 ) && isRequired( change.getID(), objectClass ) )
+                        {
+                            log.error( "Trying to remove a required attribute: " + change.getID() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+                        
+                        // Put back the attribute in the entry
+                        tmpEntry.put( modified );
                     }
-                    
-                    tmpEntry.remove( change.getID() );
                     
                     SchemaChecker.preventRdnChangeOnModifyRemove( name, modOp, change, 
                         this.registries.getOidRegistry() ); 
@@ -1024,13 +1373,15 @@
                     break;
             }
         }
+        
+        check( tmpEntry );
 
         // let's figure out if we need to add or take away from mods to maintain 
         // the objectClass attribute with it's hierarchy of ancestors 
         if ( objectClassMod != null )
         {
             Attribute alteredObjectClass = ( Attribute ) objectClass.clone();
-            alterObjectClasses( alteredObjectClass, ocRegistry );
+            alterObjectClasses( alteredObjectClass );
 
             if ( !alteredObjectClass.equals( objectClass ) )
             {
@@ -1074,8 +1425,6 @@
             }
         }
         
-        assertNumberOfAttributeValuesValid( tmpEntry );
-
         if ( name.startsWith( schemaBaseDN ) )
         {
             schemaManager.modify( name, mods, entry, targetEntry );
@@ -1084,35 +1433,47 @@
     }
 
 
-    private void filterTop( Attributes entry ) throws NamingException
+    private void filterObjectClass( Attributes entry ) throws NamingException
     {
-        // add top if objectClass is included and missing top
+        List objectClasses = new ArrayList();
         Attribute oc = entry.get( "objectClass" );
+        
         if ( oc != null )
         {
-            if ( !oc.contains( "top" ) )
+            getObjectClasses( oc, objectClasses );
+
+            entry.remove( "objectClass" );
+
+            Attribute newOc = new AttributeImpl( "ObjectClass" );
+
+            for ( int i = 0; i < objectClasses.size(); i++ )
             {
-                oc.add( "top" );
+                Object currentOC = objectClasses.get(i);
+
+                if ( currentOC instanceof String )
+                {
+                    newOc.add( currentOC );
+                }
+                else
+                {
+                    newOc.add( ( (ObjectClass)currentOC ).getName() );
+                }
             }
+
+            newOc.add( "top" );
+            entry.put( newOc );
         }
     }
 
 
     private void filterBinaryAttributes( Attributes entry ) throws NamingException
     {
-        long t0 = -1;
-
-        if ( IS_DEBUG )
-        {
-            t0 = System.currentTimeMillis();
-            log.debug( "Filtering entry " + AttributeUtils.toString( entry ) );
-        }
-
         /*
          * start converting values of attributes to byte[]s which are not
          * human readable and those that are in the binaries set
          */
         NamingEnumeration list = entry.getIDs();
+
         while ( list.hasMore() )
         {
             String id = ( String ) list.next();
@@ -1123,20 +1484,23 @@
             {
                 type = registries.getAttributeTypeRegistry().lookup( id );
             }
-
-            if ( type != null )
+            else
             {
-                asBinary = !type.getSyntax().isHumanReadible();
-                asBinary = asBinary || binaries.contains( type );
+                continue;
             }
 
+            asBinary = !type.getSyntax().isHumanReadible();
+            asBinary = asBinary || binaries.contains( type );
+
             if ( asBinary )
             {
                 Attribute attribute = entry.get( id );
                 Attribute binary = new AttributeImpl( id );
+
                 for ( int i = 0; i < attribute.size(); i++ )
                 {
                     Object value = attribute.get( i );
+                
                     if ( value instanceof String )
                     {
                         binary.add( i, StringTools.getBytesUtf8( ( String ) value ) );
@@ -1151,12 +1515,6 @@
                 entry.put( binary );
             }
         }
-
-        if ( log.isDebugEnabled() )
-        {
-            long t1 = System.currentTimeMillis();
-            log.debug( "Time to filter entry = " + ( t1 - t0 ) + " ms" );
-        }
     }
 
     /**
@@ -1185,7 +1543,7 @@
         public boolean accept( Invocation invocation, SearchResult result, SearchControls controls )
             throws NamingException
         {
-            filterTop( result.getAttributes() );
+            filterObjectClass( result.getAttributes() );
             return true;
         }
     }
@@ -1194,35 +1552,107 @@
     /**
      * Check that all the attributes exist in the schema for this entry.
      */
-    public void add( NextInterceptor next, LdapDN normName, Attributes attrs ) throws NamingException
+    private void check( Attributes entry ) throws NamingException
     {
-        AttributeTypeRegistry atRegistry = this.registries.getAttributeTypeRegistry();
-        NamingEnumeration attrEnum = attrs.getIDs();
+        NamingEnumeration attrEnum = entry.getIDs();
+
+        // ---------------------------------------------------------------
+        // First, make sure all attributes are valid schema defined attributes
+        // ---------------------------------------------------------------
+
         while ( attrEnum.hasMoreElements() )
         {
             String name = ( String ) attrEnum.nextElement();
             
-            // ---------------------------------------------------------------
-            // make sure all attributes are valid schema defined attributes
-            // ---------------------------------------------------------------
-
-            if ( !atRegistry.hasAttributeType( name ) )
+            if ( !registries.getAttributeTypeRegistry().hasAttributeType( name ) )
             {
                 throw new LdapInvalidAttributeIdentifierException( name + " not found in attribute registry!" );
             }
         }
 
-        alterObjectClasses( attrs.get( "objectClass" ), this.registries.getObjectClassRegistry() );
-        assertRequiredAttributesPresent( attrs );
-        assertNumberOfAttributeValuesValid( attrs );
+        // We will check some elements :
+        // 1) the entry must have all the MUST attributes of all its ObjectClass
+        // 2) The SingleValued attributes must be SingleValued
+        // 3) No attributes should be used if they are not part of MUST and MAY
+        // 3-1) Except if the extensibleObject ObjectClass is used
+        // 3-2) or if the AttributeType is COLLECTIVE
+        Attribute objectClassAttr = entry.get( "objectClass" );
+        List ocs = new ArrayList();
+
+        alterObjectClasses( objectClassAttr );
+
+        Set must = getAllMust( objectClassAttr.getAll() );
+        Set allowed = getAllAllowed( objectClassAttr.getAll(), must );
+
+        boolean hasExtensibleObject = getObjectClasses( objectClassAttr, ocs );
+
+        assertRequiredAttributesPresent( entry, must );
+        assertNumberOfAttributeValuesValid( entry );
+
+        if ( !hasExtensibleObject )
+        {
+            assertAllAttributesAllowed( entry, allowed );
+        }
+    }
+
+    /**
+     * Check that all the attributes exist in the schema for this entry.
+     */
+    public void add( NextInterceptor next, LdapDN normName, Attributes attrs ) throws NamingException
+    {
+        check( attrs );
 
         if ( normName.startsWith( schemaBaseDN ) )
         {
             schemaManager.add( normName, attrs );
         }
-        next.add(normName, attrs );
+
+        next.add( normName, attrs );
     }
     
+
+    /**
+     * Checks to see if an attribute is required by as determined from an entry's
+     * set of objectClass attribute values.
+     *
+     * @param attrId the attribute to test if required by a set of objectClass values
+     * @param objectClass the objectClass values
+     * @return true if the objectClass values require the attribute, false otherwise
+     * @throws NamingException if the attribute is not recognized
+     */
+    private void assertAllAttributesAllowed( Attributes attributes, Set allowed ) throws NamingException
+    {
+        // Never check the attributes if the extensibleObject objectClass is
+        // declared for this entry
+        Attribute objectClass = attributes.get( "objectClass" );
+
+        if ( AttributeUtils.containsValueCaseIgnore( objectClass, "extensibleObject" ) )
+        {
+            return;
+        }
+
+
+        NamingEnumeration attrs = attributes.getAll();
+
+        while ( attrs.hasMoreElements() )
+        {
+            Attribute attribute = (Attribute)attrs.nextElement();
+            String attrId = attribute.getID();
+            String attrOid = registries.getOidRegistry().getOid( attrId );
+
+            AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( attrOid );
+
+            if ( !attributeType.isCollective() && ( attributeType.getUsage() == UsageEnum.USER_APPLICATIONS ) )
+            {
+                if ( !allowed.contains( attrOid ) )
+                {
+                    throw new LdapSchemaViolationException( "Attribute " +
+                        attribute.getID() + " not declared in entry's objectClasses.",
+                        ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                }
+            }
+        }
+    }
     
     public void delete( NextInterceptor next, LdapDN normName ) throws NamingException
     {
@@ -1267,92 +1697,25 @@
     /**
      * Checks to see the presence of all required attributes within an entry.
      */
-    private void assertRequiredAttributesPresent( Attributes entry ) 
+    private void assertRequiredAttributesPresent( Attributes entry, Set must )
         throws NamingException
     {
-        AttributeType[] required = getRequiredAttributes( entry.get( "objectClass" ), 
-            this.registries.getObjectClassRegistry() );
-        for ( int ii = 0; ii < required.length; ii++ )
-        {
-            boolean aliasFound = false;
-            String[] aliases = required[ii].getNames();
-            for ( int jj = 0; jj < aliases.length; jj++ )
-            {
-                if ( entry.get( aliases[jj] ) != null )
-                {
-                    aliasFound = true;
-                    break;
-                }
-            }
-            
-            if ( ! aliasFound )
-            {
-                throw new LdapSchemaViolationException( "Required attribute " + 
-                    required[ii].getName() + " not found within entry.", 
-                    ResultCodeEnum.OBJECT_CLASS_VIOLATION );
-            }
-        }
-    }
+        NamingEnumeration attributes = entry.getAll();
 
-
-    /**
-     * Uses the objectClass registry to ascend super classes and collect 
-     * all attributeTypes within must lists until top is reached on each
-     * parent.
-     */
-    private static final AttributeType[] getRequiredAttributes( Attribute objectClass, 
-        ObjectClassRegistry registry ) throws NamingException
-    {
-        AttributeType[] attributeTypes;
-        Set<AttributeType> set = new HashSet<AttributeType>();
-        
-        for ( int ii = 0; ii < objectClass.size(); ii++ )
+        while ( attributes.hasMoreElements() && ( must.size() > 0 ) )
         {
-            String ocString = ( String ) objectClass.get( ii );
-            ObjectClass oc = registry.lookup( ocString );
-            infuseMustList( set, oc );
-        }
-        
-        attributeTypes = set.toArray( EMPTY_ATTRIBUTE_TYPE_ARRAY );
-        return attributeTypes;
-    }
+            Attribute attribute = (Attribute)attributes.nextElement();
+            
+            String oid = registries.getOidRegistry().getOid( attribute.getID() );
 
-    
-    /**
-     * Recursive method that finds all the required attributes for an 
-     * objectClass and infuses them into the provided non-null set.
-     * 
-     * @param set set to infuse attributeTypes into
-     * @param oc the objectClass to ascent the polymorphic inheritance tree of 
-     */
-    private static final void infuseMustList( Set<AttributeType> set, ObjectClass oc ) throws NamingException
-    {
-        // ignore top
-        if ( oc.getName().equalsIgnoreCase( "top" ) )
-        {
-            return;
+            must.remove( oid );
         }
-        
-        // add all the required attributes for this objectClass 
-        Collections.addAll( set, oc.getMustList() );
-        
-        // don't bother ascending if no parents exist
-        ObjectClass[] parents = oc.getSuperClasses();
-        if ( parents == null || parents.length == 0 )
-        {
-            return;
-        }
-        
-        // save on a for loop
-        if ( parents.length == 1 ) 
-        {
-            infuseMustList( set, parents[0] );
-            return;
-        }
-        
-        for ( int ii = 0; ii < parents.length; ii++ )
+
+        if ( must.size() != 0 )
         {
-            infuseMustList( set, parents[ii] );
+            throw new LdapSchemaViolationException( "Required attributes " +
+                must.toArray() + " not found within entry.",
+                ResultCodeEnum.OBJECT_CLASS_VIOLATION );
         }
     }
 }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryService.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryService.java Wed Jan 24 10:31:33 2007
@@ -55,6 +55,7 @@
 import org.apache.directory.shared.ldap.schema.NormalizerMappingResolver;
 import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
 import org.apache.directory.shared.ldap.subtree.SubtreeSpecificationParser;
+import org.apache.directory.shared.ldap.util.AttributeUtils;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -192,22 +193,22 @@
                 ResultCodeEnum.OBJECT_CLASS_VIOLATION );
         }
         
-        if ( oc.contains( "accessControlSubentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, "accessControlSubentry" ) )
         {
             types |= Subentry.ACCESS_CONTROL_SUBENTRY;
         }
         
-        if ( oc.contains( "subschema" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, "subschema" ) )
         {
             types |= Subentry.SCHEMA_SUBENTRY;
         }
         
-        if ( oc.contains( "collectiveAttributeSubentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, "collectiveAttributeSubentry" ) )
         {
             types |= Subentry.COLLECTIVE_SUBENTRY;
         }
         
-        if ( oc.contains( "triggerExecutionSubentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( oc, "triggerExecutionSubentry" ) )
         {
             types |= Subentry.TRIGGER_SUBENTRY;
         }
@@ -373,7 +374,7 @@
     {
         Attribute objectClasses = entry.get( "objectClass" );
 
-        if ( objectClasses.contains( "subentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) )
         {
             // get the name of the administrative point and its administrativeRole attributes
             LdapDN apName = ( LdapDN ) normName.clone();
@@ -528,7 +529,7 @@
         Attributes entry = nexus.lookup( name );
         Attribute objectClasses = ServerUtils.getAttribute( objectClassType, entry );
 
-        if ( objectClasses.contains( "subentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) )
         {
             SubtreeSpecification ss = subentryCache.removeSubentry( name.toNormName() ).getSubtreeSpecification();
             next.delete( name );
@@ -680,7 +681,7 @@
         Attributes entry = nexus.lookup( name );
         Attribute objectClasses = ServerUtils.getAttribute( objectClassType, entry );
 
-        if ( objectClasses.contains( "subentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) )
         {
             Subentry subentry = subentryCache.getSubentry( name.toNormName() );
             SubtreeSpecification ss = subentry.getSubtreeSpecification();
@@ -751,7 +752,7 @@
         Attributes entry = nexus.lookup( oriChildName );
         Attribute objectClasses = ServerUtils.getAttribute( objectClassType, entry );
 
-        if ( objectClasses.contains( "subentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) )
         {
             Subentry subentry = subentryCache.getSubentry( oriChildName.toNormName() );
             SubtreeSpecification ss = subentry.getSubtreeSpecification();
@@ -822,7 +823,7 @@
         Attributes entry = nexus.lookup( oriChildName );
         Attribute objectClasses = entry.get( "objectClass" );
 
-        if ( objectClasses.contains( "subentry" ) )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) )
         {
             Subentry subentry = subentryCache.getSubentry( oriChildName.toString() );
             SubtreeSpecification ss = subentry.getSubtreeSpecification();
@@ -965,7 +966,7 @@
         Attributes entry = nexus.lookup( name );
         Attribute objectClasses = ServerUtils.getAttribute( objectClassType, entry );
 
-        if ( objectClasses.contains( "subentry" ) && mods.get( "subtreeSpecification" ) != null )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" )  && mods.get( "subtreeSpecification" ) != null )
         {
             SubtreeSpecification ssOld = subentryCache.removeSubentry( name.toNormName() ).getSubtreeSpecification();
             SubtreeSpecification ssNew;
@@ -1050,7 +1051,7 @@
             }
         }
 
-        if ( objectClasses.contains( "subentry" ) && isSubtreeSpecificationModification )
+        if ( AttributeUtils.containsValueCaseIgnore( objectClasses, "subentry" ) && isSubtreeSpecificationModification )
         {
             SubtreeSpecification ssOld = subentryCache.removeSubentry( name.toString() ).getSubtreeSpecification();
             SubtreeSpecification ssNew;
@@ -1368,12 +1369,12 @@
             Attribute objectClasses = result.getAttributes().get( "objectClass" );
             if ( objectClasses != null )
             {
-                if ( objectClasses.contains( SUBENTRY_OBJECTCLASS ) )
+                if ( AttributeUtils.containsValueCaseIgnore( objectClasses, SUBENTRY_OBJECTCLASS ) )
                 {
                     return false;
                 }
 
-                if ( objectClasses.contains( SUBENTRY_OBJECTCLASS_OID ) )
+                if ( AttributeUtils.containsValueCaseIgnore( objectClasses, SUBENTRY_OBJECTCLASS_OID ) )
                 {
                     return false;
                 }
@@ -1429,12 +1430,12 @@
             Attribute objectClasses = result.getAttributes().get( "objectClass" );
             if ( objectClasses != null )
             {
-                if ( objectClasses.contains( SUBENTRY_OBJECTCLASS ) )
+                if ( AttributeUtils.containsValueCaseIgnore( objectClasses, SUBENTRY_OBJECTCLASS ) )
                 {
                     return true;
                 }
 
-                if ( objectClasses.contains( SUBENTRY_OBJECTCLASS_OID ) )
+                if ( AttributeUtils.containsValueCaseIgnore( objectClasses, SUBENTRY_OBJECTCLASS_OID ) )
                 {
                     return true;
                 }

Modified: directory/apacheds/trunk/core/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java?view=diff&rev=499513&r1=499512&r2=499513
==============================================================================
--- directory/apacheds/trunk/core/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java (original)
+++ directory/apacheds/trunk/core/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java Wed Jan 24 10:31:33 2007
@@ -86,7 +86,7 @@
         assertTrue( nameAttrs.contains( "givenName" ) );
     }
     
-
+/*
     public void testAlterObjectClassesBogusAttr() throws NamingException
     {
         Attribute attr = new AttributeImpl( "blah", "blah" );
@@ -102,7 +102,7 @@
         }
 
         attr = new AttributeImpl( "objectClass" );
-        SchemaService.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+        SchemaService.alterObjectClasses( attr );
         assertEquals( 0, attr.size() );
     }
 
@@ -110,7 +110,7 @@
     public void testAlterObjectClassesNoAttrValue() throws NamingException
     {
         Attribute attr = new AttributeImpl( "objectClass" );
-        SchemaService.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+        SchemaService.alterObjectClasses( attr );
         assertEquals( 0, attr.size() );
     }
 
@@ -158,4 +158,5 @@
         assertTrue( attr.contains( "dSA" ) );
         assertTrue( attr.contains( "applicationEntity" ) );
     }
+    */
 }