directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r426892 - /directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
Date Sun, 30 Jul 2006 15:13:01 GMT
Author: elecharny
Date: Sun Jul 30 08:13:01 2006
New Revision: 426892

URL: http://svn.apache.org/viewvc?rev=426892&view=rev
Log:
- Fixed DIRSERVER_636
- Added some javadoco (but a lot remains to do ...)
- Added some defensive tests

Modified:
    directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java

Modified: directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
URL: http://svn.apache.org/viewvc/directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java?rev=426892&r1=426891&r2=426892&view=diff
==============================================================================
--- directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
(original)
+++ directory/branches/apacheds/optimization/core/src/main/java/org/apache/directory/server/core/schema/SchemaService.java
Sun Jul 30 08:13:01 2006
@@ -39,6 +39,7 @@
 import org.apache.directory.server.core.partition.PartitionNexus;
 import org.apache.directory.shared.ldap.exception.LdapAttributeInUseException;
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeIdentifierException;
+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;
@@ -49,6 +50,7 @@
 import org.apache.directory.shared.ldap.message.LockableAttributesImpl;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
 import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.Rdn;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.DITContentRule;
 import org.apache.directory.shared.ldap.schema.DITStructureRule;
@@ -124,11 +126,18 @@
         startUpTimeStamp = DateUtils.getGeneralizedTime();
     }
 
-
+    /**
+     * Initialize the Schema Service
+     * 
+     * @param factoryCfg
+     * @param cfg
+     * 
+     * @throws NamingException
+     */
     public void init( DirectoryServiceConfiguration factoryCfg, InterceptorConfiguration
cfg ) throws NamingException
     {
-        this.nexus = factoryCfg.getPartitionNexus();
-        this.globalRegistries = factoryCfg.getGlobalRegistries();
+        nexus = factoryCfg.getPartitionNexus();
+        globalRegistries = factoryCfg.getGlobalRegistries();
         binaryAttributeFilter = new BinaryAttributeFilter();
         topFilter = new TopFilter();
         filters.add( binaryAttributeFilter );
@@ -142,19 +151,26 @@
 
 
     /**
-     * @return Returns the binaries.
+     * Check if an attribute stores binary values.
+     * 
+     * @return Returns true if the attribute is binary.
      */
     public boolean isBinary( String id )
     {
         return binaries.contains( StringTools.lowerCase( StringTools.trim( id ) ) );
     }
 
-
+    /**
+     * Destroy the Schema Service
+     */
     public void destroy()
     {
     }
 
 
+    /**
+     * 
+     */
     public NamingEnumeration list( NextInterceptor nextInterceptor, LdapDN base ) throws
NamingException
     {
         NamingEnumeration e = nextInterceptor.list( base );
@@ -163,6 +179,9 @@
     }
 
 
+    /**
+     * 
+     */
     public NamingEnumeration search( NextInterceptor nextInterceptor, LdapDN base, Map env,
ExprNode filter,
         SearchControls searchCtls ) throws NamingException
     {
@@ -216,6 +235,12 @@
     }
 
 
+    /**
+     * 
+     * @param ids
+     * @return
+     * @throws NamingException
+     */
     private Attributes getSubschemaEntry( String[] ids ) throws NamingException
     {
         if ( ids == null )
@@ -396,6 +421,9 @@
     }
 
 
+    /**
+     * 
+     */
     public Attributes lookup( NextInterceptor nextInterceptor, LdapDN name ) throws NamingException
     {
         Attributes result = nextInterceptor.lookup( name );
@@ -404,7 +432,9 @@
         return result;
     }
 
-
+    /**
+     * 
+     */
     public Attributes lookup( NextInterceptor nextInterceptor, LdapDN name, String[] attrIds
) throws NamingException
     {
         Attributes result = nextInterceptor.lookup( name, attrIds );
@@ -487,8 +517,15 @@
         return changedEntryAttr.size() == 0;
     }
 
-
-    Attribute getResultantObjectClasses( int modOp, Attribute changes, Attribute existing
) throws NamingException
+    /**
+     * 
+     * @param modOp
+     * @param changes
+     * @param existing
+     * @return
+     * @throws NamingException
+     */
+    private Attribute getResultantObjectClasses( int modOp, Attribute changes, Attribute
existing ) throws NamingException
     {
         if ( changes == null && existing == null )
         {
@@ -574,15 +611,46 @@
         }
     }
 
-
+    /**
+     * Check that the modify operations are allowed, and the conform to
+     * the schema.
+     * 
+     * @param next The next interceptor to call when we are done with the local operation
+     * @param name The DN on which the modification is being done 
+     * @param modOp The modification. One of :
+     *   DirContext.ADD_ATTRIBUTE
+     *   DirContext.REMOVE_ATTRIBUTE
+     *   DirContext.REPLACE_ATTRIBUTE
+     * @param mods The modifications to check. Each operation is atomic, and should
+     * be applied to a copy of the entry, in order to check that the schema is not
+     * violated at the end. For instance, we can't delete an attribute that does
+     * not exist and add it later. The opposite is legal.
+     * 
+     * @throws NamingException The generic exception we get if an illegal operation occurs
+     * @throws LdapNameNotFoundException If we don't find the entry, then this exception
is thrown.
+     * @throws LdapInvalidAttributeIdentifierException The modified attribute is not known
+     * by the schema, or the Entry is not extensible.
+     * @throws LdapNoSuchAttributeException The modified Attribute does not exist in the

+     * current entry or is not added by a previous modification operation.
+     * @throws LdapSchemaViolationException Another schema violation occured.
+     */
     public void modify( NextInterceptor next, LdapDN name, int modOp, Attributes mods ) throws
NamingException
     {
+        // First, we get the entry from the backend. If it does not exist, then we throw
an exception
         Attributes entry = nexus.lookup( name );
+        
+        if ( entry == null )
+        {
+            log.error( "No entry with this name :{}", name );
+            throw new LdapNameNotFoundException( "The entry which name is " + name + " is
not found." );
+        }
+        
         Attribute objectClass = getResultantObjectClasses( modOp, mods.get( "objectClass"
), entry.get( "objectClass" ) );
         ObjectClassRegistry ocRegistry = this.globalRegistries.getObjectClassRegistry();
         AttributeTypeRegistry atRegistry = this.globalRegistries.getAttributeTypeRegistry();
 
         NamingEnumeration changes = mods.getIDs();
+        
         while ( changes.hasMore() )
         {
             String id = ( String ) changes.next();
@@ -644,6 +712,7 @@
                             }
                         }
                         break;
+                        
                     case ( DirContext.REMOVE_ATTRIBUTE  ):
                         for ( int ii = 0; ii < alteredObjectClass.size(); ii++ )
                         {
@@ -653,6 +722,7 @@
                             }
                         }
                         break;
+                        
                     case ( DirContext.REPLACE_ATTRIBUTE  ):
                         for ( int ii = 0; ii < alteredObjectClass.size(); ii++ )
                         {
@@ -662,7 +732,9 @@
                             }
                         }
                         break;
