You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/03/20 08:19:30 UTC

svn commit: r158316 - in directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi: CoreContextFactory.java JndiProvider.java call/interceptor/InterceptorChain.java call/interceptor/Validator.java ibs/

Author: trustin
Date: Sat Mar 19 23:19:29 2005
New Revision: 158316

URL: http://svn.apache.org/viewcvs?view=rev&rev=158316
Log:
Finished basic conversion.


Added:
    directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java   (with props)
Removed:
    directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/ibs/
Modified:
    directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java
    directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java
    directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/InterceptorChain.java

Modified: directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java?view=diff&r1=158315&r2=158316
==============================================================================
--- directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java (original)
+++ directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java Sat Mar 19 23:19:29 2005
@@ -46,6 +46,7 @@
 import org.apache.ldap.server.SystemPartition;
 import org.apache.ldap.server.auth.AbstractAuthenticator;
 import org.apache.ldap.server.auth.AnonymousAuthenticator;
+import org.apache.ldap.server.auth.Authenticator;
 import org.apache.ldap.server.auth.AuthenticatorConfig;
 import org.apache.ldap.server.auth.AuthenticatorContext;
 import org.apache.ldap.server.auth.SimpleAuthenticator;
@@ -55,12 +56,10 @@
 import org.apache.ldap.server.db.ExpressionEvaluator;
 import org.apache.ldap.server.db.SearchEngine;
 import org.apache.ldap.server.db.jdbm.JdbmDatabase;
-import org.apache.ldap.server.jndi.ibs.FilterService;
-import org.apache.ldap.server.jndi.ibs.FilterServiceImpl;
-import org.apache.ldap.server.jndi.ibs.OperationalAttributeService;
-import org.apache.ldap.server.jndi.ibs.SchemaService;
-import org.apache.ldap.server.jndi.ibs.ServerExceptionService;
-import org.apache.ldap.server.jndi.request.interceptor.Interceptor;
+import org.apache.ldap.server.jndi.call.interceptor.Authorizer;
+import org.apache.ldap.server.jndi.call.interceptor.DefaultAttributeTagger;
+import org.apache.ldap.server.jndi.call.interceptor.SchemaManager;
+import org.apache.ldap.server.jndi.call.interceptor.Validator;
 import org.apache.ldap.server.schema.AttributeTypeRegistry;
 import org.apache.ldap.server.schema.ConcreteNameComponentNormalizer;
 import org.apache.ldap.server.schema.GlobalRegistries;
@@ -499,16 +498,33 @@
         // --------------------------------------------------------------------
         // Adding interceptors
         // --------------------------------------------------------------------
+        addDefaultInterceptors();
 
+        // fire up the app partitions now!
+        if ( initialEnv.get( EnvKeys.PARTITIONS ) != null )
+        {
+            startUpAppPartitions( wkdir );
+        }
+    }
+    
+    private void addDefaultInterceptors() throws NamingException
+    {
+        addAuthenticator();
+        addAuthorizer();
+        addValidator();
+        addSchemaManager();
+        addDefaultAttributeTagger();
+    }
+    
+    private void addAuthenticator() throws NamingException
+    {
         /*
          * Create and add the Authentication service interceptor to before
          * interceptor chain.
          */
-        InvocationStateEnum[] state = new InvocationStateEnum[]{InvocationStateEnum.PREINVOCATION};
-
         boolean allowAnonymous = !initialEnv.containsKey( EnvKeys.DISABLE_ANONYMOUS );
-
-        AuthenticationService authenticationService = new AuthenticationService();
+        org.apache.ldap.server.jndi.call.interceptor.Authenticator authenticationService =
+                new org.apache.ldap.server.jndi.call.interceptor.Authenticator();
 
         // create authenticator context
         AuthenticatorContext authenticatorContext = new AuthenticatorContext();
@@ -522,7 +538,7 @@
             authenticatorConfig.setAuthenticatorName( "none" );
             authenticatorConfig.setAuthenticatorContext( authenticatorContext );
 
-            AbstractAuthenticator authenticator = new AnonymousAuthenticator();
+            Authenticator authenticator = new AnonymousAuthenticator();
             authenticator.init( authenticatorConfig );
             authenticationService.register( authenticator );
 
@@ -564,76 +580,51 @@
                 e.printStackTrace();
             }
         }
+        
+        provider.getInterceptorChain().addLast( "authenticator", authenticationService );
+    }
 
