Package org.apache.ldap.server.interceptor

Source Code of org.apache.ldap.server.interceptor.InterceptorChain$Entry

/*
*   Copyright 2004 The Apache Software Foundation
*
*   Licensed 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.ldap.server.interceptor;


import org.apache.ldap.server.authn.AuthenticationService;
import org.apache.ldap.server.invocation.Invocation;
import org.apache.ldap.server.authz.AuthorizationService;
import org.apache.ldap.server.schema.SchemaService;
import org.apache.ldap.server.operational.OperationalAttributeService;
import org.apache.ldap.server.exception.ExceptionService;
import org.apache.ldap.server.normalization.NormalizationService;

import javax.naming.NamingException;
import java.util.*;


/**
* Manages the chain of {@link Interceptor}s.  <tt>InterceptorChain</tt>
* is also an {@link Interceptor}, and thus you can create hiararchical
* interceptor structure to break down complex interceptors.
* <p/>
* {@link org.apache.ldap.server.jndi.JndiProvider#invoke(Invocation)}
* redirects {@link Invocation}s to {@link #process(NextInterceptor, Invocation)}
* and the chain starts.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev: 159467 $, $Date: 2005-03-30 02:38:30 -0500 (Wed, 30 Mar 2005) $
*/
public class InterceptorChain implements Interceptor
{
    /**
     * The name of default interceptor that passes its control to the
     * next interceptor in parent chain.
     */
    public static final String NEXT_INTERCEPTOR = "nextInterceptor";


    /**
     * Returns a new chain of default interceptors required to run core.
     */
    public static InterceptorChain newDefaultChain()
    {
        InterceptorChain chain = new InterceptorChain();

        chain.addFirst( "normalizationService", new NormalizationService() );

        chain.addBefore( NEXT_INTERCEPTOR, "authenticationService", new AuthenticationService() );

        chain.addBefore( NEXT_INTERCEPTOR, "authorizationService", new AuthorizationService() );

        chain.addBefore( NEXT_INTERCEPTOR, "exceptionService", new ExceptionService() );

        chain.addBefore( NEXT_INTERCEPTOR, "schemaService", new SchemaService() );

        chain.addBefore( NEXT_INTERCEPTOR, "operationalAttributeService", new OperationalAttributeService() );

        return chain;
    }


    private final Interceptor NEXT_INTERCEPTOR0 = new Interceptor()
    {
        public void init( InterceptorContext context )
        {
        }


        public void destroy()
        {
        }


        public void process( NextInterceptor nextInterceptor, Invocation invocation ) throws NamingException
        {
            if( parent != null )
            {
                Entry e = ( Entry ) parent.interceptor2entry.get( InterceptorChain.this );

                e.nextInterceptor.process( invocation );
            }

            nextInterceptor.process( invocation );
        }
    };


    private final Interceptor FINAL_INTERCEPTOR = new Interceptor()
    {
        private InterceptorContext ctx;


        public void init( InterceptorContext context )
        {
            ctx = context;
        }


        public void destroy()
        {
            // unused
        }


        public void process( NextInterceptor nextInterceptor, Invocation call ) throws NamingException
        {
            if ( parent == null )
            {
                // execute the actual backend operation only when this chain is root.

                call.execute( ctx.getRootNexus() );
            }
        }
    };

    private InterceptorChain parent;

    private final Map name2entry = new HashMap();

    private final Map interceptor2entry = new IdentityHashMap();

    private Entry head = new Entry( null, null, NEXT_INTERCEPTOR, NEXT_INTERCEPTOR0 );

    private final Entry tail = new Entry( null, null, "end", FINAL_INTERCEPTOR );


    /**
     * Create a new interceptor chain.
     */
    public InterceptorChain()
    {
        head.nextEntry = tail;

        tail.prevEntry = head;

        register( NEXT_INTERCEPTOR, head );
    }


