public void modify()

in interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/SubentryInterceptor.java [1088:1265]


    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        Dn dn = modifyContext.getDn();
        List<Modification> modifications = modifyContext.getModItems();

        Entry entry = modifyContext.getEntry();

        // We have three types of modifications :
        // 1) A modification applied on a normal entry
        // 2) A modification done on a subentry (the entry will have a 'subentry' ObjectClass)
        // 3) A modification on a normal entry on whch we add a 'subentry' ObjectClass
        // The third case is a transformation of a normal entry to a subentry. Not sure if it's
        // legal ...

        boolean isSubtreeSpecificationModification = false;
        Modification subtreeMod = null;

        // Find the subtreeSpecification
        for ( Modification mod : modifications )
        {
            if ( mod.getAttribute().getAttributeType()
                .equals( directoryService.getAtProvider().getSubtreeSpecification() ) )
            {
                isSubtreeSpecificationModification = true;
                subtreeMod = mod;
                break;
            }
        }

        boolean containsSubentryOC = entry.contains( directoryService.getAtProvider().getObjectClass(),
            SchemaConstants.SUBENTRY_OC );

        // Check if we have a modified subentry attribute in a Subentry entry
        if ( containsSubentryOC && isSubtreeSpecificationModification )
        {
            Subentry subentry = directoryService.getSubentryCache().removeSubentry( dn );
            SubtreeSpecification ssOld = subentry.getSubtreeSpecification();
            SubtreeSpecification ssNew;

            try
            {
                ssNew = ssParser.parse( subtreeMod.getAttribute().getString() );
            }
            catch ( Exception e )
            {
                String msg = I18n.err( I18n.ERR_29000_CANNOT_PARSE_SUBTREE_SPECIFICATION );
                LOG.error( msg, e );
                throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
            }

            subentry.setSubtreeSpecification( ssNew );
            subentry.setAdministrativeRoles( getSubentryTypes( entry, modifications ) );
            directoryService.getSubentryCache().addSubentry( dn, subentry );

            next( modifyContext );

            // search for all entries selected by the old SS and remove references to subentry
            Dn apName = dn.getParent();
            Dn oldBaseDn = apName;
            oldBaseDn = oldBaseDn.add( ssOld.getBase() );

            ExprNode filter = new PresenceNode( directoryService.getAtProvider().getObjectClass() );
            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( modifyContext.getSession(),
                oldBaseDn, filter, controls );
            searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
            searchOperationContext.setPartition( modifyContext.getPartition() );
            searchOperationContext.setTransaction( modifyContext.getTransaction() );

            EntryFilteringCursor subentries = nexus.search( searchOperationContext );

            try
            {
                while ( subentries.next() )
                {
                    Entry candidate = subentries.get();
                    Dn candidateDn = candidate.getDn();

                    if ( directoryService.getEvaluator().evaluate( ssOld, apName, candidateDn, candidate ) )
                    {
                        ModifyOperationContext newModifyContext = new ModifyOperationContext( modifyContext.getSession(), candidateDn,
                            getOperationalModsForRemove( dn, candidate ) );
                        newModifyContext.setPartition( modifyContext.getPartition() );
                        newModifyContext.setTransaction( modifyContext.getTransaction() );
                        
                        nexus.modify( newModifyContext );
                    }
                }

                subentries.close();
            }
            catch ( Exception e )
            {
                throw new LdapOperationErrorException( e.getMessage(), e );
            }
            finally
            {
                try
                {
                    subentries.close();
                }
                catch ( Exception e )
                {
                    LOG.error( I18n.err( I18n.ERR_38007_FAILED_ON_LIST_CLOSE ), e );
                }
            }

            // search for all selected entries by the new SS and add references to subentry
            subentry = directoryService.getSubentryCache().getSubentry( dn );
            List<Attribute> operationalAttributes = getSubentryOperationalAttributes( dn, subentry );
            Dn newBaseDn = apName;
            newBaseDn = newBaseDn.add( ssNew.getBase() );

            searchOperationContext = new SearchOperationContext( modifyContext.getSession(), newBaseDn, filter,
                controls );
            searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
            searchOperationContext.setPartition( modifyContext.getPartition() );
            searchOperationContext.setTransaction( modifyContext.getTransaction() );

            subentries = nexus.search( searchOperationContext );

            try
            {
                while ( subentries.next() )
                {
                    Entry candidate = subentries.get();
                    Dn candidateDn = candidate.getDn();

                    if ( directoryService.getEvaluator().evaluate( ssNew, apName, candidateDn, candidate ) )
                    {
                        ModifyOperationContext newModifyContext = new ModifyOperationContext( modifyContext.getSession(), candidateDn,
                            getOperationalModsForAdd( candidate, operationalAttributes ) );
                        newModifyContext.setTransaction( modifyContext.getTransaction() );
                        nexus.modify( newModifyContext );
                    }
                }
                subentries.close();
            }
            catch ( Exception e )
            {
                throw new LdapOperationErrorException( e.getMessage(), e );
            }
            finally
            {
                try
                {
                    subentries.close();
                }
                catch ( Exception e )
                {
                    LOG.error( I18n.err( I18n.ERR_38007_FAILED_ON_LIST_CLOSE ), e );
                }
            }
        }
        else
        {
            next( modifyContext );

            if ( !containsSubentryOC )
            {
                Entry newEntry = modifyContext.getAlteredEntry();

                List<Modification> subentriesOpAttrMods = getModsOnEntryModification( dn, entry, newEntry );

                if ( !subentriesOpAttrMods.isEmpty() )
                {
                    ModifyOperationContext newModifyContext = new ModifyOperationContext( modifyContext.getSession(), dn, subentriesOpAttrMods );
                    newModifyContext.setPartition( modifyContext.getPartition() );
                    newModifyContext.setTransaction( modifyContext.getTransaction() );
                    nexus.modify( newModifyContext );
                }
            }
        }
    }