public void add( NextInterceptor next, AddOperationContext addContext ) throws Exception
{
DN name = addContext.getDn();
ClonedServerEntry entry = addContext.getEntry();
EntryAttribute objectClasses = entry.get( SchemaConstants.OBJECT_CLASS_AT );
if ( objectClasses.contains( SchemaConstants.SUBENTRY_OC ) )
{
// get the name of the administrative point and its administrativeRole attributes
DN apName = ( DN ) name.clone();
apName.remove( name.size() - 1 );
ServerEntry ap = addContext.lookup( apName, ByPassConstants.LOOKUP_BYPASS );
EntryAttribute administrativeRole = ap.get( "administrativeRole" );
// check that administrativeRole has something valid in it for us
if ( administrativeRole == null || administrativeRole.size() <= 0 )
{
throw new LdapNoSuchAttributeException( I18n.err( I18n.ERR_306, apName ) );
}
/* ----------------------------------------------------------------
* Build the set of operational attributes to be injected into
* entries that are contained within the subtree repesented 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.setTypes( getSubentryTypes( entry ) );
ServerEntry operational = getSubentryOperatationalAttributes( 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( SchemaConstants.SUBTREE_SPECIFICATION_AT ).getString();
SubtreeSpecification ss;
try
{
ss = ssParser.parse( subtree );
}
catch ( Exception e )
{
String msg = I18n.err( I18n.ERR_307, name.getName() );
LOG.warn( msg );
throw new LdapInvalidAttributeValueException( msg, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX );
}
subentryCache.setSubentry( name.getNormName(), ss, getSubentryTypes( entry ) );
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() );
ExprNode filter = new PresenceNode( SchemaConstants.OBJECT_CLASS_AT_OID ); // (objectClass=*)
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( addContext.getSession(), baseDn,
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( ss, apName, dn, candidate ) )
{
nexus.modify( new ModifyOperationContext( addContext.getSession(), dn,
getOperationalModsForAdd( candidate, operational ) ) );
}
}
// 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 );
DN apDn = ( DN ) subentryDn.clone();
apDn.remove( apDn.size() - 1 );
Subentry subentry = subentryCache.getSubentry( subentryDnStr );
SubtreeSpecification ss = subentry.getSubtreeSpecification();
if ( evaluator.evaluate( ss, apDn, name, entry ) )
{
EntryAttribute operational;
if ( subentry.isAccessControlSubentry() )
{
operational = entry.get( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT );
if ( operational == null )
{
operational = new DefaultServerAttribute( schemaManager
.lookupAttributeTypeRegistry( SchemaConstants.ACCESS_CONTROL_SUBENTRIES_AT ) );
entry.put( operational );
}
operational.add( subentryDn.getNormName() );
}
if ( subentry.isSchemaSubentry() )
{
operational = entry.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
if ( operational == null )
{
operational = new DefaultServerAttribute( schemaManager
.lookupAttributeTypeRegistry( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ) );
entry.put( operational );
}
operational.add( subentryDn.getNormName() );
}
if ( subentry.isCollectiveSubentry() )
{
operational = entry.get( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT );
if ( operational == null )
{
operational = new DefaultServerAttribute( schemaManager
.lookupAttributeTypeRegistry( SchemaConstants.COLLECTIVE_ATTRIBUTE_SUBENTRIES_AT ) );
entry.put( operational );
}
operational.add( subentryDn.getNormName() );
}
if ( subentry.isTriggerSubentry() )
{
operational = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
if ( operational == null )
{
operational = new DefaultServerAttribute( schemaManager
.lookupAttributeTypeRegistry( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ) );
entry.put( operational );
}
operational.add( subentryDn.getNormName() );
}
}
}
// TODO why are we doing this here if we got the entry from the