-        provider.addInterceptor( authenticationService, state );
-
-        /*
-         * Create and add the Eve Exception service interceptor to both the
-         * before and onError interceptor chains.
-         */
-        state = new InvocationStateEnum[]{InvocationStateEnum.POSTINVOCATION};
-
-        FilterService filterService = new FilterServiceImpl();
-
-        Interceptor interceptor = ( Interceptor ) filterService;
-
-        provider.addInterceptor( interceptor, state );
-
+    private void addAuthorizer() throws NamingException
+    {
         /*
          * Create and add the Authorization service interceptor to before
          * interceptor chain.
          */
-        state = new InvocationStateEnum[]{InvocationStateEnum.PREINVOCATION};
-
-        ConcreteNameComponentNormalizer normalizer;
 
         AttributeTypeRegistry atr = globalRegistries.getAttributeTypeRegistry();
-
-        normalizer = new ConcreteNameComponentNormalizer( atr );
-
-        interceptor = new AuthorizationService( normalizer, filterService );
-
-        provider.addInterceptor( interceptor, state );
-
+        ConcreteNameComponentNormalizer normalizer = new ConcreteNameComponentNormalizer( atr );
+        Authorizer authorizer = new Authorizer( normalizer );
+        provider.getInterceptorChain().addLast( "authorizer", authorizer );
+    }
+    
+    private void addValidator()
+    {
         /*
          * Create and add the Eve Exception service interceptor to both the
          * before and onError interceptor chains.
          */
-        state = new InvocationStateEnum[]{
-            InvocationStateEnum.PREINVOCATION, InvocationStateEnum.FAILUREHANDLING};
-
-        interceptor = new ServerExceptionService( nexus );
-
-        provider.addInterceptor( interceptor, state );
-
+        Validator validator = new Validator( nexus );
+        provider.getInterceptorChain().addLast( "validator", validator );
+    }
+    
+    private void addSchemaManager() throws NamingException
+    {
         /*
          * Create and add the Eve schema service interceptor to before chain.
          */
-        state = new InvocationStateEnum[]{InvocationStateEnum.PREINVOCATION};
-
-        interceptor = new SchemaService( nexus, globalRegistries, filterService );
-
-        provider.addInterceptor( interceptor, state );
-
+        SchemaManager schemaManager = new SchemaManager( nexus, globalRegistries );
+        provider.getInterceptorChain().addLast( "schemaManager", schemaManager );
+    }
+    
+    private void addDefaultAttributeTagger()
+    {
         /*
          * Create and add the Eve operational attribute managment service
          * interceptor to both the before and after interceptor chains.
          */
-        state = new InvocationStateEnum[]{
-            InvocationStateEnum.PREINVOCATION,
-            InvocationStateEnum.POSTINVOCATION};
-
-        interceptor = new OperationalAttributeService( nexus, globalRegistries, filterService );
-
-        provider.addInterceptor( interceptor, state );
-
-        // fire up the app partitions now!
-        if ( initialEnv.get( EnvKeys.PARTITIONS ) != null )
-        {
-            startUpAppPartitions( wkdir );
-        }
+        DefaultAttributeTagger tagger = new DefaultAttributeTagger( nexus, globalRegistries );
+        provider.getInterceptorChain().addLast( "defaultAttributeTagger", tagger );
     }
-
 
     /**
      * Starts up all the application partitions that will be attached to naming contexts in the system.  Partition

Modified: directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java?view=diff&r1=158315&r2=158316
==============================================================================
--- directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java (original)
+++ directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java Sat Mar 19 23:19:29 2005
@@ -16,25 +16,42 @@
  */
 package org.apache.ldap.server.jndi;
 
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
 
 import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
 import javax.naming.ldap.LdapContext;
 
-import org.apache.ldap.common.exception.LdapNamingException;
-import org.apache.ldap.common.message.ResultCodeEnum;
+import org.apache.ldap.common.filter.ExprNode;
 import org.apache.ldap.server.BackendSubsystem;
+import org.apache.ldap.server.ContextPartition;
 import org.apache.ldap.server.PartitionNexus;
 import org.apache.ldap.server.RootNexus;
-import org.apache.ldap.server.jndi.request.interceptor.BaseInterceptor;
-import org.apache.ldap.server.jndi.request.interceptor.Interceptor;
-import org.apache.ldap.server.jndi.request.interceptor.InterceptorChain;
+import org.apache.ldap.server.jndi.call.Add;
+import org.apache.ldap.server.jndi.call.Call;
+import org.apache.ldap.server.jndi.call.Delete;
+import org.apache.ldap.server.jndi.call.GetMatchedDN;
+import org.apache.ldap.server.jndi.call.GetSuffix;
+import org.apache.ldap.server.jndi.call.HasEntry;
+import org.apache.ldap.server.jndi.call.IsSuffix;
+import org.apache.ldap.server.jndi.call.List;
+import org.apache.ldap.server.jndi.call.ListSuffixes;
+import org.apache.ldap.server.jndi.call.Lookup;
+import org.apache.ldap.server.jndi.call.LookupWithAttrIds;
+import org.apache.ldap.server.jndi.call.Modify;
+import org.apache.ldap.server.jndi.call.ModifyMany;
+import org.apache.ldap.server.jndi.call.ModifyRN;
+import org.apache.ldap.server.jndi.call.Move;
+import org.apache.ldap.server.jndi.call.MoveAndModifyRN;
+import org.apache.ldap.server.jndi.call.Search;
+import org.apache.ldap.server.jndi.call.interceptor.InterceptorChain;
 
 
 /**
@@ -43,17 +60,17 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class JndiProvider implements BackendSubsystem, InvocationHandler
+public class JndiProvider implements BackendSubsystem
 {
     /** Singleton instance of this class */
