You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2010/07/16 17:27:19 UTC
svn commit: r964837 [2/2] - in
/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree:
SubentryCache.java SubentryInterceptor.java
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryInterceptor.java?rev=964837&r1=964836&r2=964837&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryInterceptor.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/subtree/SubentryInterceptor.java Fri Jul 16 15:27:19 2010
@@ -22,7 +22,6 @@ package org.apache.directory.server.core
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -133,7 +132,64 @@ public class SubentryInterceptor extends
/** A reference to the SubtreeSpecification AT */
private static AttributeType SUBTREE_SPECIFICATION_AT;
+ /** A reference to the AccessControlSubentries AT */
+ private static AttributeType ACCESS_CONTROL_SUBENTRIES_AT;
+
+ /** A reference to the AccessControlSubentries AT */
+ private static AttributeType SUBSCHEMA_SUBENTRY_AT;
+
+ /** A reference to the CollectiveAttributeSubentries AT */
+ private static AttributeType COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT;
+
+ /** A reference to the TriggerExecutionSubentries AT */
+ private static AttributeType TRIGGER_EXECUTION_SUBENTRIES_AT;
+
+
+ //-------------------------------------------------------------------------------------------
+ // Search filter methods
+ //-------------------------------------------------------------------------------------------
+ /**
+ * SearchResultFilter used to filter out subentries based on objectClass values.
+ */
+ public class HideSubentriesFilter implements EntryFilter
+ {
+ public boolean accept( SearchingOperationContext searchContext, ClonedServerEntry entry ) throws Exception
+ {
+ // See if the requested entry is a subentry
+ if ( subentryCache.hasSubentry( entry.getDn() ) )
+ {
+ return false;
+ }
+
+ // see if we can use objectclass if present
+ return !entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC );
+ }
+ }
+
+
+ /**
+ * SearchResultFilter used to filter out normal entries but shows subentries based on
+ * objectClass values.
+ */
+ public class HideEntriesFilter implements EntryFilter
+ {
+ public boolean accept( SearchingOperationContext searchContext, ClonedServerEntry entry ) throws Exception
+ {
+ // See if the requested entry is a subentry
+ if ( subentryCache.hasSubentry( entry.getDn() ) )
+ {
+ return true;
+ }
+
+ // see if we can use objectclass if present
+ return entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC );
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------
+ // Interceptor initialization
+ //-------------------------------------------------------------------------------------------
/**
* Initialize the Subentry Interceptor
*
@@ -150,6 +206,10 @@ public class SubentryInterceptor extends
OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
ADMINISTRATIVE_ROLE_AT = schemaManager.getAttributeType( SchemaConstants.ADMINISTRATIVE_ROLE_AT );
SUBTREE_SPECIFICATION_AT = schemaManager.getAttributeType( SchemaConstants.SUBTREE_SPECIFICATION_AT );
+ ACCESS_CONTROL_SUBENTRIES_AT = schemaManager.getAttributeType( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT );
+ SUBSCHEMA_SUBENTRY_AT = schemaManager.getAttributeType( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
+ COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT = schemaManager.getAttributeType( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
+ TRIGGER_EXECUTION_SUBENTRIES_AT = schemaManager.getAttributeType( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
ssParser = new SubtreeSpecificationParser( schemaManager );
evaluator = new SubtreeEvaluator( schemaManager );
@@ -221,6 +281,12 @@ public class SubentryInterceptor extends
}
+ //-------------------------------------------------------------------------------------------
+ // Helper methods
+ //-------------------------------------------------------------------------------------------
+ /**
+ * Return the list of AdministrativeRole for a subentry
+ */
private Set<AdministrativeRole> getSubentryAdminRoles( Entry subentry ) throws LdapException
{
Set<AdministrativeRole> adminRoles = new HashSet<AdministrativeRole>();
@@ -256,49 +322,6 @@ public class SubentryInterceptor extends
}
- // -----------------------------------------------------------------------
- // Methods/Code dealing with Subentry Visibility
- // -----------------------------------------------------------------------
-
- public EntryFilteringCursor list( NextInterceptor nextInterceptor, ListOperationContext listContext )
- throws LdapException
- {
- EntryFilteringCursor cursor = nextInterceptor.list( listContext );
-
- if ( !isSubentryVisible( listContext ) )
- {
- cursor.addEntryFilter( new HideSubentriesFilter() );
- }
-
- return cursor;
- }
-
-
- public EntryFilteringCursor search( NextInterceptor nextInterceptor, SearchOperationContext searchContext )
- throws LdapException
- {
- EntryFilteringCursor cursor = nextInterceptor.search( searchContext );
-
- // object scope searches by default return subentries
- if ( searchContext.getScope() == SearchScope.OBJECT )
- {
- return cursor;
- }
-
- // for subtree and one level scope we filter
- if ( !isSubentryVisible( searchContext ) )
- {
- cursor.addEntryFilter( new HideSubentriesFilter() );
- }
- else
- {
- cursor.addEntryFilter( new HideEntriesFilter() );
- }
-
- return cursor;
- }
-
-
/**
* Checks to see if subentries for the search and list operations should be
* made visible based on the availability of the search request control
@@ -318,463 +341,484 @@ public class SubentryInterceptor extends
if ( opContext.hasRequestControl( SUBENTRY_CONTROL ) )
{
SubentriesControl subentriesControl = ( SubentriesControl ) opContext.getRequestControl( SUBENTRY_CONTROL );
+
return subentriesControl.isVisible();
}
return false;
}
-
- // -----------------------------------------------------------------------
- // Methods dealing with entry and subentry addition
- // -----------------------------------------------------------------------
-
/**
- * Evaluates the set of subentry subtrees upon an entry and returns the
- * operational subentry attributes that will be added to the entry if
- * added at the dn specified.
- *
- * @param dn the normalized distinguished name of the entry
- * @param entryAttrs the entry attributes are generated for
- * @return the set of subentry op attrs for an entry
- * @throws Exception if there are problems accessing entry information
+ * Update all the entries under an AP adding the
*/
- public Entry getSubentryAttributes( DN dn, Entry entryAttrs ) throws LdapException
+ private void updateEntries( CoreSession session, DN apDn, SubtreeSpecification ss, DN baseDn, List<EntryAttribute> modifications ) throws LdapException
{
- Entry subentryAttrs = new DefaultEntry( schemaManager, dn );
- Iterator<String> list = subentryCache.nameIterator();
-
- while ( list.hasNext() )
- {
- String subentryDnStr = list.next();
- DN subentryDn = new DN( subentryDnStr );
- subentryDn.normalize( schemaManager.getNormalizerMapping() );
- DN apDn = subentryDn.getParent();
- Subentry subentry = subentryCache.getSubentry( subentryDn );
- SubtreeSpecification ss = subentry.getSubtreeSpecification();
-
- if ( evaluator.evaluate( ss, apDn, dn, entryAttrs ) )
- {
- EntryAttribute operational;
+ ExprNode filter = new PresenceNode( OBJECT_CLASS_AT ); // (objectClass=*)
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ controls.setReturningAttributes( new String[]
+ { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
- if ( subentry.isAccessControlAdminRole() )
- {
- operational = subentryAttrs.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT );
+ SearchOperationContext searchOperationContext = new SearchOperationContext( session,
+ baseDn, filter, controls );
+ searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT,
- schemaManager.lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
- subentryAttrs.put( operational );
- }
+ EntryFilteringCursor subentries = nexus.search( searchOperationContext );
- operational.add( subentryDn.getNormName() );
- }
+ try
+ {
+ while ( subentries.next() )
+ {
+ Entry candidate = subentries.get();
+ DN candidateDn = candidate.getDn();
- if ( subentry.isSchemaAdminRole() )
+ if ( evaluator.evaluate( ss, apDn, candidateDn, candidate ) )
{
- operational = subentryAttrs.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
+ nexus.modify( new ModifyOperationContext( session, candidateDn,
+ getOperationalModsForAdd(
+ candidate, modifications ) ) );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ throw new LdapOtherException( e.getMessage() );
+ }
+ }
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
- subentryAttrs.put( operational );
- }
+
+ /**
+ * Checks if the given DN is a namingContext
+ */
+ private boolean isNamingContext( DN dn ) throws LdapException
+ {
+ DN namingContext = nexus.findSuffix( dn );
+
+ return dn.equals( namingContext );
+ }
+
+
+ /**
+ * Get the administrativePoint role
+ */
+ private void checkAdministrativeRole( OperationContext opContext, DN apDn ) throws LdapException
+ {
+ Entry administrationPoint = opContext.lookup( apDn, ByPassConstants.LOOKUP_BYPASS );
+
+ // The administrativeRole AT must exist and not be null
+ EntryAttribute administrativeRole = administrationPoint.get( ADMINISTRATIVE_ROLE_AT );
- operational.add( subentryDn.getNormName() );
- }
-
- if ( subentry.isCollectiveAdminRole() )
- {
- operational = subentryAttrs.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
+ // check that administrativeRole has something valid in it for us
+ if ( ( administrativeRole == null ) || ( administrativeRole.size() <= 0 ) )
+ {
+ throw new LdapNoSuchAttributeException( I18n.err( I18n.ERR_306, apDn ) );
+ }
+ }
+
+
+ /**
+ * Get the SubtreeSpecification, parse it and stores it into the subentry
+ */
+ private void setSubtreeSpecification( Subentry subentry, Entry entry ) throws LdapException
+ {
+ String subtree = entry.get( SUBTREE_SPECIFICATION_AT ).getString();
+ SubtreeSpecification ss;
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT,
- schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
- subentryAttrs.put( operational );
- }
+ try
+ {
+ ss = ssParser.parse( subtree );
+ }
+ catch ( Exception e )
+ {
+ String msg = I18n.err( I18n.ERR_307, entry.getDn() );
+ LOG.warn( msg );
+ throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
+ }
+
+ subentry.setSubtreeSpecification( ss );
+ }
+
- operational.add( subentryDn.getNormName() );
- }
-
- if ( subentry.isTriggersAdminRole() )
- {
- operational = subentryAttrs.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
+ /**
+ * 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 Exception if there are errors while searching the directory
+ */
+ private boolean hasAdministrativeDescendant( OperationContext opContext, DN name ) throws LdapException
+ {
+ ExprNode filter = new PresenceNode( ADMINISTRATIVE_ROLE_AT );
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT,
- schemaManager.lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
- subentryAttrs.put( operational );
- }
+ SearchOperationContext searchOperationContext = new SearchOperationContext( opContext.getSession(), name,
+ filter, controls );
+ searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
- operational.add( subentryDn.getNormName() );
- }
+ EntryFilteringCursor aps = nexus.search( searchOperationContext );
+
+ try
+ {
+ if ( aps.next() )
+ {
+ aps.close();
+ return true;
}
}
+ catch ( Exception e )
+ {
+ throw new LdapOperationException( e.getMessage() );
+ }
+
- return subentryAttrs;
+ return false;
}
- public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
+ private List<Modification> getModsOnEntryRdnChange( DN oldName, DN newName, Entry entry ) throws LdapException
{
- DN name = addContext.getDn();
- ClonedServerEntry entry = addContext.getEntry();
+ List<Modification> modList = new ArrayList<Modification>();
- if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
+ /*
+ * 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.
+ */
+ for ( DN subentryDn : subentryCache )
{
- // get the name of the administrative point and its administrativeRole attributes
- DN apName = name.getParent();
- Entry administrationPoint = addContext.lookup( apName, ByPassConstants.LOOKUP_BYPASS );
-
- // The administrativeRole AT must exist and not be null
- EntryAttribute administrativeRole = administrationPoint.get( ADMINISTRATIVE_ROLE_AT );
+ DN apDn = subentryDn.getParent();
+ SubtreeSpecification ss = subentryCache.getSubentry( subentryDn ).getSubtreeSpecification();
+ boolean isOldNameSelected = evaluator.evaluate( ss, apDn, oldName, entry );
+ boolean isNewNameSelected = evaluator.evaluate( ss, apDn, newName, entry );
- // check that administrativeRole has something valid in it for us
- if ( ( administrativeRole == null ) || ( administrativeRole.size() <= 0 ) )
+ if ( isOldNameSelected == isNewNameSelected )
{
- throw new LdapNoSuchAttributeException( I18n.err( I18n.ERR_306, apName ) );
+ continue;
}
- /* ----------------------------------------------------------------
- * Build the set of operational attributes to be injected into
- * entries that are contained within the subtree represented by this
- * new subentry. In the process we make sure the proper roles are
- * supported by the administrative point to allow the addition of
- * this new subentry.
- * ----------------------------------------------------------------
- */
- Subentry subentry = new Subentry();
- subentry.setAdministrativeRoles( getSubentryAdminRoles( entry ) );
- Entry operational = getSubentryOperationalAttributes( name, subentry );
-
- /* ----------------------------------------------------------------
- * Parse the subtreeSpecification of the subentry and add it to the
- * SubtreeSpecification cache. If the parse succeeds we continue
- * to add the entry to the DIT. Thereafter we search out entries
- * to modify the subentry operational attributes of.
- * ----------------------------------------------------------------
- */
- String subtree = entry.get( SUBTREE_SPECIFICATION_AT ).getString();
- SubtreeSpecification ss;
-
- try
- {
- ss = ssParser.parse( subtree );
- }
- catch ( Exception e )
+ // need to remove references to the subentry
+ if ( isOldNameSelected && !isNewNameSelected )
{
- String msg = I18n.err( I18n.ERR_307, name.getName() );
- LOG.warn( msg );
- throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
- }
-
- subentry.setSubtreeSpecification( ss );
-
- subentryCache.addSubentry( name, subentry );
-
- next.add( addContext );
-
- /* ----------------------------------------------------------------
- * Find the baseDn for the subentry and use that to search the tree
- * while testing each entry returned for inclusion within the
- * subtree of the subentry's subtreeSpecification. All included
- * entries will have their operational attributes merged with the
- * operational attributes calculated above.
- * ----------------------------------------------------------------
- */
- DN baseDn = ( DN ) apName.clone();
- baseDn.addAll( ss.getBase() );
-
- /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- /// <Ugly-disgusting>
- /// We loop on *all* the entries under this subtree
- /// and we will add some operational attribute in each
- /// one of them. This is *utter crap* !!!
- /// </Ugly-disgusting>
- /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- /// What we should do :
- /// have a filter to process each entry when they are manipulated
- /// instead of doing such a killing modification... This simply does
- /// not scale when we have more than a few hundred entries !
- ExprNode filter = new PresenceNode( OBJECT_CLASS_AT ); // (objectClass=*)
- SearchControls controls = new SearchControls();
- controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
- controls.setReturningAttributes( new String[]
- { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
+ for ( String aSUBENTRY_OPATTRS : SUBENTRY_OPATTRS )
+ {
+ ModificationOperation op = ModificationOperation.REPLACE_ATTRIBUTE;
+ EntryAttribute opAttr = entry.get( aSUBENTRY_OPATTRS );
- SearchOperationContext searchOperationContext = new SearchOperationContext( addContext.getSession(),
- baseDn, filter, controls );
- searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+ if ( opAttr != null )
+ {
+ opAttr = opAttr.clone();
+ opAttr.remove( subentryDn.getNormName() );
- EntryFilteringCursor subentries = nexus.search( searchOperationContext );
+ if ( opAttr.size() < 1 )
+ {
+ op = ModificationOperation.REMOVE_ATTRIBUTE;
+ }
- try
- {
- while ( subentries.next() )
- {
- Entry candidate = subentries.get();
- DN candidateDn = candidate.getDn();
-
- if ( evaluator.evaluate( ss, apName, candidateDn, candidate ) )
- {
- nexus.modify( new ModifyOperationContext( addContext.getSession(), candidateDn, getOperationalModsForAdd(
- candidate, operational ) ) );
+ modList.add( new DefaultModification( op, opAttr ) );
}
}
}
- catch ( Exception e )
+ // need to add references to the subentry
+ else if ( isNewNameSelected && !isOldNameSelected )
{
- throw new LdapOtherException( e.getMessage() );
+ for ( String aSUBENTRY_OPATTRS : SUBENTRY_OPATTRS )
+ {
+ ModificationOperation op = ModificationOperation.ADD_ATTRIBUTE;
+ EntryAttribute opAttr = new DefaultEntryAttribute( aSUBENTRY_OPATTRS, schemaManager
+ .lookupAttributeTypeRegistry( aSUBENTRY_OPATTRS ) );
+ opAttr.add( subentryDn.getNormName() );
+ modList.add( new DefaultModification( op, opAttr ) );
+ }
}
-
- // TODO why are we doing this here if we got the entry from the
- // opContext in the first place - got to look into this
- addContext.setEntry( entry );
}
- else
- {
- Iterator<String> list = subentryCache.nameIterator();
- while ( list.hasNext() )
- {
- String subentryDnStr = list.next();
- DN subentryDn = new DN( subentryDnStr ).normalize( schemaManager.getNormalizerMapping() );
- DN apDn = subentryDn.getParent();
- Subentry subentry = subentryCache.getSubentry( subentryDn );
- SubtreeSpecification ss = subentry.getSubtreeSpecification();
-
- if ( evaluator.evaluate( ss, apDn, name, entry ) )
- {
- EntryAttribute operational;
+ return modList;
+ }
- if ( subentry.isAccessControlAdminRole() )
- {
- operational = entry.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT );
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
- entry.put( operational );
- }
-
- operational.add( subentryDn.getNormName() );
- }
+ // -----------------------------------------------------------------------
+ // Methods dealing with subentry modification
+ // -----------------------------------------------------------------------
- if ( subentry.isSchemaAdminRole() )
- {
- operational = entry.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
+ private Set<AdministrativeRole> getSubentryTypes( Entry entry, List<Modification> mods ) throws LdapException
+ {
+ EntryAttribute ocFinalState = entry.get( OBJECT_CLASS_AT ).clone();
- if ( operational == null )
+ for ( Modification mod : mods )
+ {
+ if ( mod.getAttribute().getId().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) ||
+ mod.getAttribute().getId().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+ {
+ switch ( mod.getOperation() )
+ {
+ case ADD_ATTRIBUTE:
+ for ( Value<?> value : mod.getAttribute() )
{
- operational = new DefaultEntryAttribute( schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
- entry.put( operational );
+ ocFinalState.add( value.getString() );
}
- operational.add( subentryDn.getNormName() );
- }
-
- if ( subentry.isCollectiveAdminRole() )
- {
- operational = entry.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
+ break;
- if ( operational == null )
+ case REMOVE_ATTRIBUTE:
+ for ( Value<?> value : mod.getAttribute() )
{
- operational = new DefaultEntryAttribute( schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
- entry.put( operational );
+ ocFinalState.remove( value.getString() );
}
- operational.add( subentryDn.getNormName() );
- }
-
- if ( subentry.isTriggersAdminRole() )
- {
- operational = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
-
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
- entry.put( operational );
- }
+ break;
- operational.add( subentryDn.getNormName() );
- }
+ case REPLACE_ATTRIBUTE:
+ ocFinalState = mod.getAttribute();
+ break;
}
}
-
- // TODO why are we doing this here if we got the entry from the
- // opContext in the first place - got to look into this
- addContext.setEntry( entry );
-
- next.add( addContext );
}
+
+ Entry attrs = new DefaultEntry( schemaManager, DN.EMPTY_DN );
+ attrs.put( ocFinalState );
+ return getSubentryAdminRoles( attrs );
}
// -----------------------------------------------------------------------
- // Methods dealing with subentry deletion
+ // Utility Methods
// -----------------------------------------------------------------------
- public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
+
+ private List<Modification> getOperationalModsForReplace( DN oldName, DN newName, Subentry subentry, Entry entry )
+ throws Exception
{
- DN name = deleteContext.getDn();
- Entry entry = deleteContext.getEntry();
+ List<Modification> modList = new ArrayList<Modification>();
- // If the entry has a "subentry" Objectclass, we can process the entry.
- if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
+ EntryAttribute operational;
+
+ if ( subentry.isAccessControlAdminRole() )
{
- next.delete( deleteContext );
+ operational = entry.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ).clone();
- Subentry removedSubentry = subentryCache.removeSubentry( name );
- SubtreeSpecification ss = removedSubentry.getSubtreeSpecification();
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT, schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
+ operational.add( newName.toString() );
+ }
+ else
+ {
+ operational.remove( oldName.toString() );
+ operational.add( newName.toString() );
+ }
- /* ----------------------------------------------------------------
- * Find the baseDn for the subentry and use that to search the tree
- * for all entries included by the subtreeSpecification. Then we
- * check the entry for subentry operational attribute that contain
- * the DN of the subentry. These are the subentry operational
- * attributes we remove from the entry in a modify operation.
- * ----------------------------------------------------------------
- */
- DN apName = name.getParent();
- DN baseDn = ( DN ) apName.clone();
- baseDn.addAll( ss.getBase() );
+ modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
+ }
- ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
- SearchControls controls = new SearchControls();
- controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
- controls.setReturningAttributes( new String[]
- { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
+ if ( subentry.isSchemaAdminRole() )
+ {
+ operational = entry.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).clone();
- SearchOperationContext searchOperationContext = new SearchOperationContext( deleteContext.getSession(), baseDn,
- filter, controls );
- searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
+ operational.add( newName.toString() );
+ }
+ else
+ {
+ operational.remove( oldName.toString() );
+ operational.add( newName.toString() );
+ }
- EntryFilteringCursor subentries = nexus.search( searchOperationContext );
+ modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
+ }
- try
+ if ( subentry.isCollectiveAdminRole() )
+ {
+ operational = entry.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ).clone();
+
+ if ( operational == null )
{
- while ( subentries.next() )
- {
- Entry candidate = subentries.get();
- DN candidateDn = candidate.getDn();
-
- if ( evaluator.evaluate( ss, apName, candidateDn, candidate ) )
- {
- nexus.modify( new ModifyOperationContext( deleteContext.getSession(), candidateDn, getOperationalModsForRemove(
- name, candidate ) ) );
- }
- }
-
- subentries.close();
+ operational = new DefaultEntryAttribute( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT,
+ schemaManager.lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
+ operational.add( newName.toString() );
}
- catch ( Exception e )
+ else
{
- throw new LdapOperationException( e.getMessage() );
+ operational.remove( oldName.toString() );
+ operational.add( newName.toString() );
}
+
+ modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
}
- else
+
+ if ( subentry.isTriggersAdminRole() )
{
- next.delete( deleteContext );
+ operational = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ).clone();
+
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT, schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
+ operational.add( newName.toString() );
+ }
+ else
+ {
+ operational.remove( oldName.toString() );
+ operational.add( newName.toString() );
+ }
+
+ modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
}
+
+ return modList;
}
- // -----------------------------------------------------------------------
- // Methods dealing subentry name changes
- // -----------------------------------------------------------------------
+ /**
+ * Gets the subschema operational attributes to be added to or removed from
+ * an entry selected by a subentry's subtreeSpecification.
+ */
+ private List<EntryAttribute> getSubentryOperationalAttributes( DN dn, Subentry subentry ) throws LdapException
+ {
+ List<EntryAttribute> attributes = new ArrayList<EntryAttribute>();
+
+ if ( subentry.isAccessControlAdminRole() )
+ {
+ EntryAttribute accessControlSubentries = new DefaultEntryAttribute( ACCESS_CONTROL_SUBENTRIES_AT, dn.getNormName() );
+ attributes.add( accessControlSubentries );
+ }
+
+ if ( subentry.isSchemaAdminRole() )
+ {
+ EntryAttribute subschemaSubentry = new DefaultEntryAttribute( SUBSCHEMA_SUBENTRY_AT, dn.getNormName() );
+ attributes.add( subschemaSubentry );
+ }
+
+ if ( subentry.isCollectiveAdminRole() )
+ {
+ EntryAttribute collectiveAttributeSubentries = new DefaultEntryAttribute( COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT, dn.getNormName() );
+ attributes.add( collectiveAttributeSubentries );
+ }
+
+ if ( subentry.isTriggersAdminRole() )
+ {
+ EntryAttribute tiggerExecutionSubentries = new DefaultEntryAttribute( TRIGGER_EXECUTION_SUBENTRIES_AT, dn.getNormName() );
+ attributes.add( tiggerExecutionSubentries );
+ }
+
+ return attributes;
+ }
+
/**
- * Checks to see if an entry being renamed has a descendant that is an
- * administrative point.
+ * Calculates the subentry operational attributes to remove from a candidate
+ * entry selected by a subtreeSpecification. When we remove a subentry we
+ * must remove the operational attributes in the entries that were once selected
+ * by the subtree specification of that subentry. To do so we must perform
+ * a modify operation with the set of modifications to perform. This method
+ * calculates those modifications.
*
- * @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 Exception if there are errors while searching the directory
+ * @param subentryDn the distinguished name of the subentry
+ * @param candidate the candidate entry to removed from the
+ * @return the set of modifications required to remove an entry's reference to
+ * a subentry
*/
- private boolean hasAdministrativeDescendant( OperationContext opContext, DN name ) throws LdapException
+ private List<Modification> getOperationalModsForRemove( DN subentryDn, Entry candidate ) throws LdapException
{
- ExprNode filter = new PresenceNode( ADMINISTRATIVE_ROLE_AT );
- SearchControls controls = new SearchControls();
- controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
-
- SearchOperationContext searchOperationContext = new SearchOperationContext( opContext.getSession(), name,
- filter, controls );
- searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+ List<Modification> modList = new ArrayList<Modification>();
+ String dn = subentryDn.getNormName();
- EntryFilteringCursor aps = nexus.search( searchOperationContext );
+ for ( String opAttrId : SUBENTRY_OPATTRS )
+ {
+ EntryAttribute opAttr = candidate.get( opAttrId );
- try
- {
- if ( aps.next() )
+ if ( ( opAttr != null ) && opAttr.contains( dn ) )
{
- aps.close();
- return true;
+ AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( opAttrId );
+ EntryAttribute attr = new DefaultEntryAttribute( opAttrId, attributeType, dn );
+ modList.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attr ) );
}
}
- catch ( Exception e )
+
+ return modList;
+ }
+
+
+ /**
+ * Calculates the subentry operational attributes to add or replace from
+ * a candidate entry selected by a subtree specification. When a subentry
+ * is added or it's specification is modified some entries must have new
+ * operational attributes added to it to point back to the associated
+ * subentry. To do so a modify operation must be performed on entries
+ * selected by the subtree specification. This method calculates the
+ * modify operation to be performed on the entry.
+ */
+ private List<Modification> getOperationalModsForAdd( Entry entry, List<EntryAttribute> operationalAttributes ) throws LdapException
+ {
+ List<Modification> modifications = new ArrayList<Modification>();
+
+ for ( EntryAttribute operationalAttribute : operationalAttributes )
{
- throw new LdapOperationException( e.getMessage() );
+ EntryAttribute opAttrInEntry = entry.get( operationalAttribute.getAttributeType() );
+
+ if ( ( opAttrInEntry != null ) && ( opAttrInEntry.size() > 0 ) )
+ {
+ for ( Value<?> value : opAttrInEntry )
+ {
+ operationalAttribute.add( value );
+ }
+
+ modifications.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operationalAttribute ) );
+ }
+ else
+ {
+ modifications.add( new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, operationalAttribute ) );
+ }
}
-
- return false;
+ return modifications;
}
+
-
- private List<Modification> getModsOnEntryRdnChange( DN oldName, DN newName, Entry entry ) throws LdapException
+ /**
+ * Get the list of modification to apply to all the entries
+ */
+ private List<Modification> getModsOnEntryModification( DN name, Entry oldEntry, Entry newEntry ) throws LdapException
{
List<Modification> modList = new ArrayList<Modification>();
- /*
- * 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<String> subentries = subentryCache.nameIterator();
-
- while ( subentries.hasNext() )
+ for ( DN subentryDn : subentryCache )
{
- String subentryDnStr = subentries.next();
- DN subentryDn = new DN( subentryDnStr ).normalize( schemaManager.getNormalizerMapping() );
DN apDn = subentryDn.getParent();
SubtreeSpecification ss = subentryCache.getSubentry( subentryDn ).getSubtreeSpecification();
- boolean isOldNameSelected = evaluator.evaluate( ss, apDn, oldName, entry );
- boolean isNewNameSelected = evaluator.evaluate( ss, apDn, newName, entry );
+ boolean isOldEntrySelected = evaluator.evaluate( ss, apDn, name, oldEntry );
+ boolean isNewEntrySelected = evaluator.evaluate( ss, apDn, name, newEntry );
- if ( isOldNameSelected == isNewNameSelected )
+ if ( isOldEntrySelected == isNewEntrySelected )
{
continue;
}
// need to remove references to the subentry
- if ( isOldNameSelected && !isNewNameSelected )
+ if ( isOldEntrySelected && !isNewEntrySelected )
{
for ( String aSUBENTRY_OPATTRS : SUBENTRY_OPATTRS )
{
ModificationOperation op = ModificationOperation.REPLACE_ATTRIBUTE;
- EntryAttribute opAttr = entry.get( aSUBENTRY_OPATTRS );
+ EntryAttribute opAttr = oldEntry.get( aSUBENTRY_OPATTRS );
if ( opAttr != null )
{
opAttr = opAttr.clone();
- opAttr.remove( subentryDnStr );
+ opAttr.remove( subentryDn.getNormName() );
if ( opAttr.size() < 1 )
{
@@ -786,214 +830,201 @@ public class SubentryInterceptor extends
}
}
// need to add references to the subentry
- else if ( isNewNameSelected && !isOldNameSelected )
+ else if ( isNewEntrySelected && !isOldEntrySelected )
{
- for ( String aSUBENTRY_OPATTRS : SUBENTRY_OPATTRS )
+ for ( String attribute : SUBENTRY_OPATTRS )
{
ModificationOperation op = ModificationOperation.ADD_ATTRIBUTE;
- EntryAttribute opAttr = new DefaultEntryAttribute( aSUBENTRY_OPATTRS, schemaManager
- .lookupAttributeTypeRegistry( aSUBENTRY_OPATTRS ) );
- opAttr.add( subentryDnStr );
+ AttributeType type = schemaManager.lookupAttributeTypeRegistry( attribute );
+ EntryAttribute opAttr = new DefaultEntryAttribute( attribute, type );
+ opAttr.add( subentryDn.getNormName() );
modList.add( new DefaultModification( op, opAttr ) );
}
}
}
- return modList;
- }
-
-
- public void rename( NextInterceptor next, RenameOperationContext renameContext ) throws LdapException
- {
- DN oldDn = renameContext.getDn();
-
- Entry entry = renameContext.getEntry().getClonedEntry();
-
- if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
- {
- // @Todo To be reviewed !!!
- Subentry subentry = subentryCache.removeSubentry( oldDn );
- SubtreeSpecification ss = subentry.getSubtreeSpecification();
- DN apName = oldDn.getParent();
- DN baseDn = ( DN ) apName.clone();
- baseDn.addAll( ss.getBase() );
- DN newName = oldDn.getParent();
-
- newName.add( renameContext.getNewRdn() );
- newName.normalize( schemaManager.getNormalizerMapping() );
-
- subentryCache.addSubentry( newName, subentry );
- next.rename( renameContext );
-
- subentry = subentryCache.getSubentry( newName );
- ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
- SearchControls controls = new SearchControls();
- controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
- controls.setReturningAttributes( new String[]
- { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
-
- SearchOperationContext searchOperationContext = new SearchOperationContext( renameContext.getSession(), baseDn,
- filter, controls );
- searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
-
- EntryFilteringCursor subentries = nexus.search( searchOperationContext );
-
- try
- {
- while ( subentries.next() )
- {
- Entry candidate = subentries.get();
- DN dn = candidate.getDn();
- dn.normalize( schemaManager.getNormalizerMapping() );
-
- if ( evaluator.evaluate( ss, apName, dn, candidate ) )
- {
- nexus.modify( new ModifyOperationContext( renameContext.getSession(), dn, getOperationalModsForReplace(
- oldDn, newName, subentry, candidate ) ) );
- }
- }
-
- subentries.close();
- }
- catch ( Exception e )
- {
- throw new LdapOperationException( e.getMessage() );
- }
- }
- else
+ return modList;
+ }
+
+
+ //-------------------------------------------------------------------------------------------
+ // Interceptor API methods
+ //-------------------------------------------------------------------------------------------
+ /**
+ * {@inheritDoc}
+ */
+ public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
+ {
+ DN dn = addContext.getDn();
+ ClonedServerEntry entry = addContext.getEntry();
+
+ // Check that the added entry is a subentry
+ if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
{
- if ( hasAdministrativeDescendant( renameContext, oldDn ) )
+ // get the name of the administrative point and its administrativeRole attributes
+ // The AP must be the parent DN, but we also have to check that the given DN
+ // is not the rootDSE or a NamingContext
+ if ( dn.isRootDSE() || isNamingContext( dn ) )
{
- String msg = I18n.err( I18n.ERR_308 );
- LOG.warn( msg );
- throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
+ // Not allowed : we can't get a parent in those cases
+ throw new LdapOtherException( "Cannot find an AdministrativePoint for " + dn );
}
+
+ // Get the administrativePoint role
+ DN apDn = dn.getParent();
+ checkAdministrativeRole( addContext, apDn );
- next.rename( renameContext );
+ /* ----------------------------------------------------------------
+ * Build the set of operational attributes to be injected into
+ * entries that are contained within the subtree represented by this
+ * new subentry. In the process we make sure the proper roles are
+ * supported by the administrative point to allow the addition of
+ * this new subentry.
+ * ----------------------------------------------------------------
+ */
+ Subentry subentry = new Subentry();
+ subentry.setAdministrativeRoles( getSubentryAdminRoles( entry ) );
+ List<EntryAttribute> operationalAttributes = getSubentryOperationalAttributes( dn, subentry );
- // calculate the new DN now for use below to modify subentry operational
- // attributes contained within this regular entry with name changes
- DN newName = renameContext.getNewDn();
+ /* ----------------------------------------------------------------
+ * Parse the subtreeSpecification of the subentry and add it to the
+ * SubtreeSpecification cache. If the parse succeeds we continue
+ * to add the entry to the DIT. Thereafter we search out entries
+ * to modify the subentry operational attributes of.
+ * ----------------------------------------------------------------
+ */
+ setSubtreeSpecification( subentry, entry );
+ subentryCache.addSubentry( dn, subentry );
- List<Modification> mods = getModsOnEntryRdnChange( oldDn, newName, entry );
+ // Now inject the subentry into the backend
+ next.add( addContext );
- if ( mods.size() > 0 )
- {
- nexus.modify( new ModifyOperationContext( renameContext.getSession(), newName, mods ) );
- }
+ /* ----------------------------------------------------------------
+ * Find the baseDn for the subentry and use that to search the tree
+ * while testing each entry returned for inclusion within the
+ * subtree of the subentry's subtreeSpecification. All included
+ * entries will have their operational attributes merged with the
+ * operational attributes calculated above.
+ * ----------------------------------------------------------------
+ */
+ DN baseDn = ( DN ) apDn.clone();
+ baseDn.addAll( subentry.getSubtreeSpecification().getBase() );
+
+ updateEntries( addContext.getSession(), apDn, subentry.getSubtreeSpecification(), baseDn, operationalAttributes );
+
+ // TODO why are we doing this here if we got the entry from the
+ // opContext in the first place - got to look into this
+ addContext.setEntry( entry );
}
- }
+ else
+ {
+ // The added entry is not a Subentry
+ // Nevertheless, we have to check if the entry is added into an AdministrativePoint
+ // and is associated with a SubtreeSpecification
+ for ( DN subentryDn : subentryCache )
+ {
+ DN apDn = subentryDn.getParent();
+ Subentry subentry = subentryCache.getSubentry( subentryDn );
+ SubtreeSpecification ss = subentry.getSubtreeSpecification();
+ if ( evaluator.evaluate( ss, apDn, dn, entry ) )
+ {
+ EntryAttribute operational;
- public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
- {
- DN oldDn = moveAndRenameContext.getDn();
- DN newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
+ if ( subentry.isAccessControlAdminRole() )
+ {
+ operational = entry.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT );
- Entry entry = moveAndRenameContext.getOriginalEntry();
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
+ entry.put( operational );
+ }
- if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
- {
- Subentry subentry = subentryCache.removeSubentry( oldDn );
- SubtreeSpecification ss = subentry.getSubtreeSpecification();
- DN apName = oldDn.getParent();
- DN baseDn = ( DN ) apName.clone();
- baseDn.addAll( ss.getBase() );
- DN newName = newSuperiorDn.getParent();
+ operational.add( subentryDn.getNormName() );
+ }
- newName.add( moveAndRenameContext.getNewRdn() );
- newName.normalize( schemaManager.getNormalizerMapping() );
+ if ( subentry.isSchemaAdminRole() )
+ {
+ operational = entry.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
- subentryCache.addSubentry( newName, subentry );
-
- next.moveAndRename( moveAndRenameContext );
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
+ entry.put( operational );
+ }
- subentry = subentryCache.getSubentry( newName );
+ operational.add( subentryDn.getNormName() );
+ }
- ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
- SearchControls controls = new SearchControls();
- controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
- controls.setReturningAttributes( new String[]
- { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
+ if ( subentry.isCollectiveAdminRole() )
+ {
+ operational = entry.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
- SearchOperationContext searchOperationContext = new SearchOperationContext( moveAndRenameContext.getSession(), baseDn,
- filter, controls );
- searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
+ entry.put( operational );
+ }
- EntryFilteringCursor subentries = nexus.search( searchOperationContext );
+ operational.add( subentryDn.getNormName() );
+ }
- try
- {
- while ( subentries.next() )
- {
- Entry candidate = subentries.get();
- DN dn = candidate.getDn();
- dn.normalize( schemaManager.getNormalizerMapping() );
-
- if ( evaluator.evaluate( ss, apName, dn, candidate ) )
+ if ( subentry.isTriggersAdminRole() )
{
- nexus.modify( new ModifyOperationContext( moveAndRenameContext.getSession(), dn, getOperationalModsForReplace(
- oldDn, newName, subentry, candidate ) ) );
+ operational = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
+
+ if ( operational == null )
+ {
+ operational = new DefaultEntryAttribute( schemaManager
+ .lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
+ entry.put( operational );
+ }
+
+ operational.add( subentryDn.getNormName() );
}
}
-
- subentries.close();
- }
- catch ( Exception e )
- {
- throw new LdapOperationException( e.getMessage() );
- }
- }
- else
- {
- if ( hasAdministrativeDescendant( moveAndRenameContext, oldDn ) )
- {
- String msg = I18n.err( I18n.ERR_308 );
- LOG.warn( msg );
- throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
}
- next.moveAndRename( moveAndRenameContext );
-
- // calculate the new DN now for use below to modify subentry operational
- // attributes contained within this regular entry with name changes
- DN newDn = moveAndRenameContext.getNewDn();
- List<Modification> mods = getModsOnEntryRdnChange( oldDn, newDn, entry );
+ // TODO why are we doing this here if we got the entry from the
+ // opContext in the first place - got to look into this
+ addContext.setEntry( entry );
- if ( mods.size() > 0 )
- {
- nexus.modify( new ModifyOperationContext( moveAndRenameContext.getSession(), newDn, mods ) );
- }
+ next.add( addContext );
}
}
-
+
/**
* {@inheritDoc}
*/
- public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
+ public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
{
- DN oldDn = moveContext.getDn();
- DN newSuperiorDn = moveContext.getNewSuperior();
-
- Entry entry = moveContext.getOriginalEntry();
+ DN name = deleteContext.getDn();
+ Entry entry = deleteContext.getEntry();
+ // If the entry has a "subentry" Objectclass, we can process the entry.
if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
{
- Subentry subentry = subentryCache.removeSubentry( oldDn );
- SubtreeSpecification ss = subentry.getSubtreeSpecification();
- DN apName = oldDn.getParent();
- DN baseDn = ( DN ) apName.clone();
- baseDn.addAll( ss.getBase() );
- DN newName = (DN)newSuperiorDn.clone();
- newName.add( oldDn.getRdn() );
- newName.normalize( schemaManager.getNormalizerMapping() );
+ next.delete( deleteContext );
- subentryCache.addSubentry( newName, subentry );
-
- next.move( moveContext );
+ Subentry removedSubentry = subentryCache.removeSubentry( name );
+ SubtreeSpecification ss = removedSubentry.getSubtreeSpecification();
- subentry = subentryCache.getSubentry( newName );
+ /* ----------------------------------------------------------------
+ * Find the baseDn for the subentry and use that to search the tree
+ * for all entries included by the subtreeSpecification. Then we
+ * check the entry for subentry operational attribute that contain
+ * the DN of the subentry. These are the subentry operational
+ * attributes we remove from the entry in a modify operation.
+ * ----------------------------------------------------------------
+ */
+ DN apName = name.getParent();
+ DN baseDn = ( DN ) apName.clone();
+ baseDn.addAll( ss.getBase() );
ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
SearchControls controls = new SearchControls();
@@ -1001,7 +1032,7 @@ public class SubentryInterceptor extends
controls.setReturningAttributes( new String[]
{ SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
- SearchOperationContext searchOperationContext = new SearchOperationContext( moveContext.getSession(), baseDn,
+ SearchOperationContext searchOperationContext = new SearchOperationContext( deleteContext.getSession(), baseDn,
filter, controls );
searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
@@ -1009,92 +1040,46 @@ public class SubentryInterceptor extends
try
{
- // Modify all the entries under this subentry
while ( subentries.next() )
{
Entry candidate = subentries.get();
- DN dn = candidate.getDn();
- dn.normalize( schemaManager.getNormalizerMapping() );
+ DN candidateDn = candidate.getDn();
- if ( evaluator.evaluate( ss, apName, dn, candidate ) )
+ if ( evaluator.evaluate( ss, apName, candidateDn, candidate ) )
{
- nexus.modify( new ModifyOperationContext( moveContext.getSession(), dn, getOperationalModsForReplace(
- oldDn, newName, subentry, candidate ) ) );
- }
- }
-
- subentries.close();
- }
- catch ( Exception e )
- {
- throw new LdapOperationException( e.getMessage() );
- }
- }
- else
- {
- if ( hasAdministrativeDescendant( moveContext, oldDn ) )
- {
- String msg = I18n.err( I18n.ERR_308 );
- LOG.warn( msg );
- throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
- }
-
- next.move( moveContext );
-
- // calculate the new DN now for use below to modify subentry operational
- // attributes contained within this regular entry with name changes
- DN newName = moveContext.getNewDn();
- List<Modification> mods = getModsOnEntryRdnChange( oldDn, newName, entry );
-
- if ( mods.size() > 0 )
+ nexus.modify( new ModifyOperationContext( deleteContext.getSession(), candidateDn, getOperationalModsForRemove(
+ name, candidate ) ) );
+ }
+ }
+
+ subentries.close();
+ }
+ catch ( Exception e )
{
- nexus.modify( new ModifyOperationContext( moveContext.getSession(), newName, mods ) );
+ throw new LdapOperationException( e.getMessage() );
}
}
+ else
+ {
+ next.delete( deleteContext );
+ }
}
-
- // -----------------------------------------------------------------------
- // Methods dealing with subentry modification
- // -----------------------------------------------------------------------
-
- private Set<AdministrativeRole> getSubentryTypes( Entry entry, List<Modification> mods ) throws LdapException
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntryFilteringCursor list( NextInterceptor nextInterceptor, ListOperationContext listContext )
+ throws LdapException
{
- EntryAttribute ocFinalState = entry.get( OBJECT_CLASS_AT ).clone();
+ EntryFilteringCursor cursor = nextInterceptor.list( listContext );
- for ( Modification mod : mods )
+ if ( !isSubentryVisible( listContext ) )
{
- if ( mod.getAttribute().getId().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) ||
- mod.getAttribute().getId().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT_OID ) )
- {
- switch ( mod.getOperation() )
- {
- case ADD_ATTRIBUTE:
- for ( Value<?> value : mod.getAttribute() )
- {
- ocFinalState.add( value.getString() );
- }
-
- break;
-
- case REMOVE_ATTRIBUTE:
- for ( Value<?> value : mod.getAttribute() )
- {
- ocFinalState.remove( value.getString() );
- }
-
- break;
-
- case REPLACE_ATTRIBUTE:
- ocFinalState = mod.getAttribute();
- break;
- }
- }
+ cursor.addEntryFilter( new HideSubentriesFilter() );
}
- Entry attrs = new DefaultEntry( schemaManager, DN.EMPTY_DN );
- attrs.put( ocFinalState );
- return getSubentryAdminRoles( attrs );
+ return cursor;
}
@@ -1185,7 +1170,7 @@ public class SubentryInterceptor extends
// search for all selected entries by the new SS and add references to subentry
subentry = subentryCache.getSubentry( dn );
- Entry operational = getSubentryOperationalAttributes( dn, subentry );
+ List<EntryAttribute> operationalAttributes = getSubentryOperationalAttributes( dn, subentry );
DN newBaseDn = ( DN ) apName.clone();
newBaseDn.addAll( ssNew.getBase() );
@@ -1204,7 +1189,7 @@ public class SubentryInterceptor extends
if ( evaluator.evaluate( ssNew, apName, candidateDn, candidate ) )
{
nexus.modify( new ModifyOperationContext( modifyContext.getSession(), candidateDn,
- getOperationalModsForAdd( candidate, operational ) ) );
+ getOperationalModsForAdd( candidate, operationalAttributes ) ) );
}
}
}
@@ -1232,338 +1217,366 @@ public class SubentryInterceptor extends
}
- // -----------------------------------------------------------------------
- // Utility Methods
- // -----------------------------------------------------------------------
-
- private List<Modification> getOperationalModsForReplace( DN oldName, DN newName, Subentry subentry, Entry entry )
- throws Exception
+ /**
+ * {@inheritDoc}
+ */
+ public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
{
- List<Modification> modList = new ArrayList<Modification>();
+ DN oldDn = moveContext.getDn();
+ DN newSuperiorDn = moveContext.getNewSuperior();
- EntryAttribute operational;
+ Entry entry = moveContext.getOriginalEntry();
- if ( subentry.isAccessControlAdminRole() )
+ if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
{
- operational = entry.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ).clone();
+ Subentry subentry = subentryCache.removeSubentry( oldDn );
+ SubtreeSpecification ss = subentry.getSubtreeSpecification();
+ DN apName = oldDn.getParent();
+ DN baseDn = ( DN ) apName.clone();
+ baseDn.addAll( ss.getBase() );
+ DN newName = (DN)newSuperiorDn.clone();
+ newName.add( oldDn.getRdn() );
+ newName.normalize( schemaManager.getNormalizerMapping() );
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT, schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
- operational.add( newName.toString() );
- }
- else
- {
- operational.remove( oldName.toString() );
- operational.add( newName.toString() );
- }
+ subentryCache.addSubentry( newName, subentry );
+
+ next.move( moveContext );
- modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
- }
+ subentry = subentryCache.getSubentry( newName );
- if ( subentry.isSchemaAdminRole() )
- {
- operational = entry.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).clone();
+ ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ controls.setReturningAttributes( new String[]
+ { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
- if ( operational == null )
+ SearchOperationContext searchOperationContext = new SearchOperationContext( moveContext.getSession(), baseDn,
+ filter, controls );
+ searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+
+ EntryFilteringCursor subentries = nexus.search( searchOperationContext );
+
+ try
{
- operational = new DefaultEntryAttribute( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
- operational.add( newName.toString() );
+ // Modify all the entries under this subentry
+ while ( subentries.next() )
+ {
+ Entry candidate = subentries.get();
+ DN dn = candidate.getDn();
+ dn.normalize( schemaManager.getNormalizerMapping() );
+
+ if ( evaluator.evaluate( ss, apName, dn, candidate ) )
+ {
+ nexus.modify( new ModifyOperationContext( moveContext.getSession(), dn, getOperationalModsForReplace(
+ oldDn, newName, subentry, candidate ) ) );
+ }
+ }
+
+ subentries.close();
}
- else
+ catch ( Exception e )
{
- operational.remove( oldName.toString() );
- operational.add( newName.toString() );
+ throw new LdapOperationException( e.getMessage() );
}
-
- modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
}
-
- if ( subentry.isCollectiveAdminRole() )
+ else
{
- operational = entry.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ).clone();
-
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT,
- schemaManager.lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
- operational.add( newName.toString() );
- }
- else
+ if ( hasAdministrativeDescendant( moveContext, oldDn ) )
{
- operational.remove( oldName.toString() );
- operational.add( newName.toString() );
+ String msg = I18n.err( I18n.ERR_308 );
+ LOG.warn( msg );
+ throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
}
- modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
- }
+ next.move( moveContext );
- if ( subentry.isTriggersAdminRole() )
- {
- operational = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ).clone();
+ // calculate the new DN now for use below to modify subentry operational
+ // attributes contained within this regular entry with name changes
+ DN newName = moveContext.getNewDn();
+ List<Modification> mods = getModsOnEntryRdnChange( oldDn, newName, entry );
- if ( operational == null )
- {
- operational = new DefaultEntryAttribute( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT, schemaManager
- .lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
- operational.add( newName.toString() );
- }
- else
+ if ( mods.size() > 0 )
{
- operational.remove( oldName.toString() );
- operational.add( newName.toString() );
+ nexus.modify( new ModifyOperationContext( moveContext.getSession(), newName, mods ) );
}
-
- modList.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, operational ) );
}
-
- return modList;
}
- /**
- * Gets the subschema operational attributes to be added to or removed from
- * an entry selected by a subentry's subtreeSpecification.
- *
- * @param name the normalized distinguished name of the subentry (the value of op attrs)
- * @param subentry the subentry to get attributes from
- * @return the set of attributes to be added or removed from entries
- */
- private Entry getSubentryOperationalAttributes( DN name, Subentry subentry ) throws LdapException
+ public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
{
- Entry operational = new DefaultEntry( schemaManager, name );
+ DN oldDn = moveAndRenameContext.getDn();
+ DN newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
- if ( subentry.isAccessControlAdminRole() )
- {
- if ( operational.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) == null )
- {
- operational.put( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT, name.getNormName() );
- }
- else
- {
- operational.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ).add( name.getNormName() );
- }
- }
-
- if ( subentry.isSchemaAdminRole() )
- {
- if ( operational.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) == null )
- {
- operational.put( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, name.getNormName() );
- }
- else
- {
- operational.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).add( name.getNormName() );
- }
- }
-
- if ( subentry.isCollectiveAdminRole() )
+ Entry entry = moveAndRenameContext.getOriginalEntry();
+
+ if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
{
- if ( operational.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) == null )
+ Subentry subentry = subentryCache.removeSubentry( oldDn );
+ SubtreeSpecification ss = subentry.getSubtreeSpecification();
+ DN apName = oldDn.getParent();
+ DN baseDn = ( DN ) apName.clone();
+ baseDn.addAll( ss.getBase() );
+ DN newName = newSuperiorDn.getParent();
+
+ newName.add( moveAndRenameContext.getNewRdn() );
+ newName.normalize( schemaManager.getNormalizerMapping() );
+
+ subentryCache.addSubentry( newName, subentry );
+
+ next.moveAndRename( moveAndRenameContext );
+
+ subentry = subentryCache.getSubentry( newName );
+
+ ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ controls.setReturningAttributes( new String[]
+ { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
+
+ SearchOperationContext searchOperationContext = new SearchOperationContext( moveAndRenameContext.getSession(), baseDn,
+ filter, controls );
+ searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+
+ EntryFilteringCursor subentries = nexus.search( searchOperationContext );
+
+ try
{
- operational.put( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT, name.getNormName() );
+ while ( subentries.next() )
+ {
+ Entry candidate = subentries.get();
+ DN dn = candidate.getDn();
+ dn.normalize( schemaManager.getNormalizerMapping() );
+
+ if ( evaluator.evaluate( ss, apName, dn, candidate ) )
+ {
+ nexus.modify( new ModifyOperationContext( moveAndRenameContext.getSession(), dn, getOperationalModsForReplace(
+ oldDn, newName, subentry, candidate ) ) );
+ }
+ }
+
+ subentries.close();
}
- else
+ catch ( Exception e )
{
- operational.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ).add( name.getNormName() );
+ throw new LdapOperationException( e.getMessage() );
}
}
-
- if ( subentry.isTriggersAdminRole() )
+ else
{
- if ( operational.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) == null )
+ if ( hasAdministrativeDescendant( moveAndRenameContext, oldDn ) )
{
- operational.put( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT, name.getNormName() );
+ String msg = I18n.err( I18n.ERR_308 );
+ LOG.warn( msg );
+ throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
}
- else
+
+ next.moveAndRename( moveAndRenameContext );
+
+ // calculate the new DN now for use below to modify subentry operational
+ // attributes contained within this regular entry with name changes
+ DN newDn = moveAndRenameContext.getNewDn();
+ List<Modification> mods = getModsOnEntryRdnChange( oldDn, newDn, entry );
+
+ if ( mods.size() > 0 )
{
- operational.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ).add( name.getNormName() );
+ nexus.modify( new ModifyOperationContext( moveAndRenameContext.getSession(), newDn, mods ) );
}
}
-
- return operational;
}
- /**
- * Calculates the subentry operational attributes to remove from a candidate
- * entry selected by a subtreeSpecification. When we remove a subentry we
- * must remove the operational attributes in the entries that were once selected
- * by the subtree specification of that subentry. To do so we must perform
- * a modify operation with the set of modifications to perform. This method
- * calculates those modifications.
- *
- * @param subentryDn the distinguished name of the subentry
- * @param candidate the candidate entry to removed from the
- * @return the set of modifications required to remove an entry's reference to
- * a subentry
- */
- private List<Modification> getOperationalModsForRemove( DN subentryDn, Entry candidate ) throws LdapException
+ public void rename( NextInterceptor next, RenameOperationContext renameContext ) throws LdapException
{
- List<Modification> modList = new ArrayList<Modification>();
- String dn = subentryDn.getNormName();
+ DN oldDn = renameContext.getDn();
- for ( String opAttrId : SUBENTRY_OPATTRS )
- {
- EntryAttribute opAttr = candidate.get( opAttrId );
+ Entry entry = renameContext.getEntry().getClonedEntry();
- if ( ( opAttr != null ) && opAttr.contains( dn ) )
- {
- AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( opAttrId );
- EntryAttribute attr = new DefaultEntryAttribute( opAttrId, attributeType, dn );
- modList.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attr ) );
- }
- }
+ if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
+ {
+ // @Todo To be reviewed !!!
+ Subentry subentry = subentryCache.removeSubentry( oldDn );
+ SubtreeSpecification ss = subentry.getSubtreeSpecification();
+ DN apName = oldDn.getParent();
+ DN baseDn = ( DN ) apName.clone();
+ baseDn.addAll( ss.getBase() );
+ DN newName = oldDn.getParent();
- return modList;
- }
+ newName.add( renameContext.getNewRdn() );
+ newName.normalize( schemaManager.getNormalizerMapping() );
+ subentryCache.addSubentry( newName, subentry );
+ next.rename( renameContext );
- /**
- * Calculates the subentry operational attributes to add or replace from
- * a candidate entry selected by a subtree specification. When a subentry
- * is added or it's specification is modified some entries must have new
- * operational attributes added to it to point back to the associated
- * subentry. To do so a modify operation must be performed on entries
- * selected by the subtree specification. This method calculates the
- * modify operation to be performed on the entry.
- *
- * @param entry the entry being modified
- * @param operational the set of operational attributes supported by the AP
- * of the subentry
- * @return the set of modifications needed to update the entry
- * @throws Exception if there are probelms accessing modification items
- */
- public List<Modification> getOperationalModsForAdd( Entry entry, Entry operational ) throws LdapException
- {
- List<Modification> modList = new ArrayList<Modification>();
+ subentry = subentryCache.getSubentry( newName );
+ ExprNode filter = new PresenceNode( OBJECT_CLASS_AT );
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ controls.setReturningAttributes( new String[]
+ { SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.ALL_USER_ATTRIBUTES } );
- for ( AttributeType attributeType : operational.getAttributeTypes() )
- {
- ModificationOperation op = ModificationOperation.REPLACE_ATTRIBUTE;
- EntryAttribute result = new DefaultEntryAttribute( attributeType );
- EntryAttribute opAttrAdditions = operational.get( attributeType );
- EntryAttribute opAttrInEntry = entry.get( attributeType );
+ SearchOperationContext searchOperationContext = new SearchOperationContext( renameContext.getSession(), baseDn,
+ filter, controls );
+ searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
- for ( Value<?> value : opAttrAdditions )
- {
- result.add( value );
- }
+ EntryFilteringCursor subentries = nexus.search( searchOperationContext );
- if ( opAttrInEntry != null && opAttrInEntry.size() > 0 )
+ try
{
- for ( Value<?> value : opAttrInEntry )
+ while ( subentries.next() )
{
- result.add( value );
+ Entry candidate = subentries.get();
+ DN dn = candidate.getDn();
+ dn.normalize( schemaManager.getNormalizerMapping() );
+
+ if ( evaluator.evaluate( ss, apName, dn, candidate ) )
+ {
+ nexus.modify( new ModifyOperationContext( renameContext.getSession(), dn, getOperationalModsForReplace(
+ oldDn, newName, subentry, candidate ) ) );
+ }
}
+
+ subentries.close();
}
- else
+ catch ( Exception e )
{
- op = ModificationOperation.ADD_ATTRIBUTE;
+ throw new LdapOperationException( e.getMessage() );
}
-
- modList.add( new DefaultModification( op, result ) );
}
-
- return modList;
- }
-
- /**
- * SearchResultFilter used to filter out subentries based on objectClass values.
- */
- public class HideSubentriesFilter implements EntryFilter
- {
- public boolean accept( SearchingOperationContext searchContext, ClonedServerEntry entry ) throws Exception
+ else
{
- // see if we can get a match without normalization
- if ( subentryCache.hasSubentry( entry.getDn() ) )
+ if ( hasAdministrativeDescendant( renameContext, oldDn ) )
{
- return false;
+ String msg = I18n.err( I18n.ERR_308 );
+ LOG.warn( msg );
+ throw new LdapSchemaViolationException( ResultCodeEnum.NOT_ALLOWED_ON_RDN, msg );
}
- // see if we can use objectclass if present
- return !entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC );
+ next.rename( renameContext );
+
+ // calculate the new DN now for use below to modify subentry operational
+ // attributes contained within this regular entry with name changes
+ DN newName = renameContext.getNewDn();
+
+ List<Modification> mods = getModsOnEntryRdnChange( oldDn, newName, entry );
+
+ if ( mods.size() > 0 )
+ {
+ nexus.modify( new ModifyOperationContext( renameContext.getSession(), newName, mods ) );
+ }
}
}
+
/**
- * SearchResultFilter used to filter out normal entries but shows subentries based on
- * objectClass values.
+ * {@inheritDoc}
*/
- public class HideEntriesFilter implements EntryFilter
+ public EntryFilteringCursor search( NextInterceptor nextInterceptor, SearchOperationContext searchContext )
+ throws LdapException
{
- public boolean accept( SearchingOperationContext searchContext, ClonedServerEntry entry ) throws Exception
+ EntryFilteringCursor cursor = nextInterceptor.search( searchContext );
+
+ // object scope searches by default return subentries
+ if ( searchContext.getScope() == SearchScope.OBJECT )
{
- // see if we can get a match without normalization
- if ( subentryCache.hasSubentry( entry.getDn() ) )
- {
- return true;
- }
+ return cursor;
+ }
- // see if we can use objectclass if present
- return entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC );
[... 137 lines stripped ...]