You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/09/09 00:42:48 UTC

svn commit: r279664 - /directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java

Author: akarasulu
Date: Thu Sep  8 15:42:45 2005
New Revision: 279664

URL: http://svn.apache.org/viewcvs?rev=279664&view=rev
Log:
completed functionality additions to subentry service

changes ...

 o Changed op attribute for collective attribute to use one existing in 3671
   namely for collectiveAttributeSubentries
 o added functionality to modify subentry attributes when regular entries are
   added, and their names are changed
 o added code to prevent the name change of entries whose descendants are 
   administrative points due to the repercussions this would have on subentry
   attribute management


Modified:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java?rev=279664&r1=279663&r2=279664&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/subtree/SubentryService.java Thu Sep  8 15:42:45 2005
@@ -37,6 +37,7 @@
 import org.apache.ldap.common.name.LdapName;
 import org.apache.ldap.common.exception.LdapNoSuchAttributeException;
 import org.apache.ldap.common.exception.LdapInvalidAttributeValueException;
+import org.apache.ldap.common.exception.LdapSchemaViolationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,19 +70,19 @@
     public static final String AUTONOUMOUS_AREA_SUBENTRY = "autonomousAreaSubentry";
 
     public static final String AC_AREA = "accessControlSpecificArea";
-    public static final String AC_AREA_SUBENTRY = "accessControlAreaSubentry";
+    public static final String AC_AREA_SUBENTRY = "accessControlAreaSubentries";
 
     public static final String AC_INNERAREA = "accessControlInnerArea";
-    public static final String AC_INNERAREA_SUBENTRY = "accessControlInnerAreaSubentry";
+    public static final String AC_INNERAREA_SUBENTRY = "accessControlInnerAreaSubentries";
 
     public static final String SCHEMA_AREA = "subschemaAdminSpecificArea";
     public static final String SCHEMA_AREA_SUBENTRY = "subschemaSubentry";
 
     public static final String COLLECTIVE_AREA = "collectiveAttributeSpecificArea";
-    public static final String COLLECTIVE_AREA_SUBENTRY = "collectiveAttributeAreaSubentry";
+    public static final String COLLECTIVE_AREA_SUBENTRY = "collectiveAttributeSubentries";
 
     public static final String COLLECTIVE_INNERAREA = "collectiveAttributeInnerArea";
-    public static final String COLLECTIVE_INNERAREA_SUBENTRY = "collectiveAttributeInnerAreaSubentry";
+    public static final String COLLECTIVE_INNERAREA_SUBENTRY = "collectiveAttributeSubentries";
 
     public static final String[] SUBENTRY_OPATTRS = {
         AUTONOUMOUS_AREA_SUBENTRY,
@@ -484,6 +485,115 @@
     // -----------------------------------------------------------------------
 
 
+    /**
+     * Checks to see if an entry being renamed has a descendant that is an
+     * administrative point.
+     *
+     * @param name the name of the entry which is used as the search base
+     * @return true if name is an administrative point or one of its descendants
+     * are, false otherwise
+     * @throws NamingException if there are errors while searching the directory
+     */
+    private boolean hasAdministrativeDescendant( Name name ) throws NamingException
+    {
+        ExprNode filter = new PresenceNode( "administrativeRole" );
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        NamingEnumeration aps = nexus.search( name, factoryCfg.getEnvironment(), filter, controls );
+        if ( aps.hasMore() )
+        {
+            aps.close();
+            return true;
+        }
+
+        return false;
+    }
+
+
+    private ModificationItem[] getModsOnEntryRdnChange( Name oldName, Name newName, Attributes entry )
+        throws NamingException
+    {
+        Attribute objectClasses = entry.get( "objectClass" );
+        List modList = new ArrayList();
+
+        /*
+         * There are two different situations warranting action.  Firt if
+         * an ss evalutating to true with the old name no longer evalutates
+         * to true with the new name.  This would be caused by specific chop
+         * exclusions that effect the new name but did not effect the old
+         * name. In this case we must remove subentry operational attribute
+         * values associated with the dn of that subentry.
+         *
+         * In the second case an ss selects the entry with the new name when
+         * it did not previously with the old name.  Again this situation
+         * would be caused by chop exclusions. In this case we must add subentry
+         * operational attribute values with the dn of this subentry.
+         */
+        Iterator subentries = subtrees.keySet().iterator();
+        while ( subentries.hasNext() )
+        {
+            String subentryDn = ( String ) subentries.next();
+            Name apDn = new LdapName( subentryDn );
+            apDn.remove( apDn.size() - 1 );
+            SubtreeSpecification ss = ( SubtreeSpecification ) subtrees.get( subentryDn );
+            boolean isOldNameSelected = evaluator.evaluate( ss, apDn, oldName, objectClasses );
+            boolean isNewNameSelected = evaluator.evaluate( ss, apDn, newName, objectClasses );
+
+            if ( isOldNameSelected == isNewNameSelected )
+            {
+                continue;
+            }
+
+            // need to remove references to the subentry
+            if ( isOldNameSelected && ! isNewNameSelected )
+            {
+                for ( int ii = 0; ii < SUBENTRY_OPATTRS.length; ii++ )
+                {
+                    int op = DirContext.REPLACE_ATTRIBUTE;
+                    Attribute opAttr = entry.get( SUBENTRY_OPATTRS[ii] );
+                    if ( opAttr != null )
+                    {
+                        opAttr = ( Attribute ) opAttr.clone();
+                        opAttr.remove( subentryDn );
+
+                        if ( opAttr.size() < 1 )
+                        {
+                            op = DirContext.REMOVE_ATTRIBUTE;
+                        }
+
+                        modList.add( new ModificationItem( op, opAttr ) );
+                    }
+                }
+            }
+            // need to add references to the subentry
+            else if ( isNewNameSelected && ! isOldNameSelected )
+            {
+                for ( int ii = 0; ii < SUBENTRY_OPATTRS.length; ii++ )
+                {
+                    int op = DirContext.REPLACE_ATTRIBUTE;
+                    Attribute opAttr = entry.get( SUBENTRY_OPATTRS[ii] );
+                    if ( opAttr != null )
+                    {
+                        opAttr = ( Attribute ) opAttr.clone();
+                    }
+                    else
+                    {
+                        op = DirContext.ADD_ATTRIBUTE;
+                        opAttr = new LockableAttributeImpl( SUBENTRY_OPATTRS[ii] );
+                    }
+
+                    opAttr.add( subentryDn );
+                    modList.add( new ModificationItem( op, opAttr ) );
+                }
+            }
+        }
+
+        ModificationItem[] mods = new ModificationItem[modList.size()];
+        mods = ( ModificationItem[] ) modList.toArray( mods );
+        return mods;
+    }
+
+
     public void modifyRn( NextInterceptor next, Name name, String newRn, boolean deleteOldRn ) throws NamingException
     {
         Attributes entry = nexus.lookup( name );
@@ -525,7 +635,25 @@
         }
         else
         {
+            if ( hasAdministrativeDescendant( name ) )
+            {
+                String msg = "Will not allow rename operation on entries with administrative descendants.";
+                log.warn( msg );
+                throw new LdapSchemaViolationException( msg, ResultCodeEnum.NOTALLOWEDONRDN );
+            }
             next.modifyRn( name, newRn, deleteOldRn );
+
+            // calculate the new DN now for use below to modify subentry operational
+            // attributes contained within this regular entry with name changes
+            Name newName = ( Name ) name.clone();
+            newName.remove( newName.size() - 1 );
+            newName.add( newRn );
+            ModificationItem[] mods = getModsOnEntryRdnChange( name, newName, entry );
+
+            if ( mods.length > 0 )
+            {
+                nexus.modify( newName, mods );
+            }
         }
     }
 
@@ -573,7 +701,24 @@
         }
         else
         {
+            if ( hasAdministrativeDescendant( oriChildName ) )
+            {
+                String msg = "Will not allow rename operation on entries with administrative descendants.";
+                log.warn( msg );
+                throw new LdapSchemaViolationException( msg, ResultCodeEnum.NOTALLOWEDONRDN );
+            }
             next.move( oriChildName, newParentName, newRn, deleteOldRn );
+
+            // calculate the new DN now for use below to modify subentry operational
+            // attributes contained within this regular entry with name changes
+            Name newName = ( Name ) newParentName.clone();
+            newName.add( newRn );
+            ModificationItem[] mods = getModsOnEntryRdnChange( oriChildName, newName, entry );
+
+            if ( mods.length > 0 )
+            {
+                nexus.modify( newName, mods );
+            }
         }
     }
 
@@ -619,7 +764,24 @@
         }
         else
         {
+            if ( hasAdministrativeDescendant( oriChildName ) )
+            {
+                String msg = "Will not allow rename operation on entries with administrative descendants.";
+                log.warn( msg );
+                throw new LdapSchemaViolationException( msg, ResultCodeEnum.NOTALLOWEDONRDN );
+            }
             next.move( oriChildName, newParentName );
+
+            // calculate the new DN now for use below to modify subentry operational
+            // attributes contained within this regular entry with name changes
+            Name newName = ( Name ) newParentName.clone();
+            newName.add( oriChildName.get( oriChildName.size() - 1 ) );
+            ModificationItem[] mods = getModsOnEntryRdnChange( oriChildName, newName, entry );
+
+            if ( mods.length > 0 )
+            {
+                nexus.modify( newName, mods );
+            }
         }
     }