/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.apache.directory.server.core.authz;


import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.naming.directory.SearchControls;

import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.CoreSession;
import org.apache.directory.server.core.DefaultCoreSession;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.LdapPrincipal;
import org.apache.directory.server.core.authz.support.ACDFEngine;
import org.apache.directory.server.core.authz.support.AciContext;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.entry.ServerEntryUtils;
import org.apache.directory.server.core.filtering.EntryFilter;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.BaseInterceptor;
import org.apache.directory.server.core.interceptor.InterceptorChain;
import org.apache.directory.server.core.interceptor.NextInterceptor;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.interceptor.context.OperationContext;
import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.interceptor.context.SearchingOperationContext;
import org.apache.directory.server.core.partition.ByPassConstants;
import org.apache.directory.server.core.partition.PartitionNexus;
import org.apache.directory.server.core.subtree.SubentryInterceptor;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.shared.ldap.aci.ACIItem;
import org.apache.directory.shared.ldap.aci.ACIItemParser;
import org.apache.directory.shared.ldap.aci.ACITuple;
import org.apache.directory.shared.ldap.aci.MicroOperation;
import org.apache.directory.shared.ldap.model.constants.AuthenticationLevel;
import org.apache.directory.shared.ldap.model.constants.Loggers;
import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
import org.apache.directory.shared.ldap.model.entry.Entry;
import org.apache.directory.shared.ldap.model.entry.EntryAttribute;
import org.apache.directory.shared.ldap.model.entry.Modification;
import org.apache.directory.shared.ldap.model.entry.StringValue;
import org.apache.directory.shared.ldap.model.entry.Value;
import org.apache.directory.shared.ldap.model.exception.LdapException;
import org.apache.directory.shared.ldap.model.exception.LdapNoPermissionException;
import org.apache.directory.shared.ldap.model.exception.LdapOperationErrorException;
import org.apache.directory.shared.ldap.model.exception.LdapOperationException;
import org.apache.directory.shared.ldap.model.filter.EqualityNode;
import org.apache.directory.shared.ldap.model.filter.ExprNode;
import org.apache.directory.shared.ldap.model.filter.OrNode;
import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
import org.apache.directory.shared.ldap.model.name.Dn;
import org.apache.directory.shared.ldap.model.schema.MutableAttributeTypeImpl;
import org.apache.directory.shared.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An ACI based authorization service.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class AciAuthorizationInterceptor extends BaseInterceptor
{
    /** the logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( AciAuthorizationInterceptor.class );

    /** the dedicated logger for ACI */
    private static final Logger ACI_LOG = LoggerFactory.getLogger( Loggers.ACI_LOG.getName() );

    private static final Collection<MicroOperation> ADD_PERMS;
    private static final Collection<MicroOperation> READ_PERMS;
    private static final Collection<MicroOperation> COMPARE_PERMS;
    private static final Collection<MicroOperation> SEARCH_ENTRY_PERMS;
    private static final Collection<MicroOperation> SEARCH_ATTRVAL_PERMS;
    private static final Collection<MicroOperation> REMOVE_PERMS;
    private static final Collection<MicroOperation> BROWSE_PERMS;
    private static final Collection<MicroOperation> LOOKUP_PERMS;
    private static final Collection<MicroOperation> REPLACE_PERMS;
    private static final Collection<MicroOperation> RENAME_PERMS;
    private static final Collection<MicroOperation> EXPORT_PERMS;
    private static final Collection<MicroOperation> IMPORT_PERMS;
    private static final Collection<MicroOperation> MOVERENAME_PERMS;

    static
    {
        Set<MicroOperation> set = new HashSet<MicroOperation>( 2 );
        set.add( MicroOperation.BROWSE );
        set.add( MicroOperation.RETURN_DN );
        SEARCH_ENTRY_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<MicroOperation>( 2 );
        set.add( MicroOperation.READ );
        set.add( MicroOperation.BROWSE );
        LOOKUP_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<MicroOperation>( 2 );
        set.add( MicroOperation.ADD );
        set.add( MicroOperation.REMOVE );
        REPLACE_PERMS = Collections.unmodifiableCollection( set );

        set = new HashSet<MicroOperation>( 2 );
        set.add( MicroOperation.EXPORT );
        set.add( MicroOperation.RENAME );
        MOVERENAME_PERMS = Collections.unmodifiableCollection( set );

        SEARCH_ATTRVAL_PERMS = Collections.singleton( MicroOperation.READ );
        ADD_PERMS = Collections.singleton( MicroOperation.ADD );
        READ_PERMS = Collections.singleton( MicroOperation.READ );
        COMPARE_PERMS = Collections.singleton( MicroOperation.COMPARE );
        REMOVE_PERMS = Collections.singleton( MicroOperation.REMOVE );
        BROWSE_PERMS = Collections.singleton( MicroOperation.BROWSE );
        RENAME_PERMS = Collections.singleton( MicroOperation.RENAME );
        EXPORT_PERMS = Collections.singleton( MicroOperation.EXPORT );
        IMPORT_PERMS = Collections.singleton( MicroOperation.IMPORT );
    }

    /** a tupleCache that responds to add, delete, and modify attempts */
    private TupleCache tupleCache;

    /** a groupCache that responds to add, delete, and modify attempts */
    private GroupCache groupCache;

    /** a normalizing ACIItem parser */
    private ACIItemParser aciParser;

    /** use and instance of the ACDF engine */
    private ACDFEngine engine;

    /** interceptor chain */
    private InterceptorChain chain;

    /** the system wide subschemaSubentryDn */
    private String subschemaSubentryDn;

    /** A reference to the nexus for direct backend operations */
    private PartitionNexus nexus;

    public static final SearchControls DEFAULT_SEARCH_CONTROLS = new SearchControls();


    /**
     * Load the Tuples into the cache
     */
    private void initTupleCache() throws LdapException
    {
        // Load all the prescriptiveACI : they are stored in AccessControlSubentry entries
        Dn adminDn = new Dn( schemaManager, ServerDNConstants.ADMIN_SYSTEM_DN );

        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setReturningAttributes( new String[]
            { SchemaConstants.PRESCRIPTIVE_ACI_AT } );

        ExprNode filter =
                new EqualityNode<String>( OBJECT_CLASS_AT, new StringValue( SchemaConstants.ACCESS_CONTROL_SUBENTRY_OC ) );

        CoreSession adminSession = new DefaultCoreSession( new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.STRONG ),
            directoryService );

        SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, Dn.ROOT_DSE, filter,
            controls );

        searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );

        EntryFilteringCursor results = nexus.search( searchOperationContext );

        try
        {
            while ( results.next() )
            {
                Entry entry = results.get();

                tupleCache.subentryAdded( entry.getDn(), entry );
            }

            results.close();
        }
        catch ( Exception e )
        {
            throw new LdapOperationException( e.getMessage() );
        }
    }


    /**
     * Load the Groups into the cache
     */
    private void initGroupCache() throws LdapException
    {
        // Load all the member/uniqueMember : they are stored in groupOfNames/groupOfUniqueName
        Dn adminDn = new Dn( schemaManager, ServerDNConstants.ADMIN_SYSTEM_DN );

        SearchControls controls = new SearchControls();
        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
        controls.setReturningAttributes( new String[]
            { SchemaConstants.MEMBER_AT, SchemaConstants.UNIQUE_MEMBER_AT } );

        ExprNode filter =
            new OrNode(
                new EqualityNode<String>( OBJECT_CLASS_AT, new StringValue( SchemaConstants.GROUP_OF_NAMES_OC ) ),
                new EqualityNode<String>( OBJECT_CLASS_AT, new StringValue( SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC ) ) );

        CoreSession adminSession = new DefaultCoreSession( new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.STRONG ),
            directoryService );

        SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, Dn.ROOT_DSE, filter,
            controls );

        searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );

        EntryFilteringCursor results = nexus.search( searchOperationContext );

        try
        {
            while ( results.next() )
            {
                Entry entry = results.get();

                groupCache.groupAdded( entry.getDn(), entry );
            }

            results.close();
        }
        catch ( Exception e )
        {
            throw new LdapOperationException( e.getMessage() );
        }
    }


    /**
     * Initializes this interceptor based service by getting a handle on the nexus, setting up
     * the tuple and group membership caches, the ACIItem parser and the ACDF engine.
     *
     * @param directoryService the directory service core
     * @throws Exception if there are problems during initialization
     */
    public void init( DirectoryService directoryService ) throws LdapException
    {
        LOG.debug( "Initializing the AciAuthorizationInterceptor" );

        super.init( directoryService );

        nexus = directoryService.getPartitionNexus();

        Dn adminDn = directoryService.getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
        CoreSession adminSession = new DefaultCoreSession( new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.STRONG ),
            directoryService );
        chain = directoryService.getInterceptorChain();

        // Create the caches
        tupleCache = new TupleCache( adminSession );
        groupCache = new GroupCache( directoryService );

        // Iitialize the ACI PARSER and ACDF engine
        aciParser = new ACIItemParser( new ConcreteNameComponentNormalizer( schemaManager ), schemaManager );
        engine = new ACDFEngine( schemaManager );

        // stuff for dealing with subentries (garbage for now)
        Value<?> subschemaSubentry = directoryService.getPartitionNexus().getRootDSE( null ).get(
            SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
        Dn subschemaSubentryDnName = directoryService.getDnFactory().create( subschemaSubentry.getString() );
        subschemaSubentryDn = subschemaSubentryDnName.getNormName();

        // Init the caches now
        initTupleCache();
        initGroupCache();
    }


    private void protectCriticalEntries( Dn dn ) throws LdapException
    {
        Dn principalDn = getPrincipal().getDn();

        if ( dn.isEmpty() )
        {
            String msg = I18n.err( I18n.ERR_8 );
            LOG.error( msg );
            throw new LdapNoPermissionException( msg );
        }

        if ( isTheAdministrator( dn ) )
        {
            String msg = I18n.err( I18n.ERR_9, principalDn.getName(), dn.getName() );
            LOG.error( msg );
            throw new LdapNoPermissionException( msg );
        }
    }


    /**
     * Adds perscriptiveACI tuples to a collection of tuples by accessing the
     * tupleCache.  The tuple cache is accessed for each A/C subentry
     * associated with the protected entry.  Note that subentries are handled
     * differently: their parent, the administrative entry is accessed to
     * determine the perscriptiveACIs effecting the AP and hence the subentry
     * which is considered to be in the same context.
     *
     * @param tuples the collection of tuples to add to
     * @param dn the normalized distinguished name of the protected entry
     * @param entry the target entry that access to is being controled
     * @throws Exception if there are problems accessing attribute values
     * @param proxy the partition nexus proxy object
     */
    private void addPerscriptiveAciTuples( OperationContext opContext, Collection<ACITuple> tuples, Dn dn, Entry entry )
        throws LdapException
    {
        Entry originalEntry = null;

        if ( entry instanceof ClonedServerEntry )
        {
            originalEntry = ((ClonedServerEntry)entry).getOriginalEntry();
        }
        else
        {
            originalEntry = entry;
        }

        EntryAttribute oc = originalEntry.get( OBJECT_CLASS_AT );

        /*
         * If the protected entry is a subentry, then the entry being evaluated
         * for perscriptiveACIs is in fact the administrative entry.  By
         * substituting the administrative entry for the actual subentry the
         * code below this "if" statement correctly evaluates the effects of
         * perscriptiveACI on the subentry.  Basically subentries are considered
         * to be in the same naming context as their access point so the subentries
         * effecting their parent entry applies to them as well.
         */
        if ( oc.contains( SchemaConstants.SUBENTRY_OC ) )
        {
            Dn parentDn = dn.getParent();
            originalEntry = opContext.lookup( parentDn, ByPassConstants.LOOKUP_BYPASS );
        }

        EntryAttribute subentries = originalEntry.get( ACCESS_CONTROL_SUBENTRIES_AT );

        if ( subentries == null )
        {
            return;
        }

        for ( Value<?> value : subentries )
        {
            String subentryDn = value.getString();
            tuples.addAll( tupleCache.getACITuples( subentryDn ) );
        }
    }


    /**
     * Adds the set of entryACI tuples to a collection of tuples.  The entryACI
     * is parsed and tuples are generated on they fly then added to the collection.
     *
     * @param tuples the collection of tuples to add to
     * @param entry the target entry that access to is being regulated
     * @throws Exception if there are problems accessing attribute values
     */
    private void addEntryAciTuples( Collection<ACITuple> tuples, Entry entry ) throws LdapException
    {
        EntryAttribute entryAci = entry.get( ENTRY_ACI_AT );

        if ( entryAci == null )
        {
            return;
        }

        for ( Value<?> value : entryAci )
        {
            String aciString = value.getString();
            ACIItem item;

            try
            {
                item = aciParser.parse( aciString );
            }
            catch ( ParseException e )
            {
                String msg = I18n.err( I18n.ERR_10, aciString );
                LOG.error( msg, e );
                throw new LdapOperationErrorException( msg );
            }

            tuples.addAll( item.toTuples() );
        }
    }


    /**
     * Adds the set of subentryACI tuples to a collection of tuples.  The subentryACI
     * is parsed and tuples are generated on the fly then added to the collection.
     *
     * @param tuples the collection of tuples to add to
     * @param dn the normalized distinguished name of the protected entry
     * @param entry the target entry that access to is being regulated
     * @throws Exception if there are problems accessing attribute values
     * @param proxy the partition nexus proxy object
     */
    private void addSubentryAciTuples( OperationContext opContext, Collection<ACITuple> tuples, Dn dn, Entry entry )
        throws LdapException
    {
        // only perform this for subentries
        if ( !entry.contains( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) )
        {
            return;
        }

        // get the parent or administrative entry for this subentry since it
        // will contain the subentryACI attributes that effect subentries
        Dn parentDn = dn.getParent();
        Entry administrativeEntry = ( ( ClonedServerEntry ) opContext.lookup( parentDn, ByPassConstants.LOOKUP_BYPASS ) )
            .getOriginalEntry();

        EntryAttribute subentryAci = administrativeEntry.get( SUBENTRY_ACI_AT );

        if ( subentryAci == null )
        {
            return;
        }

        for ( Value<?> value : subentryAci )
        {
            String aciString = value.getString();
            ACIItem item;

            try
            {
                item = aciParser.parse( aciString );
            }
            catch ( ParseException e )
            {
                String msg = I18n.err( I18n.ERR_11, aciString );
                LOG.error( msg, e );
                throw new LdapOperationErrorException( msg );
            }

            tuples.addAll( item.toTuples() );
        }
    }


    /* -------------------------------------------------------------------------------
     * Within every access controled interceptor method we must retrieve the ACITuple
     * set for all the perscriptiveACIs that apply to the candidate, the target entry
     * operated upon.  This ACITuple set is gotten from the TupleCache by looking up
     * the subentries referenced by the accessControlSubentries operational attribute
     * within the target entry.
     *
     * Then the entry is inspected for an entryACI.  This is not done for the add op
     * since it could introduce a security breech.  So for non-add ops if present a
     * set of ACITuples are generated for all the entryACIs within the entry.  This
     * set is combined with the ACITuples cached for the perscriptiveACI affecting
     * the target entry.  If the entry is a subentry the ACIs are also processed for
     * the subentry to generate more ACITuples.  This subentry TupleACI set is joined
     * with the entry and perscriptive ACI.
     *
     * The union of ACITuples are fed into the engine along with other parameters
     * to decide whether a permission is granted or rejected for the specific
     * operation.
     * -------------------------------------------------------------------------------
     */

    public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
    {
        // bypass authz code if it was disabled
        if ( !addContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            ACI_LOG.debug( "ACI interceptor disabled" );
            next.add( addContext );
            return;
        }

        ACI_LOG.debug( "Adding the entry {}", addContext.getEntry() );

        // Access the principal requesting the operation, and bypass checks if it is the admin
        LdapPrincipal principal = addContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        Entry serverEntry = addContext.getEntry();

        Dn dn = addContext.getDn();

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            ACI_LOG.debug( "Addition done by the administartor : no check" );

            next.add( addContext );
            tupleCache.subentryAdded( dn, serverEntry );
            groupCache.groupAdded( dn, serverEntry );
            return;
        }

        // perform checks below here for all non-admin users
        SubentryInterceptor subentryInterceptor = ( SubentryInterceptor ) chain.get( SubentryInterceptor.class
            .getName() );
        Entry subentry = subentryInterceptor.getSubentryAttributes( dn, serverEntry );

        for ( EntryAttribute attribute : serverEntry )
        {
            subentry.put( attribute );
        }

        // Assemble all the information required to make an access control decision
        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();

        // Build the total collection of tuples to be considered for add rights
        // NOTE: entryACI are NOT considered in adds (it would be a security breech)
        addPerscriptiveAciTuples( addContext, tuples, dn, subentry );
        addSubentryAciTuples( addContext, tuples, dn, subentry );

        // check if entry scope permission is granted
        AciContext entryAciCtx = new AciContext( schemaManager, addContext );
        entryAciCtx.setUserGroupNames( userGroups );
        entryAciCtx.setUserDn( principalDn );
        entryAciCtx.setAuthenticationLevel( principal.getAuthenticationLevel() );
        entryAciCtx.setEntryDn( dn );
        entryAciCtx.setMicroOperations( ADD_PERMS );
        entryAciCtx.setAciTuples( tuples );
        entryAciCtx.setEntry( subentry );

        engine.checkPermission( entryAciCtx );

        // now we must check if attribute type and value scope permission is granted
        for ( EntryAttribute attribute : serverEntry )
        {
            for ( Value<?> value : attribute )
            {
                AciContext attrAciContext = new AciContext( schemaManager, addContext );
                attrAciContext.setUserGroupNames( userGroups );
                attrAciContext.setUserDn( principalDn );
                attrAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                attrAciContext.setEntryDn( dn );
                attrAciContext.setAttributeType( attribute.getAttributeType() );
                attrAciContext.setAttrValue( value );
                attrAciContext.setMicroOperations( ADD_PERMS );
                attrAciContext.setAciTuples( tuples );
                attrAciContext.setEntry( serverEntry );

                engine.checkPermission( attrAciContext );
            }
        }

        // if we've gotten this far then access has been granted
        next.add( addContext );

        // if the entry added is a subentry or a groupOf[Unique]Names we must
        // update the ACITuple cache and the groups cache to keep them in sync
        tupleCache.subentryAdded( dn, serverEntry );
        groupCache.groupAdded( dn, serverEntry );
    }


    private boolean isTheAdministrator( Dn normalizedDn )
    {
        return normalizedDn.getNormName().equals( ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
    }


    public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
    {
        CoreSession session = deleteContext.getSession();

        // bypass authz code if we are disabled
        if ( !session.getDirectoryService().isAccessControlEnabled() )
        {
            next.delete( deleteContext );
            return;
        }

        Dn dn = deleteContext.getDn();
        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        Entry entry = deleteContext.getEntry();

        protectCriticalEntries( dn );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next.delete( deleteContext );

            tupleCache.subentryDeleted( dn, entry );
            groupCache.groupDeleted( dn, entry );

            return;
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( deleteContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( deleteContext, tuples, dn, entry );

        AciContext aciContext = new AciContext( schemaManager, deleteContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( REMOVE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        next.delete( deleteContext );

        tupleCache.subentryDeleted( dn, entry );
        groupCache.groupDeleted( dn, entry );
    }


    // False positive, we want to keep the comment
    @SuppressWarnings("PMD.CollapsibleIfStatements")
    public void modify( NextInterceptor next, ModifyOperationContext modifyContext ) throws LdapException
    {
        Dn dn = modifyContext.getDn();

        // Access the principal requesting the operation, and bypass checks if it is the admin
        Entry entry = modifyContext.getEntry();

        LdapPrincipal principal = modifyContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        // bypass authz code if we are disabled
        if ( !modifyContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            next.modify( modifyContext );
            return;
        }

        List<Modification> mods = modifyContext.getModItems();

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next.modify( modifyContext );

            /**
             * @TODO: A virtual entry can be created here for not hitting the backend again.
             */
            Entry modifiedEntry = modifyContext.lookup( dn, ByPassConstants.LOOKUP_BYPASS );
            tupleCache.subentryModified( dn, mods, modifiedEntry );
            groupCache.groupModified( dn, mods, entry, schemaManager );
            return;
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( modifyContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( modifyContext, tuples, dn, entry );

        AciContext entryAciContext = new AciContext( schemaManager, modifyContext );
        entryAciContext.setUserGroupNames( userGroups );
        entryAciContext.setUserDn( principalDn );
        entryAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        entryAciContext.setEntryDn( dn );
        entryAciContext.setMicroOperations( Collections.singleton( MicroOperation.MODIFY ) );
        entryAciContext.setAciTuples( tuples );
        entryAciContext.setEntry( entry );

        engine.checkPermission( entryAciContext );

        Collection<MicroOperation> perms = null;
        Entry entryView = entry.clone();

        for ( Modification mod : mods )
        {
            EntryAttribute attr = mod.getAttribute();

            switch ( mod.getOperation() )
            {
                case ADD_ATTRIBUTE:
                    perms = ADD_PERMS;

                    // If the attribute is being created with an initial value ...
                    if ( entry.get( attr.getId() ) == null )
                    {
                        AciContext attrAciContext = new AciContext( schemaManager, modifyContext );
                        attrAciContext.setUserGroupNames( userGroups );
                        attrAciContext.setUserDn( principalDn );
                        attrAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                        attrAciContext.setEntryDn( dn );
                        attrAciContext.setAttributeType( attr.getAttributeType() );
                        attrAciContext.setMicroOperations( perms );
                        attrAciContext.setAciTuples( tuples );
                        attrAciContext.setEntry( entry );

                        // ... we also need to check if adding the attribute is permitted
                        engine.checkPermission( attrAciContext );
                    }

                    break;

                case REMOVE_ATTRIBUTE:
                    perms = REMOVE_PERMS;
                    EntryAttribute entryAttr = entry.get( attr.getId() );

                    if ( entryAttr != null )
                    {
                        // If there is only one value remaining in the attribute ...
                        if ( entryAttr.size() == 1 )
                        {
                            // ... we also need to check if removing the attribute at all is permitted
                            AciContext aciContext = new AciContext( schemaManager, modifyContext );
                            aciContext.setUserGroupNames( userGroups );
                            aciContext.setUserDn( principalDn );
                            aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                            aciContext.setEntryDn( dn );
                            aciContext.setAttributeType( attr.getAttributeType() );
                            aciContext.setMicroOperations( perms );
                            aciContext.setAciTuples( tuples );
                            aciContext.setEntry( entry );

                            engine.checkPermission( aciContext );
                        }
                    }

                    break;

                case REPLACE_ATTRIBUTE:
                    perms = REPLACE_PERMS;
                    break;
            }

            /**
             * Update the entry view as the current modification is applied to the original entry.
             * This is especially required for handling the MaxValueCount protected item. Number of
             * values for an attribute after a modification should be known in advance in order to
             * check permissions for MaxValueCount protected item. So during addition of the first
             * value of an attribute it can be rejected if the permission denied due the the
             * MaxValueCount protected item. This is not the perfect implementation as required by
             * the specification because the system should reject the addition exactly on the right
             * value of the attribute. However as we do not have that much granularity in our
             * implementation (we consider an Attribute Addition itself a Micro Operation,
             * not the individual Value Additions) we just handle this when the first value of an
             * attribute is being checked for relevant permissions below.
             */
            entryView = ServerEntryUtils.getTargetEntry( mod, entryView, schemaManager );

            for ( Value<?> value : attr )
            {
                AciContext aciContext = new AciContext( schemaManager, modifyContext );
                aciContext.setUserGroupNames( userGroups );
                aciContext.setUserDn( principalDn );
                aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                aciContext.setEntryDn( dn );
                aciContext.setAttributeType( attr.getAttributeType() );
                aciContext.setAttrValue( value );
                aciContext.setMicroOperations( perms );
                aciContext.setAciTuples( tuples );
                aciContext.setEntry( entry );
                aciContext.setEntryView( entryView );

                engine.checkPermission( aciContext );
            }
        }

        next.modify( modifyContext );
        /**
         * @TODO: A virtual entry can be created here for not hitting the backend again.
         */
        Entry modifiedEntry = modifyContext.lookup( dn, ByPassConstants.LOOKUP_BYPASS );
        tupleCache.subentryModified( dn, mods, modifiedEntry );
        groupCache.groupModified( dn, mods, entry, schemaManager );
    }


    public boolean hasEntry( NextInterceptor next, EntryOperationContext hasEntryContext ) throws LdapException
    {
        Dn dn = hasEntryContext.getDn();

        if ( !hasEntryContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            return ( dn.isRootDSE() || next.hasEntry( hasEntryContext ) );
        }

        boolean answer = next.hasEntry( hasEntryContext );

        // no checks on the RootDSE
        if ( dn.isRootDSE() )
        {
            // No need to go down to the stack, if the dn is empty
            // It's the rootDSE, and it exists !
            return answer;
        }

        // TODO - eventually replace this with a check on session.isAnAdministrator()
        LdapPrincipal principal = hasEntryContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            return answer;
        }

        Entry entry = hasEntryContext.lookup( dn, ByPassConstants.HAS_ENTRY_BYPASS );
        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( hasEntryContext, tuples, dn, entry );
        addEntryAciTuples( tuples, ( ( ClonedServerEntry ) entry ).getOriginalEntry() );
        addSubentryAciTuples( hasEntryContext, tuples, dn, ( ( ClonedServerEntry ) entry ).getOriginalEntry() );

        // check that we have browse access to the entry
        AciContext aciContext = new AciContext( schemaManager, hasEntryContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( BROWSE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( ((ClonedServerEntry)entry).getOriginalEntry() );

        engine.checkPermission( aciContext );

        return next.hasEntry( hasEntryContext );
    }


    /**
     * Checks if the READ permissions exist to the entry and to each attribute type and
     * value.
     *
     * @todo not sure if we should hide attribute types/values or throw an exception
     * instead.  I think we're going to have to use a filter to restrict the return
     * of attribute types and values instead of throwing an exception.  Lack of read
     * perms to attributes and their values results in their removal when returning
     * the entry.
     *
     * @param principal the user associated with the call
     * @param dn the name of the entry being looked up
     * @param entry the raw entry pulled from the nexus
     * @throws Exception if undlying access to the DIT fails
     */
    private void checkLookupAccess( LookupOperationContext lookupContext, Entry entry ) throws LdapException
    {
        Dn dn = lookupContext.getDn();

        // no permissions checks on the RootDSE
        if ( dn.isRootDSE() )
        {
            return;
        }

        LdapPrincipal principal = lookupContext.getSession().getEffectivePrincipal();
        Dn userName = principal.getDn();
        Set<Dn> userGroups = groupCache.getGroups( userName.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( lookupContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( lookupContext, tuples, dn, entry );

        // check that we have read access to the entry
        AciContext aciContext = new AciContext( schemaManager, lookupContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( userName );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( LOOKUP_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // check that we have read access to every attribute type and value
        for ( EntryAttribute attribute : entry )
        {

            for ( Value<?> value : attribute )
            {
                AciContext valueAciContext = new AciContext( schemaManager, lookupContext );
                valueAciContext.setUserGroupNames( userGroups );
                valueAciContext.setUserDn( userName );
                valueAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                valueAciContext.setEntryDn( dn );
                valueAciContext.setAttributeType( attribute.getAttributeType() );
                valueAciContext.setAttrValue( value );
                valueAciContext.setMicroOperations( READ_PERMS );
                valueAciContext.setAciTuples( tuples );
                valueAciContext.setEntry( entry );

                engine.checkPermission( valueAciContext );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    public Entry lookup( NextInterceptor next, LookupOperationContext lookupContext ) throws LdapException
    {
        CoreSession session = lookupContext.getSession();
        DirectoryService directoryService = session.getDirectoryService();

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        if ( !principalDn.isNormalized() )
        {
            principalDn.normalize( schemaManager );
        }

        // Bypass this interceptor if we disabled the AC subsystem or if the principal is the admin
        if ( isPrincipalAnAdministrator( principalDn ) || !directoryService.isAccessControlEnabled() )
        {
            return next.lookup( lookupContext );
        }

        lookupContext.setByPassed( ByPassConstants.LOOKUP_BYPASS );
        Entry entry = directoryService.getOperationManager().lookup( lookupContext );

        checkLookupAccess( lookupContext, entry );

        return next.lookup( lookupContext );
    }


    public void rename( NextInterceptor next, RenameOperationContext renameContext ) throws LdapException
    {
        Dn oldName = renameContext.getDn();
        Entry originalEntry = null;

        if ( renameContext.getEntry() != null )
        {
            originalEntry = renameContext.getEntry().getOriginalEntry();
        }

        LdapPrincipal principal = renameContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();
        Dn newName = renameContext.getNewDn();

        // bypass authz code if we are disabled
        if ( !renameContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            next.rename( renameContext );
            return;
        }

        protectCriticalEntries( oldName );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next.rename( renameContext );
            tupleCache.subentryRenamed( oldName, newName );

            // TODO : this method returns a boolean : what should we do with the result ?
            groupCache.groupRenamed( oldName, newName );

            return;
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( renameContext, tuples, oldName, originalEntry );
        addEntryAciTuples( tuples, originalEntry );
        addSubentryAciTuples( renameContext, tuples, oldName, originalEntry );

        AciContext aciContext = new AciContext( schemaManager, renameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oldName );
        aciContext.setMicroOperations( RENAME_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( originalEntry );

        engine.checkPermission( aciContext );

        next.rename( renameContext );
        tupleCache.subentryRenamed( oldName, newName );
        groupCache.groupRenamed( oldName, newName );
    }


    public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext )
        throws LdapException
    {
        Dn oldDn = moveAndRenameContext.getDn();

        Entry entry = moveAndRenameContext.getOriginalEntry();

        LdapPrincipal principal = moveAndRenameContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();
        Dn newDn = moveAndRenameContext.getNewDn();

        // bypass authz code if we are disabled
        if ( !moveAndRenameContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            next.moveAndRename( moveAndRenameContext );
            return;
        }

        protectCriticalEntries( oldDn );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next.moveAndRename( moveAndRenameContext );
            tupleCache.subentryRenamed( oldDn, newDn );
            groupCache.groupRenamed( oldDn, newDn );
            return;
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( moveAndRenameContext, tuples, oldDn,entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( moveAndRenameContext, tuples, oldDn, entry );

        AciContext aciContext = new AciContext( schemaManager, moveAndRenameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oldDn );
        aciContext.setMicroOperations( MOVERENAME_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // Get the entry again without operational attributes
        // because access control subentry operational attributes
        // will not be valid at the new location.
        // This will certainly be fixed by the SubentryInterceptor,
        // but after this service.

        Entry importedEntry = moveAndRenameContext.lookup( oldDn,
            ByPassConstants.LOOKUP_EXCLUDING_OPR_ATTRS_BYPASS );

        // As the target entry does not exist yet and so
        // its subentry operational attributes are not there,
        // we need to construct an entry to represent it
        // at least with minimal requirements which are object class
        // and access control subentry operational attributes.
        SubentryInterceptor subentryInterceptor = ( SubentryInterceptor ) chain.get( SubentryInterceptor.class
            .getName() );
        Entry subentryAttrs = subentryInterceptor.getSubentryAttributes( newDn, importedEntry );

        for ( EntryAttribute attribute : importedEntry )
        {
            subentryAttrs.put( attribute );
        }

        Collection<ACITuple> destTuples = new HashSet<ACITuple>();
        // Import permission is only valid for prescriptive ACIs
        addPerscriptiveAciTuples( moveAndRenameContext, destTuples, newDn, subentryAttrs );

        // Evaluate the target context to see whether it
        // allows an entry named newName to be imported as a subordinate.
        aciContext = new AciContext( schemaManager, moveAndRenameContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( newDn );
        aciContext.setMicroOperations( IMPORT_PERMS );
        aciContext.setAciTuples( destTuples );
        aciContext.setEntry( subentryAttrs );

        engine.checkPermission( aciContext );

        next.moveAndRename( moveAndRenameContext );
        tupleCache.subentryRenamed( oldDn, newDn );
        groupCache.groupRenamed( oldDn, newDn );
    }


    /**
     * {@inheritDoc}
     */
    public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
    {
        Dn oriChildName = moveContext.getDn();

        // Access the principal requesting the operation, and bypass checks if it is the admin
        Entry entry = moveContext.getOriginalEntry();

        Dn newDn = moveContext.getNewDn();

        LdapPrincipal principal = moveContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        // bypass authz code if we are disabled
        if ( !moveContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            next.move( moveContext );
            return;
        }

        protectCriticalEntries( oriChildName );

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next.move( moveContext );
            tupleCache.subentryRenamed( oriChildName, newDn );
            groupCache.groupRenamed( oriChildName, newDn );
            return;
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( moveContext, tuples, oriChildName, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( moveContext, tuples, oriChildName, entry );

        AciContext aciContext = new AciContext( schemaManager, moveContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( oriChildName );
        aciContext.setMicroOperations( EXPORT_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        // Get the entry again without operational attributes
        // because access control subentry operational attributes
        // will not be valid at the new location.
        // This will certainly be fixed by the SubentryInterceptor,
        // but after this service.
        Entry importedEntry = moveContext.lookup( oriChildName, ByPassConstants.LOOKUP_EXCLUDING_OPR_ATTRS_BYPASS );

        // As the target entry does not exist yet and so
        // its subentry operational attributes are not there,
        // we need to construct an entry to represent it
        // at least with minimal requirements which are object class
        // and access control subentry operational attributes.
        SubentryInterceptor subentryInterceptor = ( SubentryInterceptor ) chain.get( SubentryInterceptor.class
            .getName() );
        Entry subentryAttrs = subentryInterceptor.getSubentryAttributes( newDn, importedEntry );

        for ( EntryAttribute attribute : importedEntry )
        {
            subentryAttrs.put( attribute );
        }

        Collection<ACITuple> destTuples = new HashSet<ACITuple>();
        // Import permission is only valid for prescriptive ACIs
        addPerscriptiveAciTuples( moveContext, destTuples, newDn, subentryAttrs );

        // Evaluate the target context to see whether it
        // allows an entry named newName to be imported as a subordinate.
        aciContext = new AciContext( schemaManager, moveContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( newDn );
        aciContext.setMicroOperations( IMPORT_PERMS );
        aciContext.setAciTuples( destTuples );
        aciContext.setEntry( subentryAttrs );

        engine.checkPermission( aciContext );

        next.move( moveContext );
        tupleCache.subentryRenamed( oriChildName, newDn );
        groupCache.groupRenamed( oriChildName, newDn );
    }


    public EntryFilteringCursor list( NextInterceptor next, ListOperationContext listContext ) throws LdapException
    {
        LdapPrincipal user = listContext.getSession().getEffectivePrincipal();
        EntryFilteringCursor cursor = next.list( listContext );

        if ( isPrincipalAnAdministrator( user.getDn() )
            || !listContext.getSession().getDirectoryService().isAccessControlEnabled() )
        {
            return cursor;
        }

        AuthorizationFilter authzFilter = new AuthorizationFilter();
        cursor.addEntryFilter( authzFilter );
        return cursor;
    }


    public EntryFilteringCursor search( NextInterceptor next, SearchOperationContext searchContext ) throws LdapException
    {
        LdapPrincipal user = searchContext.getSession().getEffectivePrincipal();
        Dn principalDn = user.getDn();
        EntryFilteringCursor cursor = next.search( searchContext );

        boolean isSubschemaSubentryLookup = subschemaSubentryDn.equals( searchContext.getDn().getNormName() );
        SearchControls searchCtls = searchContext.getSearchControls();
        boolean isRootDSELookup = searchContext.getDn().size() == 0
            && searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE;

        if ( isPrincipalAnAdministrator( principalDn )
            || !searchContext.getSession().getDirectoryService().isAccessControlEnabled() || isRootDSELookup
            || isSubschemaSubentryLookup )
        {
            return cursor;
        }

        cursor.addEntryFilter( new AuthorizationFilter() );
        return cursor;
    }


    public final boolean isPrincipalAnAdministrator( Dn principalDn )
    {
        return groupCache.isPrincipalAnAdministrator( principalDn );
    }


    /**
     * {@inheritDoc}
     */
    public boolean compare( NextInterceptor next, CompareOperationContext compareContext ) throws LdapException
    {
        CoreSession session = compareContext.getSession();
        Dn dn = compareContext.getDn();
        String oid = compareContext.getOid();
        Value<?> value = compareContext.getValue();

        Entry entry = compareContext.getOriginalEntry();

        LdapPrincipal principal = session.getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        if ( isPrincipalAnAdministrator( principalDn ) || !session.getDirectoryService().isAccessControlEnabled() )
        {
            return next.compare( compareContext );
        }

        Set<Dn> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( compareContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( compareContext, tuples, dn, entry );

        AciContext aciContext = new AciContext( schemaManager, compareContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setMicroOperations( READ_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        MutableAttributeTypeImpl attributeType = schemaManager.lookupAttributeTypeRegistry( oid );

        aciContext = new AciContext( schemaManager, compareContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( principalDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( dn );
        aciContext.setAttributeType( attributeType );
        aciContext.setMicroOperations( COMPARE_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( entry );

        engine.checkPermission( aciContext );

        return next.compare( compareContext );
    }


    public void cacheNewGroup( Dn name, Entry entry ) throws Exception
    {
        groupCache.groupAdded( name, entry );
    }


    private boolean filter( OperationContext opContext, Dn normName, ClonedServerEntry clonedEntry ) throws Exception
    {
        /*
         * First call hasPermission() for entry level "Browse" and "ReturnDN" perm
         * tests.  If we hasPermission() returns false we immediately short the
         * process and return false.
         */

        LdapPrincipal principal = opContext.getSession().getEffectivePrincipal();
        Dn userDn = principal.getDn();
        Set<Dn> userGroups = groupCache.getGroups( userDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<ACITuple>();
        addPerscriptiveAciTuples( opContext, tuples, normName, clonedEntry );
        addEntryAciTuples( tuples, clonedEntry.getOriginalEntry() );
        addSubentryAciTuples( opContext, tuples, normName, clonedEntry.getOriginalEntry() );

        AciContext aciContext = new AciContext( schemaManager, opContext );
        aciContext.setUserGroupNames( userGroups );
        aciContext.setUserDn( userDn );
        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        aciContext.setEntryDn( normName );
        aciContext.setMicroOperations( SEARCH_ENTRY_PERMS );
        aciContext.setAciTuples( tuples );
        aciContext.setEntry( clonedEntry.getOriginalEntry() );

        if ( !engine.hasPermission( aciContext ) )
        {
            return false;
        }

        /*
         * For each attribute type we check if access is allowed to the type.  If not
         * the attribute is yanked out of the entry to be returned.  If permission is
         * allowed we move on to check if the values are allowed.  Values that are
         * not allowed are removed from the attribute.  If the attribute has no more
         * values remaining then the entire attribute is removed.
         */
        List<MutableAttributeTypeImpl> attributeToRemove = new ArrayList<MutableAttributeTypeImpl>();

        for ( MutableAttributeTypeImpl attributeType : clonedEntry.getAttributeTypes() )
        {
            // if attribute type scope access is not allowed then remove the attribute and continue
            EntryAttribute attr = clonedEntry.get( attributeType );

            aciContext = new AciContext( schemaManager, opContext );
            aciContext.setUserGroupNames( userGroups );
            aciContext.setUserDn( userDn );
            aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
            aciContext.setEntryDn( normName );
            aciContext.setAttributeType( attributeType );
            aciContext.setMicroOperations( SEARCH_ATTRVAL_PERMS );
            aciContext.setAciTuples( tuples );
            aciContext.setEntry( clonedEntry );

            if ( !engine.hasPermission( aciContext ) )
            {
                attributeToRemove.add( attributeType );

                continue;
            }

            List<Value<?>> valueToRemove = new ArrayList<Value<?>>();

            // attribute type scope is ok now let's determine value level scope
            for ( Value<?> value : attr )
            {
                aciContext = new AciContext( schemaManager, opContext );
                aciContext.setUserGroupNames( userGroups );
                aciContext.setUserDn( userDn );
                aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                aciContext.setEntryDn( normName );
                aciContext.setAttributeType( attr.getAttributeType() );
                aciContext.setAttrValue( value );
                aciContext.setMicroOperations( SEARCH_ATTRVAL_PERMS );
                aciContext.setAciTuples( tuples );
                aciContext.setEntry( clonedEntry );

                if ( !engine.hasPermission( aciContext ) )
                {
                    valueToRemove.add( value );
                }
            }

            for ( Value<?> value : valueToRemove )
            {
                attr.remove( value );
            }

            if ( attr.size() == 0 )
            {
                attributeToRemove.add( attributeType );
            }
        }

        for ( MutableAttributeTypeImpl attributeType : attributeToRemove )
        {
            clonedEntry.removeAttributes( attributeType );
        }

        return true;
    }

    /**
     * WARNING: create one of these filters fresh every time for each new search.
     */
    class AuthorizationFilter implements EntryFilter
    {
        public boolean accept( SearchingOperationContext searchContext, ClonedServerEntry entry ) throws Exception
        {
            Dn normName = entry.getDn().normalize( schemaManager );
            return filter( searchContext, normName, entry );
        }
    }
}