+                        
                     default:
+                        break;
                 }
             }
         }
@@ -670,13 +742,29 @@
         next.modify( name, modOp, mods );
     }
 
-
     public void modify( NextInterceptor next, LdapDN name, ModificationItem[] mods ) throws
NamingException
     {
+        // First, we get the entry from the backend. If it does not exist, then we throw
an exception
         Attributes entry = nexus.lookup( name );
+
+        if ( entry == null )
+        {
+            log.error( "No entry with this name :{}", name );
+            throw new LdapNameNotFoundException( "The entry which name is " + name + " is
not found." );
+        }
+        
+        // We will use this temporary entry to check that the modifications
+        // can be applied as atomic operations
+        Attributes tmpEntry = (Attributes)entry.clone();
+        
         Set modset = new HashSet();
         ModificationItem objectClassMod = null;
-
+        
+        // Check that we don't have two times the same modification.
+        // This is somehow useless, has 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.
         for ( int ii = 0; ii < mods.length; ii++ )
         {
             if ( mods[ii].getAttribute().getID().equalsIgnoreCase( "objectclass" ) )
@@ -687,16 +775,20 @@
             StringBuffer keybuf = new StringBuffer();
             keybuf.append( mods[ii].getModificationOp() );
             keybuf.append( mods[ii].getAttribute().getID() );
+
             for ( int jj = 0; jj < mods[ii].getAttribute().size(); jj++ )
             {
                 keybuf.append( mods[ii].getAttribute().get( jj ) );
             }
+            
             if ( !modset.add( keybuf.toString() ) && mods[ii].getModificationOp()
== DirContext.ADD_ATTRIBUTE )
             {
                 throw new LdapAttributeInUseException( "found two copies of the following
modification item: "
                     + mods[ii] );
             }
         }
+        
+        // Get the objectClass attribute.
         Attribute objectClass;
 
         if ( objectClassMod == null )
@@ -712,6 +804,8 @@
         ObjectClassRegistry ocRegistry = this.globalRegistries.getObjectClassRegistry();
         AttributeTypeRegistry atRegistry = this.globalRegistries.getAttributeTypeRegistry();
 
+        // Now, apply the modifications on the cloned entry before applyong it to the
+        // real object.
         for ( int ii = 0; ii < mods.length; ii++ )
         {
             int modOp = mods[ii].getModificationOp();
@@ -722,29 +816,86 @@
                 throw new LdapInvalidAttributeIdentifierException();
             }
 
-            if ( modOp == DirContext.REMOVE_ATTRIBUTE && entry.get( change.getID()
) == null )
-            {
-                throw new LdapNoSuchAttributeException();
-            }
-
-            if ( modOp == DirContext.REMOVE_ATTRIBUTE )
+            switch ( modOp )
             {
-                // 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 ) )
-                {
-                    throw new LdapSchemaViolationException( ResultCodeEnum.OBJECTCLASSVIOLATION
);
-                }
-                SchemaChecker.preventRdnChangeOnModifyRemove( name, modOp, change, 
-                    this.globalRegistries.getOidRegistry() ); 
-                SchemaChecker
-                    .preventStructuralClassRemovalOnModifyRemove( ocRegistry, name, modOp,
change, objectClass );
-            }
+                case DirContext.ADD_ATTRIBUTE :
+                    Attribute attr = tmpEntry.get( change.getID() );
+                    
+                    if ( attr != null ) 
+                    {
+                        NamingEnumeration values = change.getAll();
+                        
+                        while ( values.hasMoreElements() )
+                        {
+                            attr.add( values.nextElement() );
+                        }
+                    }
+                    else
+                    {
+                        attr = new LockableAttributeImpl( change.getID() );
+                        NamingEnumeration values = change.getAll();
+                        
+                        while ( values.hasMoreElements() )
+                        {
+                            attr.add( values.nextElement() );
+                        }
+                        
+                        tmpEntry.put( attr );
+                    }
+                    
+                    break;
+
+                case DirContext.REMOVE_ATTRIBUTE :
+                    if ( tmpEntry.get( change.getID() ) == null )
+                    {
+                        log.error( "Trying to remove an inexistant attribute" );
+                        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 ) )
+                    {
+                        log.error( "Trying to remove a required attribute" );
+                        throw new LdapSchemaViolationException( ResultCodeEnum.OBJECTCLASSVIOLATION
);
+                    }
+                    
+                    tmpEntry.remove( change.getID() );
+                    
+                    SchemaChecker.preventRdnChangeOnModifyRemove( name, modOp, change, 
+                        this.globalRegistries.getOidRegistry() ); 
+                    SchemaChecker
+                        .preventStructuralClassRemovalOnModifyRemove( ocRegistry, name, modOp,
change, objectClass );
+                    break;
+                        
+                case DirContext.REPLACE_ATTRIBUTE :
+                    SchemaChecker.preventRdnChangeOnModifyReplace( name, modOp, change );
+                    SchemaChecker.preventStructuralClassRemovalOnModifyReplace( ocRegistry,
name, modOp, change );
+                    
+                    attr = tmpEntry.get( change.getID() );
+                    
+                    if ( attr != null )
+                    {
+                        tmpEntry.remove( change.getID() );
+                    }
+                    else
+                    {
+                        attr = new LockableAttributeImpl( change.getID() );
+                    }
+                    
+                    NamingEnumeration values = change.getAll();
+                    
+                    if ( values.hasMoreElements() ) 
+                    {
+                        while ( values.hasMoreElements() )
+                        {
+                            attr.add( values.nextElement() );
+                        }
 
-            if ( modOp == DirContext.REPLACE_ATTRIBUTE )
-            {
-                SchemaChecker.preventRdnChangeOnModifyReplace( name, modOp, change );
-                SchemaChecker.preventStructuralClassRemovalOnModifyReplace( ocRegistry, name,
modOp, change );
+                        tmpEntry.put( attr );
+                    }
+                    
+                    break;
             }
         }
 
@@ -758,6 +909,7 @@
             if ( !alteredObjectClass.equals( objectClass ) )
             {
                 Attribute ocMods = objectClassMod.getAttribute();
+                
                 switch ( objectClassMod.getModificationOp() )
                 {
                     case ( DirContext.ADD_ATTRIBUTE  ):



Mime
View raw message