-    private static JndiProvider s_singleton = null;
+    private static JndiProvider s_singleton;
     
     /** The interceptor chain for this provider */
-    private final InterceptorChain interceptors = new InterceptorChain();
+    private InterceptorChain interceptors;
     /** RootNexus as it was given to us by the ServiceManager */
-    private RootNexus nexus = null;
+    private RootNexus nexus;
     /** PartitionNexus proxy wrapping nexus to inject services */
-    private PartitionNexus proxy = null;
+    private PartitionNexus proxy;
 
     /** whether or not this instance has been shutdown */
     private boolean isShutdown = false;
@@ -81,10 +98,8 @@
 
         s_singleton = this;
         this.nexus = nexus;
-        this.proxy = ( PartitionNexus ) Proxy.newProxyInstance(
-            nexus.getClass().getClassLoader(),
-            nexus.getClass().getInterfaces(), this );
-
+        this.interceptors = new InterceptorChain( nexus );
+        this.proxy = new PartitionNexusImpl();
     }
 
 
@@ -150,213 +165,121 @@
         this.isShutdown = true;
         s_singleton = null;
     }
+    
+    public InterceptorChain getInterceptorChain()
+    {
+        return interceptors;
+    }
 
 
-    // ------------------------------------------------------------------------
-    // Invokation Handler Implementation
-    // ------------------------------------------------------------------------
-
+    public Object invoke( Call call ) throws NamingException
+    {
+        interceptors.process( call );
+        return call.getResponse();
+    }
 
     /**
-     * @see java.lang.reflect.InvocationHandler#invoke(Object,Method,Object[])
+     * A dead context is requested and returned when we shutdown the system. It
+     * prevents a {@link javax.naming.NoInitialContextException} from being
+     * thrown by InitialContext or one of its subclasses.
+     *
+     * @return a unusable dead context
      */
