public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws Exception
{
DN name = opContext.getDn();
List<Modification> mods = opContext.getModItems();
ServerEntry entry = opContext.lookup( name, ByPassConstants.LOOKUP_BYPASS );
ServerEntry oldEntry = ( ServerEntry ) entry.clone();
EntryAttribute objectClasses = entry.get( objectClassType );
boolean isSubtreeSpecificationModification = false;
Modification subtreeMod = null;
for ( Modification mod : mods )
{
if ( SchemaConstants.SUBTREE_SPECIFICATION_AT.equalsIgnoreCase( mod.getAttribute().getId() ) )
{
isSubtreeSpecificationModification = true;
subtreeMod = mod;
}
}
if ( objectClasses.contains( SchemaConstants.SUBENTRY_OC ) && isSubtreeSpecificationModification )
{
SubtreeSpecification ssOld = subentryCache.removeSubentry( name.getNormName() ).getSubtreeSpecification();
SubtreeSpecification ssNew;
try
{
ssNew = ssParser.parse( subtreeMod.getAttribute().getString() );
}
catch ( Exception e )
{
String msg = I18n.err( I18n.ERR_71 );
LOG.error( msg, e );
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
}
subentryCache.setSubentry( name.getNormName(), ssNew, getSubentryTypes( entry, mods ) );
next.modify( opContext );
// search for all entries selected by the old SS and remove references to subentry
DN apName = ( DN ) name.clone();
apName.remove( apName.size() - 1 );
DN oldBaseDn = ( DN ) apName.clone();
oldBaseDn.addAll( ssOld.getBase() );
ExprNode filter = new PresenceNode( schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.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( opContext.getSession(), oldBaseDn,
filter, controls );
searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
EntryFilteringCursor subentries = nexus.search( searchOperationContext );
while ( subentries.next() )
{
ServerEntry candidate = subentries.get();
DN dn = candidate.getDn();
dn.normalize( schemaManager.getNormalizerMapping() );
if ( evaluator.evaluate( ssOld, apName, dn, candidate ) )
{
nexus.modify( new ModifyOperationContext( opContext.getSession(), dn,
getOperationalModsForRemove( name, candidate ) ) );
}
}
// search for all selected entries by the new SS and add references to subentry
Subentry subentry = subentryCache.getSubentry( name.getNormName() );
ServerEntry operational = getSubentryOperatationalAttributes( name, subentry );
DN newBaseDn = ( DN ) apName.clone();
newBaseDn.addAll( ssNew.getBase() );
searchOperationContext = new SearchOperationContext( opContext.getSession(), newBaseDn,
filter, controls );
searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
subentries = nexus.search( searchOperationContext );
while ( subentries.next() )
{
ServerEntry candidate = subentries.get();
DN dn = candidate.getDn();
dn.normalize( schemaManager.getNormalizerMapping() );
if ( evaluator.evaluate( ssNew, apName, dn, candidate ) )
{
nexus.modify( new ModifyOperationContext( opContext.getSession(), dn,
getOperationalModsForAdd( candidate, operational ) ) );
}
}
}
else
{
next.modify( opContext );
if ( !objectClasses.contains( SchemaConstants.SUBENTRY_OC ) )
{
ServerEntry newEntry = opContext.lookup( name, ByPassConstants.LOOKUP_BYPASS );
List<Modification> subentriesOpAttrMods = getModsOnEntryModification( name, oldEntry, newEntry );
if ( subentriesOpAttrMods.size() > 0 )
{