    /**
     * Initializes all interceptors this chain contains.
     */
    public synchronized void init( InterceptorContext ctx ) throws NamingException
    {
        ListIterator it = getAll().listIterator();

        Interceptor interceptor = null;

        try
        {
            while ( it.hasNext() )
            {
                interceptor = ( Interceptor ) it.next();

                String name = getName( interceptor );

                Map config = InterceptorConfigBuilder.build( ctx.getConfig(), ( name == null ) ? "" : name );

                InterceptorContext newCtx = new InterceptorContext( ctx.getEnvironment(),
                        ctx.getSystemPartition(), ctx.getGlobalRegistries(), ctx.getRootNexus(), config );

                interceptor.init( newCtx );
            }
        }
        catch ( Throwable t )
        {
            while ( it.hasPrevious() )
            {
                Interceptor i = ( Interceptor ) it.previous();

                try
                {
                    i.destroy();
                }
                catch ( Throwable t2 )
                {
                    t2.printStackTrace();
                }
            }

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


    /**
     * Deinitializes all interceptors this chain contains.
     */
    public synchronized void destroy()
    {
        ListIterator it = getAllReversed().listIterator();

        while ( it.hasNext() )
        {
            Interceptor interceptor = ( Interceptor ) it.next();

            try
            {
                interceptor.destroy();
            }
            catch ( Throwable t )
            {
                t.printStackTrace();
            }
        }
    }


    /**
     * Returns the interceptor with the specified <code>name</code>.
     *
     * @return <code>null</code> if there is no interceptor with the specified <code>name</code>.
     */
    public Interceptor get( String name )
    {
        Entry e = ( Entry ) name2entry.get( name );

        if ( e == null )
        {
            return null;
        }

        return e.interceptor;
    }


    private String getName( Interceptor interceptor )
    {
        Entry e = ( Entry ) interceptor2entry.get( interceptor );

        if ( e == null )
        {
            return null;
        }

        return e.name;
    }


    /**
     * Adds the specified interceptor with the specified name at the beginning of this chain.
     */
    public synchronized void addFirst( String name,
                                       Interceptor interceptor )
    {
        checkAddable( name, interceptor );

        Entry newEntry = new Entry( null, head, name, interceptor );

        head.prevEntry = newEntry;

        head = newEntry;

        register( name, newEntry );
    }


    /**
     * Adds the specified interceptor with the specified name at the end of this chain.
     */
    public synchronized void addLast( String name,
                                      Interceptor interceptor )
    {
        checkAddable( name, interceptor );

        Entry newEntry = new Entry( tail.prevEntry, tail, name, interceptor );

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

        tail.prevEntry = newEntry;

        register( name, newEntry );
    }


    /**
     * Adds the specified interceptor with the specified name just before the interceptor whose name is
     * <code>baseName</code> in this chain.
     */
    public synchronized void addBefore( String baseName, String name, Interceptor interceptor )
    {
        Entry baseEntry = checkOldName( baseName );

        checkAddable( name, interceptor );

        Entry prevEntry = baseEntry.prevEntry;

        Entry newEntry = new Entry( prevEntry, baseEntry, name, interceptor );

        if ( prevEntry == null )
        {
            baseEntry.prevEntry = newEntry;

            head = newEntry;
           
        }
        else
        {
            baseEntry.prevEntry = newEntry;

            prevEntry.nextEntry = newEntry;
        }

        register( name, newEntry );
    }


    /**
     * Adds the specified interceptor with the specified name just after the interceptor whose name is
     * <code>baseName</code> in this chain.
     */
    public synchronized void addAfter( String baseName, String name, Interceptor interceptor )
    {
        Entry baseEntry = checkOldName( baseName );

        checkAddable( name, interceptor );

        Entry nextEntry = baseEntry.nextEntry;

        Entry newEntry = new Entry( baseEntry, nextEntry, name, interceptor );

        if ( nextEntry == null )
        {
            throw new IllegalStateException();
        }

        nextEntry.prevEntry.nextEntry = newEntry;

        nextEntry.prevEntry = newEntry;

        register( name, newEntry );
    }


    /**
     * Removes the interceptor with the specified name from this chain.
     */
    public synchronized void remove( String name )
    {
        Entry entry = checkOldName( name );

        Entry prevEntry = entry.prevEntry;

        Entry nextEntry = entry.nextEntry;

        if ( prevEntry == null )
        {
            nextEntry.prevEntry = null;

            head = entry;
        }
        else
        {
            prevEntry.nextEntry = nextEntry;

            nextEntry.prevEntry = prevEntry;
        }

        name2entry.remove( name );

        Interceptor interceptor = entry.interceptor;

        interceptor2entry.remove( interceptor );

        if ( interceptor instanceof InterceptorChain )
        {
            ( ( InterceptorChain ) interceptor ).parent = null;
        }
    }


    /**
     * Removes all interceptors added to this chain.
     */
    public synchronized void clear()
    {
        Iterator it = new ArrayList( name2entry.keySet() ).iterator();

        while ( it.hasNext() )
        {
            this.remove( ( String ) it.next() );
        }
    }


    private void register( String name, Entry newEntry )
    {
        Interceptor interceptor = newEntry.interceptor;

        name2entry.put( name, newEntry );

        interceptor2entry.put( newEntry.interceptor, newEntry );

        if ( interceptor instanceof InterceptorChain )
        {
            ( ( InterceptorChain ) interceptor ).parent = this;
        }
    }


    /**
     * Throws an exception when the specified interceptor name is not registered in this chain.
     *
     * @return An interceptor entry with the specified name.
     */
    private Entry checkOldName( String baseName )
    {
        Entry e = ( Entry ) name2entry.get( baseName );

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

        return e;
    }


    /**
     * Checks the specified interceptor name is already taken and throws an exception if already taken.
     */
    private void checkAddable( String name, Interceptor interceptor )
    {
        if ( name2entry.containsKey( name ) )
        {
            throw new IllegalArgumentException( "Other interceptor is using name '" + name + "'" );
        }

        if ( interceptor instanceof InterceptorChain )
        {
            if ( ( ( InterceptorChain ) interceptor ).parent != null )
            {
                throw new IllegalArgumentException( "This interceptor chain has its parent already." );
            }
        }
    }


    /**
     * Start invocation chain with the specified invocation.
     *
     * @throws NamingException if invocation failed
     */
    public void process( NextInterceptor nextInterceptor, Invocation invocation ) throws NamingException
    {
        Entry head = this.head;

        try
        {
            head.interceptor.process( head.nextInterceptor, invocation );
        }
        catch ( NamingException ne )
        {
            throw ne;
        }
        catch ( Throwable e )
        {
            throw new InterceptorException( head.interceptor, invocation, "Unexpected exception.", e );
        }
    }


    /**
     * Returns the list of interceptors this chain in the order of evaluation.
     */
    public List getAll()
    {
        List list = new ArrayList();

        Entry e = head;

        do
        {
            list.add( e.interceptor );

            e = e.nextEntry;
        }
        while ( e != null );

        return list;
    }


    /**
     * Returns the list of interceptors this chain in the reversed order of evaluation.
     */
    public List getAllReversed()
    {
        List list = new ArrayList();

        Entry e = tail;

        do
        {
            list.add( e.interceptor );

            e = e.prevEntry;
        }

        while ( e != null );

        return list;
    }


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

        private Entry nextEntry;

        private final String name;

        private final Interceptor interceptor;

        private final NextInterceptor nextInterceptor;


        private Entry( Entry prevEntry, Entry nextEntry,
                       String name, Interceptor interceptor )
        {
            if ( interceptor == null )
            {
                throw new NullPointerException( "interceptor" );
            }
            if ( name == null )
            {
                throw new NullPointerException( "name" );
            }

            this.prevEntry = prevEntry;

            this.nextEntry = nextEntry;

            this.name = name;

            this.interceptor = interceptor;

            this.nextInterceptor = new NextInterceptor()
            {
                public void process( Invocation call ) throws NamingException
                {
                    Interceptor interceptor = Entry.this.nextEntry.interceptor;

                    try
                    {
                        interceptor.process( Entry.this.nextEntry.nextInterceptor, call );
                    }
                    catch ( NamingException ne )
                    {
                        throw ne;
                    }
                    catch ( Throwable e )
                    {
                        throw new InterceptorException( interceptor, call, "Unexpected exception.", e );
                    }
                }
            };
        }
    }
}
TOP

Related Classes of org.apache.ldap.server.interceptor.InterceptorChain$Entry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.