-    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
+    public Context getDeadContext()
+    {
+        return new DeadContext();
+    }
+    
+    private class PartitionNexusImpl implements PartitionNexus
     {
-        // Setup the invocation and populate: remember aspect sets context stack
-        Invocation invocation = new Invocation();
-        invocation.setMethod( method );
-        invocation.setProxy( proxy );
-        invocation.setParameters( args );
 
-        // used for an optimization
-        BaseInterceptor.setInvocation( invocation );
+        public LdapContext getLdapContext() {
+            return nexus.getLdapContext();
+        }
 
-        try
-        {
-            before.invoke( invocation );
+        public Name getMatchedDn(Name dn, boolean normalized) throws NamingException {
+            return ( Name ) JndiProvider.this.invoke( new GetMatchedDN( dn, normalized ) );
         }
-        catch ( Throwable throwable )
-        {
-            /*
-             * On errors we need to continue into the failure handling state
-             * of Invocation processing and not throw anything just record it.
-             */
-            if ( invocation.getBeforeFailure() == null )
-            {
-                invocation.setBeforeFailure( throwable );
-            }
 
-            invocation.setState( InvocationStateEnum.FAILUREHANDLING );
+        public Name getSuffix(Name dn, boolean normalized) throws NamingException {
+            return ( Name ) JndiProvider.this.invoke( new GetSuffix( dn, normalized ) );
         }
 
-        
-        /*
-         * If before pipeline succeeds invoke the target and change state to 
-         * POSTINVOCATION on success but on failure record exception and set 
-         * state to FAILUREHANDLING.
-         * 
-         * If before pipeline failed then we invoke the after failure pipeline
-         * and throw the before failure exception.
-         */
-        if ( invocation.getState() == InvocationStateEnum.PREINVOCATION )
-        {
-            NamingException target = null;
+        public Iterator listSuffixes(boolean normalized) throws NamingException {
+            return ( Iterator ) JndiProvider.this.invoke( new ListSuffixes( normalized ) );
+        }
 
-            try
-            {
-                /*
-                 * If the invocation is not bypassed, we invoke on the proxied
-                 * object and set the return value on invocation.  If we do
-                 * bypass, its because a before chain service set the bypass
-                 * flag.  If the invoked method has a return value it's the
-                 * responsibility of the bypass triggering interceptor to set
-                 * the value to return.
-                 */
-
-                if ( ! invocation.doBypass() )
-                {
-                    Object retVal = method.invoke( nexus, invocation.getParameters() );
-                    invocation.setReturnValue( retVal );
-                }
-
-                // even if invocation is bypassed state is now post invocation 
-                invocation.setState( InvocationStateEnum.POSTINVOCATION );
-            }
-            catch ( InvocationTargetException ite )
-            {
-                if ( ite.getTargetException() != null )
-                {
-                    if ( ite.getTargetException() instanceof NamingException )
-                    {
-                        target = ( NamingException ) ite.getTargetException();
-                    }
-                    else
-                    {
-                        target = new NamingException();
-                        target.setRootCause( ite.getTargetException() );
-                    }
-                }
-                else
-                {
-                    target = new NamingException();
-                    target.setRootCause( ite );
-                }
-
-                invocation.setThrowable( target );
-                invocation.setState( InvocationStateEnum.FAILUREHANDLING );
-            }
-            catch ( Throwable t )
-            {
-                target = new NamingException();
-                target.setRootCause( t );
-                invocation.setThrowable( target );
-                invocation.setState( InvocationStateEnum.FAILUREHANDLING );
-            }
+        public void register(ContextPartition partition) {
+            nexus.register( partition );
+        }
 
-            invocation.setComplete( true );
+        public void unregister(ContextPartition partition) {
+            nexus.unregister( partition );
         }
-        else if ( invocation.getState() == InvocationStateEnum.FAILUREHANDLING )
-        {
-            afterFailure.invoke( invocation );
-            BaseInterceptor.setInvocation( null );
-            throw invocation.getBeforeFailure();
+
+        public void delete(Name name) throws NamingException {
+            JndiProvider.this.invoke( new Delete( name ) );
         }
 
+        public void add(String upName, Name normName, Attributes entry) throws NamingException {
+            JndiProvider.this.invoke( new Add( upName, normName, entry ) );
+        }
 
-        /*
-         * If we have gotten this far then the before pipeline succeeded.  If
-         * the target invocation succeeded then we should be in the
-         * POSTINVOCATION state in which case we invoke the after pipeline.
-         *
-         * If the target invocation failed then we should run the after failure
-         * pipeline since we will be in the FAILUREHANDLINE state and after
-         * doing so we throw the original throwable raised by the target.
-         */
-        if ( invocation.getState() == InvocationStateEnum.POSTINVOCATION )
-        {
-            try
-            {
-                after.invoke( invocation );
-                BaseInterceptor.setInvocation( null );
-                return invocation.getReturnValue();
-            }
-            catch ( Throwable throwable )
-            {
-                invocation.setState( InvocationStateEnum.FAILUREHANDLING );
-                
-                if ( invocation.getAfterFailure() == null )
-                {
-                    invocation.setAfterFailure( throwable );
-                }
-
-                afterFailure.invoke( invocation );
-                BaseInterceptor.setInvocation( null );
-                throw invocation.getAfterFailure();
-            }
+        public void modify(Name name, int modOp, Attributes mods) throws NamingException {
+            JndiProvider.this.invoke( new Modify( name, modOp, mods ) );
         }
-        else if ( invocation.getState() == InvocationStateEnum.FAILUREHANDLING )
-        {
-            afterFailure.invoke( invocation );
 
-            if ( invocation.getThrowable() == null )
-            {
-                throw new LdapNamingException( "Interceptor Framework Failure: "
-                        + "failures on the proxied call should have a non null "
-                        + "throwable associated with the Invocation object.",
-                        ResultCodeEnum.OTHER );
-            }
-
-            BaseInterceptor.setInvocation( null );
-            throw invocation.getThrowable();
-        }
-
-        // used for an optimization
-        BaseInterceptor.setInvocation( null );
-        throw new LdapNamingException( "Interceptor Framework Failure: "
-                + "invocation handling should never have reached this line",
-                ResultCodeEnum.OTHER );
-    }
+        public void modify(Name name, ModificationItem[] mods) throws NamingException {
+            JndiProvider.this.invoke( new ModifyMany( name, mods ) );
+        }
+
+        public NamingEnumeration list(Name base) throws NamingException {
+            return ( NamingEnumeration ) JndiProvider.this.invoke( new List( base ) );
+        }
 
+        public NamingEnumeration search(Name base, Map env, ExprNode filter, SearchControls searchCtls) throws NamingException {
+            return ( NamingEnumeration ) JndiProvider.this.invoke( new Search( base, env, filter, searchCtls ) );
+        }
 
-    /**
-     * Allows the addition of an interceptor to pipelines based on invocation
-     * processing states.
-     *
-     * @param interceptor the interceptor to add to pipelines
-     * @param states the states (pipelines) where the interceptor should be applied
-     */
-    public void addInterceptor( Interceptor interceptor, InvocationStateEnum states[] )
-    {
-        for ( int ii = 0; ii < states.length; ii++ )
-        {
-            switch( states[ii].getValue() )
-            {
-                case( InvocationStateEnum.PREINVOCATION_VAL ):
-                    before.add( interceptor );
-                    break;
-                case( InvocationStateEnum.POSTINVOCATION_VAL ):
-                    after.add( interceptor );
-                    break;
-                case( InvocationStateEnum.FAILUREHANDLING_VAL ):
-                    afterFailure.add( interceptor );
-                    break;
-                default:
-                    throw new IllegalStateException( "unexpected invocation state: "
-                            + states[ii].getBaseName() );
-            }
+        public Attributes lookup(Name name) throws NamingException {
+            return ( Attributes ) JndiProvider.this.invoke( new Lookup( name ) );
         }
-    }
 
+        public Attributes lookup(Name dn, String[] attrIds) throws NamingException {
+            return ( Attributes ) JndiProvider.this.invoke( new LookupWithAttrIds( dn, attrIds ) );
+        }
 
-    /**
-     * A dead context is requested and returned when we shutdown the system. It
-     * prevents a {@link javax.naming.NoInitialContextException} from being
-     * thrown by InitialContext or one of its subclasses.
-     *
-     * @return a unusable dead context
-     */
-    public Context getDeadContext()
-    {
-        return new DeadContext();
+        public boolean hasEntry(Name name) throws NamingException {
+            return Boolean.TRUE.equals( JndiProvider.this.invoke( new HasEntry( name ) ) );
+        }
+
+        public boolean isSuffix(Name name) throws NamingException {
+            return Boolean.TRUE.equals( JndiProvider.this.invoke( new IsSuffix( name ) ) );
+        }
+
+        public void modifyRn(Name name, String newRn, boolean deleteOldRn) throws NamingException {
+            JndiProvider.this.invoke( new ModifyRN( name, newRn, deleteOldRn ) );
+        }
+
+        public void move(Name oriChildName, Name newParentName) throws NamingException {
+            JndiProvider.this.invoke( new Move( oriChildName, newParentName ) );
+        }
+
+        public void move(Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn) throws NamingException {
+            JndiProvider.this.invoke( new MoveAndModifyRN( oriChildName, newParentName, newRn, deleteOldRn ) );
+        }
+
+        public void sync() throws NamingException {
+            nexus.sync();
+        }
+
+        public void close() throws NamingException {
+            nexus.close();
+        }
+
+        public boolean isClosed() {
+            return nexus.isClosed();
+        }
+        
     }
 }

Modified: directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/InterceptorChain.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/InterceptorChain.java?view=diff&r1=158315&r2=158316
==============================================================================
--- directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/InterceptorChain.java (original)
+++ directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/InterceptorChain.java Sat Mar 19 23:19:29 2005
@@ -8,6 +8,7 @@
 
 import javax.naming.NamingException;
 
+import org.apache.ldap.server.BackingStore;
 import org.apache.ldap.server.jndi.call.Call;
 
 /**
@@ -22,7 +23,7 @@
  */
 public class InterceptorChain
 {
-    private static final Interceptor FINAL_PROCESSOR = new Interceptor()
+    private final Interceptor FINAL_PROCESSOR = new Interceptor()
     {
         public void init(Properties config) throws NamingException
         {
@@ -34,28 +35,35 @@
             // do nothing
         }
 
-        public void process(NextInterceptor nextProcessor, Call call)
+        public void process(NextInterceptor nextInterceptor, Call call)
                 throws NamingException
         {
-            // do nothing
+            call.execute( store );
         }
     };
 
+    private final BackingStore store;
     private final Map name2entry = new HashMap();
     private Entry head = new Entry( null, null, "", FINAL_PROCESSOR );
     private final Entry tail = head;
 
     /**
-     * Create a new processor chain.
+     * Create a new interceptor chain.
      */
-    public InterceptorChain()
+    public InterceptorChain( BackingStore store )
     {
+        if( store == null )
+        {
+            throw new NullPointerException( "store" ) ;
+        }
+        
+        this.store = store;
     }
 
     /**
-     * Returns the processor with the specified <code>name</code>.
+     * Returns the interceptor with the specified <code>name</code>.
      * 
-     * @return <code>null</code> if there is no processor with the specified
+     * @return <code>null</code> if there is no interceptor with the specified
      *         <code>name</code>.
      */
     public Interceptor get( String name )
@@ -65,50 +73,50 @@
         {
             return null;
         }
-        return e.processor;
+        return e.interceptor;
     }
 
     /**
-     * Adds the specified processor with the specified name at the beginning
+     * Adds the specified interceptor with the specified name at the beginning
      * of this chain.
      */
     public synchronized void addFirst( String name,
-                                       Interceptor processor )
+                                       Interceptor interceptor )
     {
         checkNewName( name );
         
-        Entry newEntry = new Entry( null, head, name, processor );
+        Entry newEntry = new Entry( null, head, name, interceptor );
         head.prevEntry = newEntry;
         head = newEntry;
     }
 
     /**
-     * Adds the specified processor with the specified name at the end
+     * Adds the specified interceptor with the specified name at the end
      * of this chain.
      */
     public synchronized void addLast( String name,
-                                      Interceptor processor )
+                                      Interceptor interceptor )
     {
         checkNewName( name );
         
-        Entry newEntry = new Entry( tail.prevEntry, tail, name, processor );
+        Entry newEntry = new Entry( tail.prevEntry, tail, name, interceptor );
         tail.prevEntry.nextEntry = newEntry;
         tail.prevEntry = newEntry;
     }
 
     /**
-     * Adds the specified processor with the specified name just before
-     * the processor whose name is <code>baseName</code> in this chain.
+     * 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 processor )
+                                        Interceptor interceptor )
     {
         Entry baseEntry = checkOldName( baseName );
         checkNewName( name );
 
         Entry prevEntry = baseEntry.prevEntry;
-        Entry newEntry = new Entry( prevEntry, baseEntry, name, processor );
+        Entry newEntry = new Entry( prevEntry, baseEntry, name, interceptor );
         if( prevEntry == null )
         {
             head = newEntry;
@@ -123,18 +131,18 @@
     }
     
     /**
-     * Adds the specified processor with the specified name just after
-     * the processor whose name is <code>baseName</code> in this chain.
+     * 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 processor )
+                                       Interceptor interceptor )
     {
         Entry baseEntry = checkOldName( baseName );
         checkNewName(name);
 
         Entry nextEntry = baseEntry.nextEntry;
-        Entry newEntry = new Entry( baseEntry, nextEntry, name, processor );
+        Entry newEntry = new Entry( baseEntry, nextEntry, name, interceptor );
         if( nextEntry == null )
         {
             throw new IllegalStateException();
@@ -146,7 +154,7 @@
     }
     
     /**
-     * Removes the processor with the specified name from this chain.
+     * Removes the interceptor with the specified name from this chain.
      */
     public synchronized void remove( String name )
     {
@@ -166,7 +174,7 @@
     }
 
     /**
-     * Removed all processors added to this chain.
+     * Removed all interceptors added to this chain.
      */
     public synchronized void clear()
     {
@@ -180,7 +188,7 @@
         Entry e = ( Entry ) name2entry.get( baseName );
         if( e == null )
         {
-            throw new IllegalArgumentException( "Unknown processor name:" +
+            throw new IllegalArgumentException( "Unknown interceptor name:" +
                                                 baseName );
         }
         return e;
@@ -191,7 +199,7 @@
         if( name2entry.containsKey( name ) )
         {
             throw new IllegalArgumentException(
-                    "Other processor is using name '" + name + "'" );
+                    "Other interceptor is using name '" + name + "'" );
         }
     }
     
@@ -204,8 +212,8 @@
         Entry head = this.head;
         try
         {
-            head.processor.process(
-                    head.nextProcessor, call );
+            head.interceptor.process(
+                    head.nextInterceptor, call );
         }
         catch( NamingException ne )
         {
@@ -213,13 +221,13 @@
         }
         catch( Throwable e )
         {
-            throw new InterceptorException( head.processor, call,
+            throw new InterceptorException( head.interceptor, call,
                                             "Unexpected exception.", e );
         }
     }
 
     /**
-     * Returns the list of processors this chain contains in the order of
+     * Returns the list of interceptors this chain contains in the order of
      * evaluation.
      */
     public List getAll()
@@ -228,7 +236,7 @@
         Entry e = head;
         do
         {
-            list.add( e.processor );
+            list.add( e.interceptor );
             e = e.nextEntry;
         }
         while( e != null );
@@ -237,7 +245,7 @@
     }
 
     /**
-     * Returns the list of processors this chain contains in the reversed
+     * Returns the list of interceptors this chain contains in the reversed
      * order of evaluation.
      */
     public List getAllReversed()
@@ -246,7 +254,7 @@
         Entry e = tail;
         do
         {
-            list.add( e.processor );
+            list.add( e.interceptor );
             e = e.prevEntry;
         }
         while( e != null );
@@ -259,15 +267,15 @@
         private Entry prevEntry;
         private Entry nextEntry;
         //private final String name;
-        private final Interceptor processor;
-        private final NextInterceptor nextProcessor;
+        private final Interceptor interceptor;
+        private final NextInterceptor nextInterceptor;
 
         private Entry( Entry prevEntry, Entry nextEntry,
-                       String name, Interceptor processor )
+                       String name, Interceptor interceptor )
         {
-            if( processor == null )
+            if( interceptor == null )
             {
-                throw new NullPointerException( "processor" );
+                throw new NullPointerException( "interceptor" );
             }
             if( name == null )
             {
@@ -277,16 +285,16 @@
             this.prevEntry = prevEntry;
             this.nextEntry = nextEntry;
             //this.name = name;
-            this.processor = processor;
-            this.nextProcessor = new NextInterceptor()
+            this.interceptor = interceptor;
+            this.nextInterceptor = new NextInterceptor()
             {
                 public void process(Call call)
                         throws NamingException {
-                    Interceptor processor = Entry.this.nextEntry.processor;
+                    Interceptor interceptor = Entry.this.nextEntry.interceptor;
                     try
                     {
-                        processor.process(
-                                Entry.this.nextEntry.nextProcessor, call );
+                        interceptor.process(
+                                Entry.this.nextEntry.nextInterceptor, call );
                     }
                     catch( NamingException ne )
                     {
@@ -294,7 +302,7 @@
                     }
                     catch( Throwable e )
                     {
-                        throw new InterceptorException( processor, call,
+                        throw new InterceptorException( interceptor, call,
                                                              "Unexpected exception.", e );
                     }
                 }

Added: directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java?view=auto&rev=158316
==============================================================================
--- directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java (added)
+++ directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java Sat Mar 19 23:19:29 2005
@@ -0,0 +1,375 @@
+/*
+ *   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.jndi.call.interceptor;
+
+
+import java.util.Properties;
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.exception.LdapContextNotEmptyException;
+import org.apache.ldap.common.exception.LdapNameAlreadyBoundException;
+import org.apache.ldap.common.exception.LdapNameNotFoundException;
+import org.apache.ldap.common.exception.LdapNamingException;
+import org.apache.ldap.common.message.ResultCodeEnum;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.server.RootNexus;
+import org.apache.ldap.server.jndi.call.Add;
+import org.apache.ldap.server.jndi.call.Delete;
+import org.apache.ldap.server.jndi.call.List;
+import org.apache.ldap.server.jndi.call.Lookup;
+import org.apache.ldap.server.jndi.call.LookupWithAttrIds;
+import org.apache.ldap.server.jndi.call.Modify;
+import org.apache.ldap.server.jndi.call.ModifyMany;
+import org.apache.ldap.server.jndi.call.ModifyRN;
+import org.apache.ldap.server.jndi.call.Move;
+import org.apache.ldap.server.jndi.call.MoveAndModifyRN;
+import org.apache.ldap.server.jndi.call.Search;
+
+
+/**
+ * An interceptor based service used to detect, raise and handle eve exceptions
+ * in one place.  This interceptor has two modes of operation.  The first mode
+ * is as a before chain interceptor where it raises exceptions.  An example
+ * where this interceptor raises an exception is when an entry already exists
+ * at a DN and is added once again to the same DN.  The other mode is as an on
+ * error chain interceptor.  In this mode the service may wrap exceptions and
+ * add extra information to an exception which is to be thrown back at the
+ * caller.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class Validator extends BaseInterceptor
+{
+    /** the root nexus of the system */
+    private RootNexus nexus = null;
+
+
+    /**
+     * Creates an interceptor that is also the exception handling service.
+     *
+     * @param nexus the root partition nexus
+     */
+    public Validator( RootNexus nexus )
+    {
+        this.nexus = nexus;
+    }
+    
+    public void init( Properties config )
+    {
+    }
+
+    public void destroy()
+    {
+    }
+
+    /**
+     * In the pre-invocation state this interceptor method checks to see if
+     * the entry to be added already exists.  If it does an exception is
+     * raised.
+     *
+     * @see BaseInterceptor#add(String, Name, Attributes)
+     */
+    protected void process( NextInterceptor nextInterceptor, Add call ) throws NamingException
+    {
+        // check if the entry already exists
+        Name normName = call.getNormalizedName();
+        String upName = call.getUserProvidedName();
+        if ( nexus.hasEntry( normName ) )
+        {
+            NamingException ne = new LdapNameAlreadyBoundException();
+            ne.setResolvedName( new LdapName( upName ) );
+            throw ne;
+        }
+
+        Name parentDn = new LdapName( upName );
+        parentDn = parentDn.getSuffix( 1 );
+
+        // check if we don't have the parent to add to
+        assertHasEntry( "Attempt to add under non-existant parent: ", parentDn );
+
+        // check if we're trying to add to a parent that is an alias
+        Attributes attrs = nexus.lookup( normName.getSuffix( 1 ) );
+        Attribute objectClass = attrs.get( "objectClass" );
+        if ( objectClass.contains( "alias" ) )
+        {
+            String msg = "Attempt to add entry to alias '" + upName
+                    + "' not allowed.";
+            ResultCodeEnum rc = ResultCodeEnum.ALIASPROBLEM;
+            NamingException e = new LdapNamingException( msg, rc );
+            e.setResolvedName( parentDn );
+            throw e;
+        }
+        
+        nextInterceptor.process( call );
+    }
+
+    /**
+     * Checks to make sure the entry being deleted exists, and has no children,
+     * otherwise throws the appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, Delete call ) throws NamingException
+    {
+        Name name = call.getName();
+        
+        // check if entry to delete exists
+        String msg = "Attempt to delete non-existant entry: ";
+        assertHasEntry( msg, name );
+
+        // check if entry to delete has children (only leaves can be deleted)
+        boolean hasChildren = false;
+        NamingEnumeration list = nexus.list( name );
+        if ( list.hasMore() )
+        {
+            hasChildren = true;
+        }
+
+        list.close();
+        if ( hasChildren )
+        {
+            LdapContextNotEmptyException e = new LdapContextNotEmptyException();
+            e.setResolvedName( name );
+            throw e;
+        }
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the base being searched exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, List call ) throws NamingException
+    {
+        // check if entry to search exists
+        String msg = "Attempt to search under non-existant entry: ";
+        assertHasEntry( msg, call.getBaseName() );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to make sure the entry being looked up exists other wise throws
+     * the appropriate LdapException.
+     *
+     * @see org.apache.ldap.server.jndi.BaseInterceptor#lookup(javax.naming.Name)
+     */
+    protected void process( NextInterceptor nextInterceptor, Lookup call ) throws NamingException
+    {
+        String msg = "Attempt to lookup non-existant entry: ";
+        assertHasEntry( msg, call.getName() );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the base being searched exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, LookupWithAttrIds call ) throws NamingException
+    {
+        // check if entry to lookup exists
+        String msg = "Attempt to lookup non-existant entry: ";
+        assertHasEntry( msg, call.getName() );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being modified exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, Modify call ) throws NamingException
+    {
+        // check if entry to modify exists
+        String msg = "Attempt to modify non-existant entry: ";
+        assertHasEntry( msg, call.getName() );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being modified exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, ModifyMany call ) throws NamingException
+    {
+        // check if entry to modify exists
+        String msg = "Attempt to modify non-existant entry: ";
+        assertHasEntry( msg, call.getName() );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being renamed exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, ModifyRN call ) throws NamingException
+    {
+        Name dn = call.getName();
+        String newRdn = call.getNewRelativeName();
+        
+        // check if entry to rename exists
+        String msg = "Attempt to rename non-existant entry: ";
+        assertHasEntry( msg, dn );
+
+        // check to see if target entry exists
+        Name target = dn.getSuffix( 1 ).add( newRdn );
+        if ( nexus.hasEntry( target ) )
+        {
+            LdapNameAlreadyBoundException e = null;
+            e = new LdapNameAlreadyBoundException( "target entry " + target
+                + " already exists!" );
+            e.setResolvedName( target );
+            throw e;
+        }
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being moved exists, and so does its parent,
+     * otherwise throws the appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, Move call ) throws NamingException
+    {
+        // check if child to move exists
+        String msg = "Attempt to move to non-existant parent: ";
+        assertHasEntry( msg, call.getName() );
+
+        // check if parent to move to exists
+        msg = "Attempt to move to non-existant parent: ";
+        assertHasEntry( msg, call.getNewParentName() );
+
+        // check to see if target entry exists
+        String rdn = call.getName().get( call.getName().size() - 1 );
+        Name target = ( Name ) call.getNewParentName().clone();
+        target.add( rdn );
+        if ( nexus.hasEntry( target ) )
+        {
+            LdapNameAlreadyBoundException e = null;
+            e = new LdapNameAlreadyBoundException( "target entry " + target
+                + " already exists!" );
+            e.setResolvedName( target );
+            throw e;
+        }
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being moved exists, and so does its parent,
+     * otherwise throws the appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, MoveAndModifyRN call ) throws NamingException
+    {
+        // check if child to move exists
+        String msg = "Attempt to move to non-existant parent: ";
+        assertHasEntry( msg, call.getName() );
+
+        // check if parent to move to exists
+        msg = "Attempt to move to non-existant parent: ";
+        assertHasEntry( msg, call.getNewParentName() );
+
+        // check to see if target entry exists
+        Name target = ( Name ) call.getNewParentName().clone();
+        target.add( call.getNewRelativeName() );
+        if ( nexus.hasEntry( target ) )
+        {
+            LdapNameAlreadyBoundException e = null;
+            e = new LdapNameAlreadyBoundException( "target entry " + target
+                + " already exists!" );
+            e.setResolvedName( target );
+            throw e;
+        }
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Checks to see the entry being searched exists, otherwise throws the
+     * appropriate LdapException.
+     */
+    protected void process( NextInterceptor nextInterceptor, Search call ) throws NamingException
+    {
+        String msg = "Attempt to search under non-existant entry: ";
+
+        Name base = call.getBaseName();
+        if ( base.size() == 0 )
+        {
+            nextInterceptor.process( call );
+            return;
+        }
+        
+        Attribute attr = nexus.getRootDSE().get( "subschemaSubentry" );
+        if ( ( ( String ) attr.get() ).equalsIgnoreCase( base.toString() ) )
+        {
+            nextInterceptor.process( call );
+            return;
+        }  
+
+        assertHasEntry( msg, base );
+        
+        nextInterceptor.process( call );
+    }
+
+
+    /**
+     * Asserts that an entry is present and as a side effect if it is not,
+     * creates a LdapNameNotFoundException, which is used to set the before
+     * exception on the invocation - eventually the exception is thrown.
+     *
+     * @param msg the message to prefix to the distinguished name for explanation
+     * @param dn the distinguished name of the entry that is asserted
+     * @param invocation the invocation object to alter if the entry does not exist
+     * @throws NamingException if the entry does not exist
+     */
+    private void assertHasEntry( String msg, Name dn ) throws NamingException
+    {
+        if ( ! nexus.hasEntry( dn ) )
+        {
+            LdapNameNotFoundException e = null;
+
+            if ( msg != null )
+            {
+                e = new LdapNameNotFoundException( msg + dn );
+            }
+            else
+            {
+                e = new LdapNameNotFoundException( dn.toString() );
+            }
+
+            e.setResolvedName( nexus.getMatchedDn( dn, false ) );
+            throw e;
+        }
+    }
+}

Propchange: directory/apacheds/branches/interceptor_revamp/core/src/main/java/org/apache/ldap/server/jndi/call/interceptor/Validator.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision