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 2009/08/10 00:56:01 UTC

svn commit: r802621 - /directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java

Author: elecharny
Date: Sun Aug  9 22:56:00 2009
New Revision: 802621

URL: http://svn.apache.org/viewvc?rev=802621&view=rev
Log:
Removed a useless lookup done in the modify() operation : we already have the entry loaded in the operation context

Modified:
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java?rev=802621&r1=802620&r2=802621&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java Sun Aug  9 22:56:00 2009
@@ -1237,7 +1237,8 @@
         }
         else
         {
-            entry = opContext.lookup( name, ByPassConstants.LOOKUP_BYPASS );
+            // Get the entry we already read at the beginning
+            entry = opContext.getEntry();
         }
 
         // First, we get the entry from the backend. If it does not exist, then we throw an exception
@@ -1536,6 +1537,321 @@
         next.modify( opContext );
     }
 
+    
+    public void modify2( NextInterceptor next, ModifyOperationContext opContext ) throws Exception
+    {
+        ServerEntry entry;
+        LdapDN name = opContext.getDn();
+        List<Modification> mods = opContext.getModItems();
+
+        // handle operations against the schema subentry in the schema service
+        // and never try to look it up in the nexus below
+        if ( name.getNormName().equalsIgnoreCase( subschemaSubentryDnNorm ) )
+        {
+            entry = schemaService.getSubschemaEntry( SCHEMA_SUBENTRY_RETURN_ATTRIBUTES );
+            entry.setDn( name );
+        }
+        else
+        {
+            entry = opContext.lookup( name, ByPassConstants.LOOKUP_BYPASS );
+        }
+
+        // First, we get the entry from the backend. If it does not exist, then we throw an exception
+        ServerEntry targetEntry = (ServerEntry)SchemaUtils.getTargetEntry( mods , entry );
+
+        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
+        ServerEntry tmpEntry = ( ServerEntry ) entry.clone();
+
+        Set<String> modset = new HashSet<String>();
+        Modification objectClassMod = null;
+
+        // Check that we don't have two times the same modification.
+        // 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.
+        for ( Modification mod : mods )
+        {
+            if ( mod.getAttribute().getId().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) )
+            {
+                objectClassMod = mod;
+            }
+
+            // Freak out under some weird cases
+            if ( mod.getAttribute().size() == 0 )
+            {
+                // not ok for add but ok for replace and delete
+                if ( mod.getOperation() == ModificationOperation.ADD_ATTRIBUTE )
+                {
+                    throw new LdapInvalidAttributeValueException( "No value is not a valid value for an attribute.",
+                        ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX );
+                }
+            }
+
+            StringBuffer keybuf = new StringBuffer();
+            keybuf.append( mod.getOperation() );
+            keybuf.append( mod.getAttribute().getId() );
+
+            for ( Value<?> value : ( ServerAttribute ) mod.getAttribute() )
+            {
+                keybuf.append( value.getString() );
+            }
+
+            if ( !modset.add( keybuf.toString() ) && ( mod.getOperation() == ModificationOperation.ADD_ATTRIBUTE ) )
+            {
+                throw new LdapAttributeInUseException( "found two copies of the following modification item: " + mod );
+            }
+        }
+
+        // Get the objectClass attribute.
+        EntryAttribute objectClass;
+
+        if ( objectClassMod == null )
+        {
+            objectClass = entry.get( SchemaConstants.OBJECT_CLASS_AT );
+
+            if ( objectClass == null )
+            {
+                objectClass = new DefaultServerAttribute( SchemaConstants.OBJECT_CLASS_AT, OBJECT_CLASS );
+            }
+        }
+        else
+        {
+            objectClass = getResultantObjectClasses( objectClassMod.getOperation(), objectClassMod.getAttribute(),
+                tmpEntry.get( SchemaConstants.OBJECT_CLASS_AT ) );
+        }
+
+        ObjectClassRegistry ocRegistry = this.registries.getObjectClassRegistry();
+
+        // Now, apply the modifications on the cloned entry before applying it on the
+        // real object.
+        for ( Modification mod : mods )
+        {
+            ModificationOperation modOp = mod.getOperation();
+            ServerAttribute change = ( ServerAttribute ) mod.getAttribute();
+
+            // TODO/ handle http://issues.apache.org/jira/browse/DIRSERVER-1198
+            if ( ( change.getAttributeType() == null ) && !atRegistry.hasAttributeType( change.getUpId() )
+                && !objectClass.contains( SchemaConstants.EXTENSIBLE_OBJECT_OC ) )
+            {
+                throw new LdapInvalidAttributeIdentifierException();
+            }
+
+            // We will forbid modification of operational attributes which are not
+            // user modifiable.
+            AttributeType attributeType = change.getAttributeType();
+            
+            if ( attributeType == null )
+            {
+                attributeType = atRegistry.lookup( change.getUpId() );
+            }
+
+            if ( !attributeType.isCanUserModify() )
+            {
+                throw new NoPermissionException( "Cannot modify the attribute '" + change.getUpId() + "'" );
+            }
+
+            switch ( modOp )
+            {
+                case ADD_ATTRIBUTE:
+                    EntryAttribute attr = tmpEntry.get( attributeType.getName() );
+
+                    if ( attr != null )
+                    {
+                        for ( Value<?> value : change )
+                        {
+                            attr.add( value );
+                        }
+                    }
+                    else
+                    {
+                        attr = new DefaultServerAttribute( change.getUpId(), attributeType );
+
+                        for ( Value<?> value : change )
+                        {
+                            attr.add( value );
+                        }
+
+                        tmpEntry.put( attr );
+                    }
+
+                    break;
+
+                case REMOVE_ATTRIBUTE:
+                    if ( tmpEntry.get( change.getId() ) == null )
+                    {
+                        LOG.error( "Trying to remove an non-existant attribute: " + change.getUpId() );
+                        throw new LdapNoSuchAttributeException();
+                    }
+
+                    // We may have to remove the attribute or only some values
+                    if ( change.size() == 0 )
+                    {
+                        // No value : we have to remove the entire attribute
+                        // Check that we aren't removing a MUST attribute
+                        if ( isRequired( change.getUpId(), objectClass ) )
+                        {
+                            LOG.error( "Trying to remove a required attribute: " + change.getUpId() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+                        
+                        attr = tmpEntry.get( change.getUpId() );
+                        if ( attr != null )
+                        {
+                            tmpEntry.removeAttributes( change.getUpId() );
+                        }
+                    }
+                    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.getUpId(), objectClass ) && isCompleteRemoval( change, entry ) )
+                        {
+                            LOG.error( "Trying to remove a required attribute: " + change.getUpId() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+
+                        // Now remove the attribute and all its values
+                        EntryAttribute modified = tmpEntry.removeAttributes( change.getId() ).get( 0 );
+
+                        // And inject back the values except the ones to remove
+                        for ( Value<?> value : change )
+                        {
+                            modified.remove( value );
+                        }
+
+                        // 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.getUpId() );
+                            throw new LdapSchemaViolationException( ResultCodeEnum.OBJECT_CLASS_VIOLATION );
+                        }
+
+                        // Put back the attribute in the entry only if it has values left in it
+                        if ( modified.size() > 0 )
+                        {
+                            tmpEntry.put( modified );
+                        }
+                    }
+
+                    SchemaChecker
+                        .preventRdnChangeOnModifyRemove( name, modOp, change, this.registries.getOidRegistry() );
+                    SchemaChecker.preventStructuralClassRemovalOnModifyRemove( ocRegistry, name, modOp, change,
+                        objectClass );
+                    break;
+
+                case REPLACE_ATTRIBUTE:
+                    SchemaChecker.preventRdnChangeOnModifyReplace( name, modOp, change, registries.getOidRegistry() );
+                    SchemaChecker.preventStructuralClassRemovalOnModifyReplace( ocRegistry, name, modOp, change );
+
+                    attr = tmpEntry.get( change.getUpId() );
+
+                    if ( attr != null )
+                    {
+                        tmpEntry.removeAttributes( change.getUpId() );
+                    }
+
+                    attr = new DefaultServerAttribute( change.getUpId(), attributeType );
+
+                    if ( change.size() != 0 )
+                    {
+                        for ( Value<?> value : change )
+                        {
+                            attr.add( value );
+                        }
+
+                        tmpEntry.put( attr );
+                    }
+
+                    break;
+            }
+        }
+
+        check( name, 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 )
+        {
+            ServerAttribute alteredObjectClass = ( ServerAttribute ) objectClass.clone();
+            alterObjectClasses( alteredObjectClass );
+
+            if ( !alteredObjectClass.equals( objectClass ) )
+            {
+                ServerAttribute ocMods = ( ServerAttribute ) objectClassMod.getAttribute();
+
+                switch ( objectClassMod.getOperation() )
+                {
+                    case ADD_ATTRIBUTE:
+                        if ( ocMods.contains( SchemaConstants.TOP_OC ) )
+                        {
+                            ocMods.remove( SchemaConstants.TOP_OC );
+                        }
+
+                        for ( Value<?> value : alteredObjectClass )
+                        {
+                            if ( !objectClass.contains( value ) )
+                            {
+                                ocMods.add( value );
+                            }
+                        }
+
+                        break;
+
+                    case REMOVE_ATTRIBUTE:
+                        for ( Value<?> value : alteredObjectClass )
+                        {
+                            if ( !objectClass.contains( value ) )
+                            {
+                                ocMods.remove( value );
+                            }
+                        }
+
+                        break;
+
+                    case REPLACE_ATTRIBUTE:
+                        for ( Value<?> value : alteredObjectClass )
+                        {
+                            if ( !objectClass.contains( value ) )
+                            {
+                                ocMods.add( value );
+                            }
+                        }
+
+                        break;
+
+                    default:
+                }
+            }
+        }
+
+        if ( name.startsWith( schemaBaseDN ) )
+        {
+            LOG.debug( "Modification attempt on schema partition {}: \n{}", name, opContext );
+
+            schemaManager.modify( opContext, entry, targetEntry, opContext
+                .hasRequestControl( CascadeControl.CONTROL_OID ) );
+        }
+        else if ( subschemaSubentryDnNorm.equals( name.getNormName() ) )
+        {
+            LOG.debug( "Modification attempt on schema subentry {}: \n{}", name, opContext );
+
+            schemaManager.modifySchemaSubentry( opContext, entry, targetEntry, opContext
+                .hasRequestControl( CascadeControl.CONTROL_OID ) );
+            return;
+        }
+
+        next.modify( opContext );
+    }
+    
 
     /**
      * Filter the attributes by removing the ones which are not allowed