/*
 *  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.interceptor;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.ConfigurationException;

import org.apache.directory.server.core.CoreSession;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.interceptor.context.AddContextPartitionOperationContext;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.BindOperationContext;
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.GetMatchedNameOperationContext;
import org.apache.directory.server.core.interceptor.context.GetRootDSEOperationContext;
import org.apache.directory.server.core.interceptor.context.GetSuffixOperationContext;
import org.apache.directory.server.core.interceptor.context.ListOperationContext;
import org.apache.directory.server.core.interceptor.context.ListSuffixOperationContext;
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.RemoveContextPartitionOperationContext;
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.UnbindOperationContext;
import org.apache.directory.server.core.invocation.InvocationStack;
import org.apache.directory.server.core.partition.ByPassConstants;
import org.apache.directory.server.core.partition.PartitionNexus;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Manages the chain of {@link Interceptor}s.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public class InterceptorChain
{
    private static final Logger LOG = LoggerFactory.getLogger( InterceptorChain.class );

    /** Speedup for logs */
    private static final boolean IS_DEBUG = LOG.isDebugEnabled();

    private final Interceptor FINAL_INTERCEPTOR = new Interceptor()
    {
        private PartitionNexus nexus;


        public String getName()
        {
            return "FINAL";
        }

        public void init( DirectoryService directoryService )
        {
            this.nexus = directoryService.getPartitionNexus();
        }


        public void destroy()
        {
            // unused
        }


        public boolean compare( NextInterceptor next, CompareOperationContext opContext ) throws Exception
        {
            return nexus.compare( opContext );
        }


        public ClonedServerEntry getRootDSE( NextInterceptor next, GetRootDSEOperationContext opContext ) throws Exception
        {
            return nexus.getRootDSE( opContext );
        }


        public LdapDN getMatchedName( NextInterceptor next, GetMatchedNameOperationContext opContext ) throws Exception
        {
            return ( LdapDN ) nexus.getMatchedName( opContext ).clone();
        }


        public LdapDN getSuffix( NextInterceptor next, GetSuffixOperationContext opContext ) throws Exception
        {
            return ( LdapDN ) nexus.getSuffix( opContext ).clone();
        }


        public Set<String> listSuffixes( NextInterceptor next, ListSuffixOperationContext opContext ) throws Exception
        {
            return nexus.listSuffixes( opContext );
        }


        public void delete( NextInterceptor next, DeleteOperationContext opContext ) throws Exception
        {
            nexus.delete( opContext );
        }


        public void add( NextInterceptor next, AddOperationContext opContext ) throws Exception
        {
            nexus.add( opContext );
        }


        public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws Exception
        {
            nexus.modify( opContext );
        }


        public EntryFilteringCursor list( NextInterceptor next, ListOperationContext opContext ) throws Exception
        {
            return nexus.list( opContext );
        }


        public EntryFilteringCursor search( NextInterceptor next, SearchOperationContext opContext ) throws Exception
        {
            return nexus.search( opContext );
        }


        public ClonedServerEntry lookup( NextInterceptor next, LookupOperationContext opContext ) throws Exception
        {
            return nexus.lookup( opContext );
        }


        public boolean hasEntry( NextInterceptor next, EntryOperationContext opContext ) throws Exception
        {
            return nexus.hasEntry( opContext );
        }


        public void rename( NextInterceptor next, RenameOperationContext opContext )
            throws Exception
        {
            nexus.rename( opContext );
        }


        public void move( NextInterceptor next, MoveOperationContext opContext ) throws Exception
        {
            nexus.move( opContext );
        }


        public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext opContext )
            throws Exception
        {
            nexus.moveAndRename( opContext );
        }


        public void addContextPartition( NextInterceptor next, AddContextPartitionOperationContext opContext )
            throws Exception
        {
            nexus.addContextPartition( opContext );
        }


        public void removeContextPartition( NextInterceptor next, RemoveContextPartitionOperationContext opContext ) throws Exception
        {
            nexus.removeContextPartition( opContext );
        }


        public void bind( NextInterceptor next, BindOperationContext opContext )  throws Exception
        {
            nexus.bind( opContext );
        }


        public void unbind( NextInterceptor next, UnbindOperationContext opContext ) throws Exception
        {
            nexus.unbind( opContext );
        }
    };

    private final Map<String, Entry> name2entry = new HashMap<String, Entry>();

    private final Entry tail;

    private Entry head;

    private DirectoryService directoryService;


    /**
     * Create a new interceptor chain.
     */
    public InterceptorChain()
    {
        tail = new Entry( "tail", null, null, FINAL_INTERCEPTOR );
        head = tail;
    }


    /**
     * Initializes and registers all interceptors according to the specified
     * {@link DirectoryService}.
     * @throws javax.naming.Exception if an interceptor cannot be initialized.
     * @param directoryService the directory core
     */
    public synchronized void init( DirectoryService directoryService ) throws Exception
    {
        // Initialize tail first.
        this.directoryService = directoryService;
        FINAL_INTERCEPTOR.init( directoryService );

        // And register and initialize all interceptors
        try
        {
            for ( Interceptor interceptor: directoryService.getInterceptors() )
            {
                if ( IS_DEBUG )
                {
                    LOG.debug( "Adding interceptor " + interceptor.getName() );
                }

                register( interceptor );
            }
        }
        catch ( Throwable t )
        {
            // destroy if failed to initialize all interceptors.
            destroy();

            if ( t instanceof Exception )
            {
                throw ( Exception ) t;
            }
            else
            {
                throw new InterceptorException( null, "Failed to initialize interceptor chain.", t );
            }
        }
    }


    /**
     * Deinitializes and deregisters all interceptors this chain contains.
     */
    public synchronized void destroy()
    {
        List<Entry> entries = new ArrayList<Entry>();
        Entry e = tail;

        do
        {
            entries.add( e );
            e = e.prevEntry;
        }
        while ( e != null );

        for ( Entry entry:entries )
        {
            if ( entry != tail )
            {
                try
                {
                    deregister( entry.getName() );
                }
                catch ( Throwable t )
                {
                    LOG.warn( "Failed to deregister an interceptor: " + entry.getName(), t );
                }
            }
        }
    }


    /**
     * Returns the registered interceptor with the specified name.
     * @param interceptorName name of the interceptor to look for
     * @return <tt>null</tt> if the specified name doesn't exist.
     */
    public Interceptor get( String interceptorName )
    {
        Entry e = name2entry.get( interceptorName );
        if ( e == null )
        {
            return null;
        }

        return e.interceptor;
    }


    /**
     * Returns the list of all registered interceptors.
     * @return a list of all the registered interceptors.
     */
    public synchronized List<Interceptor> getAll()
    {
        List<Interceptor> result = new ArrayList<Interceptor>();
        Entry e = head;

        do
        {
            result.add( e.interceptor );
            e = e.nextEntry;
        }
        while ( e != tail );

        return result;
    }


    public synchronized void addFirst( Interceptor interceptor ) throws Exception
    {
        register0( interceptor, head );
    }


    public synchronized void addLast( Interceptor interceptor ) throws Exception
    {
        register0( interceptor, tail );
    }


    public synchronized void addBefore( String nextInterceptorName, Interceptor interceptor )
        throws Exception
    {
        Entry e = name2entry.get( nextInterceptorName );
        if ( e == null )
        {
            throw new ConfigurationException( "Interceptor not found: " + nextInterceptorName );
        }
        register0( interceptor, e );
    }


    public synchronized String remove( String interceptorName ) throws Exception
    {
        return deregister( interceptorName );
    }


    public synchronized void addAfter( String prevInterceptorName, Interceptor interceptor )
        throws Exception
    {
        Entry e = name2entry.get( prevInterceptorName );
        if ( e == null )
        {
            throw new ConfigurationException( "Interceptor not found: " + prevInterceptorName );
        }
        register0( interceptor, e.nextEntry );
    }


    /**
     * Adds and initializes an interceptor with the specified configuration.
     * @param interceptor interceptor to add to end of chain
     * @throws javax.naming.Exception if there is already an interceptor of this name or the interceptor
     * cannot be initialized.
     */
    private void register( Interceptor interceptor ) throws Exception
    {
        checkAddable( interceptor );
        register0( interceptor, tail );
    }


    /**
     * Removes and deinitializes the interceptor with the specified name.
     * @param name name of interceptor to remove
     * @return name of interceptor removed, if any
     * @throws javax.naming.ConfigurationException if no interceptor registered under that name
     */
    private String deregister( String name ) throws ConfigurationException
    {
        Entry entry = checkOldName( name );
        Entry prevEntry = entry.prevEntry;
        Entry nextEntry = entry.nextEntry;

        if ( nextEntry == null )
        {
            // Don't deregister tail
            return null;
        }

        if ( prevEntry == null )
        {
            nextEntry.prevEntry = null;
            head = nextEntry;
        }
        else
        {
            prevEntry.nextEntry = nextEntry;
            nextEntry.prevEntry = prevEntry;
        }

        name2entry.remove( name );
        entry.interceptor.destroy();

        return entry.getName();
    }

    
    private void register0( Interceptor interceptor, Entry nextEntry ) throws Exception
    {
        String name = interceptor.getName();

        interceptor.init( directoryService );
        Entry newEntry;
        if ( nextEntry == head )
        {
            newEntry = new Entry( interceptor.getName(), null, head, interceptor );
            head.prevEntry = newEntry;
            head = newEntry;
        }
        else if ( head == tail )
        {
            newEntry = new Entry( interceptor.getName(), null, tail, interceptor );
            tail.prevEntry = newEntry;
            head = newEntry;
        }
        else
        {
            newEntry = new Entry( interceptor.getName(), nextEntry.prevEntry, nextEntry, interceptor );
            nextEntry.prevEntry.nextEntry = newEntry;
            nextEntry.prevEntry = newEntry;
        }

        name2entry.put( name, newEntry );
    }


    /**
     * Throws an exception when the specified interceptor name is not registered in this chain.
     *
     * @param name name of interceptor to look for
     * @return An interceptor entry with the specified name.
     * @throws javax.naming.ConfigurationException if no interceptor has that name
     */
    private Entry checkOldName( String name ) throws ConfigurationException
    {
        Entry e = name2entry.get( name );

        if ( e == null )
        {
            throw new ConfigurationException( "Unknown interceptor name:" + name );
        }

        return e;
    }


    /**
     * Checks the specified interceptor name is already taken and throws an exception if already taken.
     * @param interceptor interceptor to check
     * @throws javax.naming.ConfigurationException if interceptor name is already registered
     */
    private void checkAddable( Interceptor interceptor ) throws ConfigurationException
    {
        if ( name2entry.containsKey( interceptor.getName() ) )
        {
            throw new ConfigurationException( "Other interceptor is using name '" + interceptor.getName() + "'" );
        }
    }


    /**
     * Gets the InterceptorEntry to use first with bypass information considered.
     *
     * @return the first entry to use.
     */
    private Entry getStartingEntry()
    {
        if ( InvocationStack.getInstance().isEmpty() )
        {
            return head;
        }

        OperationContext opContext = InvocationStack.getInstance().peek();
        
        if ( !opContext.hasBypass() )
        {
            return head;
        }

        if ( opContext.isBypassed( ByPassConstants.BYPASS_ALL ) )
        {
            return tail;
        }

        Entry next = head;
        
        while ( next != tail )
        {
            if ( opContext.isBypassed( next.getName() ) )
            {
                next = next.nextEntry;
            }
            else
            {
                return next;
            }
        }

        return tail;
    }


    public ClonedServerEntry getRootDSE( GetRootDSEOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.getRootDSE( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public LdapDN getMatchedName( GetMatchedNameOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.getMatchedName( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public LdapDN getSuffix( GetSuffixOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.getSuffix( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public boolean compare( CompareOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.compare( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public Set<String> listSuffixes( ListSuffixOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.listSuffixes( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public void addContextPartition( AddContextPartitionOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            head.addContextPartition( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public void removeContextPartition( RemoveContextPartitionOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            head.removeContextPartition( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }

    
    /**
     * Eagerly populates fields of operation contexts so multiple Interceptors 
     * in the processing pathway can reuse this value without performing a 
     * redundant lookup operation.
     *
     * @param opContext the operation context to populate with cached fields
     */
    private void eagerlyPopulateFields( OperationContext opContext )
    {
        // If the entry field is not set for ops other than add for example 
        // then we set the entry but don't freak if we fail to do so since it
        // may not exist in the first place
        
        if ( opContext.getEntry() == null )
        {
            try
            {
                // We have to use the admin session here, otherwise we may have
                // trouble reading the entry due to insufficient access rights 
                CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();
                opContext.setEntry( adminSession.lookup( opContext.getDn(), SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES_ARRAY ) );
            }
            catch ( Exception e )
            {
                // might not exist
            }
        }
    }
    

    public void delete( DeleteOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );
        
        try
        {
            head.delete( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void add( AddOperationContext opContext ) throws Exception
    {
        Entry node = getStartingEntry();
        Interceptor head = node.interceptor;
        NextInterceptor next = node.nextInterceptor;

        try
        {
            head.add( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void bind( BindOperationContext opContext ) throws Exception
    {
        Entry node = getStartingEntry();
        Interceptor head = node.interceptor;
        NextInterceptor next = node.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            head.bind( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void unbind( UnbindOperationContext opContext ) throws Exception
    {
        Entry node = getStartingEntry();
        Interceptor head = node.interceptor;
        NextInterceptor next = node.nextInterceptor;

        try
        {
            head.unbind( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void modify( ModifyOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            head.modify( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public EntryFilteringCursor list( ListOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            return head.list( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public EntryFilteringCursor search( SearchOperationContext opContext )
        throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            return head.search( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.lookup( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public boolean hasEntry( EntryOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;

        try
        {
            return head.hasEntry( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
            throw new InternalError(); // Should be unreachable
        }
    }


    public void rename( RenameOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            head.rename( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void move( MoveOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            head.move( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }


    public void moveAndRename( MoveAndRenameOperationContext opContext ) throws Exception
    {
        Entry entry = getStartingEntry();
        Interceptor head = entry.interceptor;
        NextInterceptor next = entry.nextInterceptor;
        eagerlyPopulateFields( opContext );

        try
        {
            head.moveAndRename( next, opContext );
        }
        catch ( Exception ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throwInterceptorException( head, e );
        }
    }

    /**
     * Represents an internal entry of this chain.
     */
    private class Entry
    {
        private volatile Entry prevEntry;

        private volatile Entry nextEntry;

        private final String name;

        private final Interceptor interceptor;

        private final NextInterceptor nextInterceptor;


        private String getName()
        {
            return name;
        }


        private Entry( String name, Entry prevEntry, Entry nextEntry, Interceptor interceptor )
        {
            this.name = name;

            if ( interceptor == null )
            {
                throw new NullPointerException( "interceptor" );
            }

            this.prevEntry = prevEntry;
            this.nextEntry = nextEntry;
            this.interceptor = interceptor;
            this.nextInterceptor = new NextInterceptor()
            {
                private Entry getNextEntry()
                {
                    if ( InvocationStack.getInstance().isEmpty() )
                    {
                        return Entry.this.nextEntry;
                    }

                    OperationContext opContext = InvocationStack.getInstance().peek();
                    if ( !opContext.hasBypass() )
                    {
                        return Entry.this.nextEntry;
                    }

                    //  I don't think we really need this since this check is performed by the chain when
                    //  getting the interceptor head to use.
                    //
                    //                    if ( invocation.isBypassed( DirectoryPartitionNexusProxy.BYPASS_ALL ) )
                    //                    {
                    //                        return tail;
                    //                    }

                    Entry next = Entry.this.nextEntry;
                    while ( next != tail )
                    {
                        if ( opContext.isBypassed( next.getName() ) )
                        {
                            next = next.nextEntry;
                        }
                        else
                        {
                            return next;
                        }
                    }

                    return next;
                }


                public boolean compare( CompareOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.compare( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public ClonedServerEntry getRootDSE( GetRootDSEOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.getRootDSE( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public LdapDN getMatchedName( GetMatchedNameOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.getMatchedName( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public LdapDN getSuffix( GetSuffixOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.getSuffix( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public Set<String> listSuffixes( ListSuffixOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.listSuffixes( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public void delete( DeleteOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.delete( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void add( AddOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.add( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void modify( ModifyOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.modify( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }

                
                public EntryFilteringCursor list( ListOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.list( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public EntryFilteringCursor search( SearchOperationContext opContext )
                    throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.search( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public ClonedServerEntry lookup( LookupOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.lookup( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public boolean hasEntry( EntryOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        return interceptor.hasEntry( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public void rename( RenameOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.rename( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void move( MoveOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.move( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void moveAndRename( MoveAndRenameOperationContext opContext )
                    throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.moveAndRename( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void bind( BindOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;
    
                    try
                    {
                        interceptor.bind( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void unbind( UnbindOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.unbind( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                    }
                }


                public void addContextPartition( AddContextPartitionOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.addContextPartition( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }


                public void removeContextPartition( RemoveContextPartitionOperationContext opContext ) throws Exception
                {
                    Entry next = getNextEntry();
                    Interceptor interceptor = next.interceptor;

                    try
                    {
                        interceptor.removeContextPartition( next.nextInterceptor, opContext );
                    }
                    catch ( Exception ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throwInterceptorException( interceptor, e );
                        throw new InternalError(); // Should be unreachable
                    }
                }
            };
        }
    }


    private static void throwInterceptorException( Interceptor interceptor, Throwable e ) throws InterceptorException
    {
        throw new InterceptorException( interceptor, "Unexpected exception.", e );
    }
}
