You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2011/11/13 01:01:55 UTC

svn commit: r1201364 [2/3] - in /directory/apacheds/branches/apacheds-osgi: all/ apache-felix/ core-annotations/ core-avl/ core-constants/ core-integ/ core-integ/src/test/java/org/apache/directory/server/core/authn/ppolicy/ core-integ/src/test/java/org...

Modified: directory/apacheds/branches/apacheds-osgi/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-osgi/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=1201364&r1=1201363&r2=1201364&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-osgi/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/branches/apacheds-osgi/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Sun Nov 13 00:01:54 2011
@@ -26,14 +26,21 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.io.StringReader;
+import java.lang.reflect.Method;
 import java.nio.channels.FileLock;
 import java.nio.channels.OverlappingFileLockException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.naming.directory.Attributes;
 
@@ -44,7 +51,9 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.core.api.DnFactory;
 import org.apache.directory.server.core.api.InstanceLayout;
+import org.apache.directory.server.core.api.InterceptorEnum;
 import org.apache.directory.server.core.api.LdapPrincipal;
+import org.apache.directory.server.core.api.OperationEnum;
 import org.apache.directory.server.core.api.OperationManager;
 import org.apache.directory.server.core.api.ReferralManager;
 import org.apache.directory.server.core.api.administrative.AccessControlAdministrativePoint;
@@ -56,12 +65,13 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.changelog.Tag;
 import org.apache.directory.server.core.api.changelog.TaggableSearchableChangeLogStore;
 import org.apache.directory.server.core.api.event.EventService;
+import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
 import org.apache.directory.server.core.api.interceptor.Interceptor;
-import org.apache.directory.server.core.api.interceptor.InterceptorChain;
 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
-import org.apache.directory.server.core.api.interceptor.context.EntryOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.OperationContext;
 import org.apache.directory.server.core.api.journal.Journal;
 import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.core.api.partition.PartitionNexus;
@@ -134,7 +144,7 @@ public class DefaultDirectoryService imp
 
     /** A reference on the SchemaManager */
     private SchemaManager schemaManager;
-    
+
     /** The LDAP Codec Service */
     private LdapApiService ldapCodecService = LdapApiServiceFactory.getSingleton();
 
@@ -144,9 +154,6 @@ public class DefaultDirectoryService imp
     /** whether or not server is started for the first time */
     private boolean firstStart;
 
-    /** The interceptor (or interceptor chain) for this service */
-    private InterceptorChain interceptorChain;
-
     /** whether or not this instance has been shutdown */
     private boolean started;
 
@@ -182,7 +189,7 @@ public class DefaultDirectoryService imp
 
     /** remove me after implementation is completed */
     private static final String PARTIAL_IMPL_WARNING =
-            "WARNING: the changelog is only partially operational and will revert\n" +
+        "WARNING: the changelog is only partially operational and will revert\n" +
             "state without consideration of who made the original change.  All reverting " +
             "changes are made by the admin user.\n Furthermore the used controls are not at " +
             "all taken into account";
@@ -234,6 +241,17 @@ public class DefaultDirectoryService imp
 
     /** The list of declared interceptors */
     private List<Interceptor> interceptors;
+    private Map<String, Interceptor> interceptorNames;
+
+    /** A lock to protect the interceptors List */
+    private ReadWriteLock interceptorsLock = new ReentrantReadWriteLock();
+
+    /** The read and write locks */
+    private Lock readLock  = interceptorsLock.readLock();
+    private Lock writeLock  = interceptorsLock.writeLock();
+
+    /** A map associating a list of interceptor to each operation */
+    private Map<OperationEnum, List<String>> operationInterceptors;
 
     /** The System partition */
     private Partition systemPartition;
@@ -275,7 +293,7 @@ public class DefaultDirectoryService imp
 
     /** The Dn factory */
     private DnFactory dnFactory;
-    
+
     /** The Subentry cache */
     SubentryCache subentryCache = new SubentryCache();
 
@@ -458,8 +476,215 @@ public class DefaultDirectoryService imp
     public List<Interceptor> getInterceptors()
     {
         List<Interceptor> cloned = new ArrayList<Interceptor>();
-        cloned.addAll( interceptors );
-        return cloned;
+
+        try
+        {
+            readLock.lock();
+
+            cloned.addAll( interceptors );
+
+            return cloned;
+        }
+        finally
+        {
+            readLock.unlock();
+        }
+    }
+
+
+    /**
+     * Returns interceptors in the server for a given operation.
+     *
+     * @return the interceptors in the server for the given operation.
+     */
+    public List<String> getInterceptors( OperationEnum operation )
+    {
+        List<String> cloned = new ArrayList<String>();
+
+        try
+        {
+            readLock.lock();
+            cloned.addAll( operationInterceptors.get( operation ) );
+
+            return cloned;
+        }
+        finally
+        {
+            readLock.unlock();
+        }
+
+    }
+
+
+    /**
+     * Compute the list of  to call for each operation
+     */
+    private void initOperationsList()
+    {
+        try
+        {
+            writeLock.lock();
+            operationInterceptors = new ConcurrentHashMap<OperationEnum, List<String>>();
+
+            for ( OperationEnum operation : OperationEnum.getOperations() )
+            {
+                List<String> operationList = new ArrayList<String>();
+
+                for ( Interceptor interceptor : interceptors )
+                {
+                    gatherInterceptors( interceptor, interceptor.getClass(), operation, operationList );
+                }
+                
+                operationInterceptors.put( operation, operationList );
+            }
+        }
+        finally
+        {
+            writeLock.unlock();
+        }
+    }
+
+
+    /**
+     * Recursively checks if the given interceptor can be added to the list of interceptors for a given
+     * operation and adds to the list of interceptors if it implements the respective operation
+     * 
+     * @param interceptor the instance of the interceptor
+     * @param interceptorClz the class of the interceptor
+     * @param operation type of operation
+     * @param selectedInterceptorList the list of selected interceptors
+     */
+    private void gatherInterceptors( Interceptor interceptor, Class<?> interceptorClz, OperationEnum operation, List<String> selectedInterceptorList )
+    {
+        // We stop recursing when we reach the Base class
+        if( ( interceptorClz == null ) || ( interceptorClz == BaseInterceptor.class ) )
+        {
+            return;
+        }
+
+        Method[] methods = interceptorClz.getDeclaredMethods();
+
+        for ( Method method : methods )
+        {
+            Class<?>[] param = method.getParameterTypes();
+            boolean hasCorrestSig = false;
+
+            // check for the correct signature
+            if( ( param == null ) || ( param.length > 1 ) || ( param.length == 0 ))
+            {
+                continue;
+            }
+
+            if ( OperationContext.class.isAssignableFrom( param[0] ) )
+            {
+                hasCorrestSig = true;
+            }
+            else
+            {
+                continue;
+            }
+
+            if ( hasCorrestSig && method.getName().equals( operation.getMethodName() ) )
+            {
+                selectedInterceptorList.add( interceptor.getName() );
+                break;
+            }
+        }
+
+        gatherInterceptors( interceptor, interceptorClz.getSuperclass(), operation, selectedInterceptorList );
+    }
+
+
+    /**
+     * Add an interceptor to the list of interceptors to call for each operation
+     * @throws LdapException
+     */
+    private void addInterceptor( Interceptor interceptor, int position ) throws LdapException
+    {
+        // First, init the interceptor
+        interceptor.init( this );
+
+        try
+        {
+            writeLock.lock();
+
+            for ( OperationEnum operation : OperationEnum.getOperations() )
+            {
+                List<String> operationList = operationInterceptors.get( operation );
+
+                Method[] methods = interceptor.getClass().getDeclaredMethods();
+
+                for ( Method method : methods )
+                {
+                    if ( method.getName().equals( operation.getMethodName() ) )
+                    {
+                        if ( position == -1 )
+                        {
+                            operationList.add( interceptor.getName() );
+                        }
+                        else
+                        {
+                            operationList.add( position, interceptor.getName() );
+                        }
+
+                        break;
+                    }
+                }
+            }
+
+            interceptorNames.put( interceptor.getName(), interceptor );
+
+            if ( position == -1 )
+            {
+                interceptors.add( interceptor );
+            }
+            else
+            {
+                interceptors.add( position, interceptor );
+            }
+        }
+        finally
+        {
+            writeLock.unlock();
+        }
+    }
+
+
+    /**
+     * Remove an interceptor to the list of interceptors to call for each operation
+     */
+    private void removeOperationsList( String interceptorName )
+    {
+        Interceptor interceptor = interceptorNames.get( interceptorName );
+
+        try
+        {
+            writeLock.lock();
+
+            for ( OperationEnum operation : OperationEnum.getOperations() )
+            {
+                List<String> operationList = operationInterceptors.get( operation );
+
+                Method[] methods = interceptor.getClass().getDeclaredMethods();
+
+                for ( Method method : methods )
+                {
+                    if ( method.getName().equals( operation.getMethodName() ) )
+                    {
+                        operationList.remove( interceptor.getName() );
+
+                        break;
+                    }
+                }
+            }
+
+            interceptorNames.remove( interceptorName );
+            interceptors.remove( interceptor );
+        }
+        finally
+        {
+            writeLock.unlock();
+        }
     }
 
 
@@ -470,19 +695,37 @@ public class DefaultDirectoryService imp
      */
     public void setInterceptors( List<Interceptor> interceptors )
     {
-        Set<String> names = new HashSet<String>();
+        Map<String, Interceptor> interceptorNames = new HashMap<String, Interceptor>();
 
+        // Check if we don't have duplicate names in the interceptors list
         for ( Interceptor interceptor : interceptors )
         {
-            if ( names.contains( interceptor.getName() ) )
+            if ( interceptorNames.containsKey( interceptor.getName() ) )
             {
                 LOG.warn( "Encountered duplicate definitions for {} interceptor", interceptor.getName() );
+                continue;
             }
-            
-            names.add( interceptor.getName() );
+
+            interceptorNames.put( interceptor.getName(), interceptor );
         }
 
         this.interceptors = interceptors;
+        this.interceptorNames = interceptorNames;
+
+        // Now update the Map that connect each operation with the list of interceptors.
+        initOperationsList();
+    }
+
+
+    /**
+     * Initialize the interceptors
+     */
+    private void initInterceptors() throws LdapException
+    {
+        for ( Interceptor interceptor : interceptors )
+        {
+            interceptor.init( this );
+        }
     }
 
 
@@ -496,6 +739,7 @@ public class DefaultDirectoryService imp
     {
         List<LdifEntry> cloned = new ArrayList<LdifEntry>();
         cloned.addAll( testEntries );
+
         return cloned;
     }
 
@@ -530,7 +774,7 @@ public class DefaultDirectoryService imp
     public void setInstanceLayout( InstanceLayout instanceLayout ) throws IOException
     {
         this.instanceLayout = instanceLayout;
-        
+
         // Create the directories if they are missing
         if ( !instanceLayout.getInstanceDirectory().exists() )
         {
@@ -547,7 +791,7 @@ public class DefaultDirectoryService imp
                 throw new IOException(I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY, instanceLayout.getLogDirectory() ) );
             }
         }
-        
+
         if ( !instanceLayout.getRunDirectory().exists() )
         {
             if ( !instanceLayout.getRunDirectory().mkdirs() )
@@ -555,7 +799,7 @@ public class DefaultDirectoryService imp
                 throw new IOException(I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY, instanceLayout.getRunDirectory() ) );
             }
         }
-        
+
         if ( !instanceLayout.getPartitionsDirectory().exists() )
         {
             if ( !instanceLayout.getPartitionsDirectory().mkdirs() )
@@ -563,7 +807,7 @@ public class DefaultDirectoryService imp
                 throw new IOException(I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY, instanceLayout.getPartitionsDirectory() ) );
             }
         }
-        
+
         if ( !instanceLayout.getConfDirectory().exists() )
         {
             if ( !instanceLayout.getConfDirectory().mkdirs() )
@@ -682,7 +926,7 @@ public class DefaultDirectoryService imp
             // We've got an exception, we cannot add the partition to the partitions
             throw le;
         }
-        
+
         // Now, add the partition to the set of managed partitions
         partitions.add( partition );
     }
@@ -704,7 +948,7 @@ public class DefaultDirectoryService imp
             // Bad ! We can't go any further
             throw le;
         }
-        
+
         // And update the set of managed partitions
         partitions.remove( partition );
     }
@@ -768,6 +1012,8 @@ public class DefaultDirectoryService imp
         BindOperationContext bindContext = new BindOperationContext( null );
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn );
+        bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
+
         operationManager.bind( bindContext );
 
         return bindContext.getSession();
@@ -776,7 +1022,7 @@ public class DefaultDirectoryService imp
 
     public CoreSession getSession( Dn principalDn, byte[] credentials, String saslMechanism, String saslAuthId )
         throws Exception
-    {
+        {
         if ( ! started )
         {
             throw new IllegalStateException( "Service has not started." );
@@ -786,10 +1032,12 @@ public class DefaultDirectoryService imp
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn );
         bindContext.setSaslMechanism( saslMechanism );
+        bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );
+
         operationManager.bind( bindContext );
 
         return bindContext.getSession();
-    }
+        }
 
 
     public long revert() throws LdapException
@@ -1017,13 +1265,13 @@ public class DefaultDirectoryService imp
         // load the last stored valid CSN value
         LookupOperationContext loc = new LookupOperationContext( getAdminSession() );
         loc.setDn( systemPartition.getSuffixDn() );
-        
+
         // get back all the attributes
         loc.setAttrsId( SchemaConstants.ALL_ATTRIBUTES_ARRAY );
         Entry entry = systemPartition.lookup( loc );
 
         Attribute cntextCsnAt = entry.get( SchemaConstants.CONTEXT_CSN_AT );
-        
+
         if ( cntextCsnAt != null )
         {
             // this is a multivalued attribute but current syncrepl provider implementation stores only ONE value at ou=system
@@ -1102,9 +1350,8 @@ public class DefaultDirectoryService imp
         // --------------------------------------------------------------------
         // And shutdown the server
         // --------------------------------------------------------------------
-        interceptorChain.destroy();
         cacheService.destroy();
-        
+
         if ( lockFile != null )
         {
             try
@@ -1160,7 +1407,7 @@ public class DefaultDirectoryService imp
         this.schemaManager = schemaManager;
     }
 
-    
+
     public LdapApiService getLdapCodecService()
     {
         return ldapCodecService;
@@ -1191,12 +1438,6 @@ public class DefaultDirectoryService imp
     }
 
 
-    public InterceptorChain getInterceptorChain()
-    {
-        return interceptorChain;
-    }
-
-
     public boolean isFirstStart()
     {
         return firstStart;
@@ -1234,17 +1475,17 @@ public class DefaultDirectoryService imp
         /*
          * If the admin entry is there, then the database was already created
          */
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, adminDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, adminDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, adminDn );
 
             serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
-                                SchemaConstants.TOP_OC,
-                                SchemaConstants.PERSON_OC,
-                                SchemaConstants.ORGANIZATIONAL_PERSON_OC,
-                                SchemaConstants.INET_ORG_PERSON_OC );
+                SchemaConstants.TOP_OC,
+                SchemaConstants.PERSON_OC,
+                SchemaConstants.ORGANIZATIONAL_PERSON_OC,
+                SchemaConstants.INET_ORG_PERSON_OC );
 
             serverEntry.put( SchemaConstants.UID_AT, PartitionNexus.ADMIN_UID );
             serverEntry.put( SchemaConstants.USER_PASSWORD_AT, PartitionNexus.ADMIN_PASSWORD_BYTES );
@@ -1267,15 +1508,15 @@ public class DefaultDirectoryService imp
 
         Dn userDn = getDnFactory().create( ServerDNConstants.USERS_SYSTEM_DN );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, userDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, userDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, userDn );
 
             serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
-                                SchemaConstants.TOP_OC,
-                                SchemaConstants.ORGANIZATIONAL_UNIT_OC );
+                SchemaConstants.TOP_OC,
+                SchemaConstants.ORGANIZATIONAL_UNIT_OC );
 
             serverEntry.put( SchemaConstants.OU_AT, "users" );
             serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
@@ -1292,15 +1533,15 @@ public class DefaultDirectoryService imp
 
         Dn groupDn = getDnFactory().create( ServerDNConstants.GROUPS_SYSTEM_DN );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, groupDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, groupDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, groupDn );
 
             serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
-                                SchemaConstants.TOP_OC,
-                                SchemaConstants.ORGANIZATIONAL_UNIT_OC );
+                SchemaConstants.TOP_OC,
+                SchemaConstants.ORGANIZATIONAL_UNIT_OC );
 
             serverEntry.put( SchemaConstants.OU_AT, "groups" );
             serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
@@ -1317,15 +1558,15 @@ public class DefaultDirectoryService imp
 
         Dn name = getDnFactory().create( ServerDNConstants.ADMINISTRATORS_GROUP_DN );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, name ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, name ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, name );
 
             serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
-                                SchemaConstants.TOP_OC,
-                                SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC );
+                SchemaConstants.TOP_OC,
+                SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC );
 
             serverEntry.put( SchemaConstants.CN_AT, "Administrators" );
             serverEntry.put( SchemaConstants.UNIQUE_MEMBER_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
@@ -1343,7 +1584,7 @@ public class DefaultDirectoryService imp
 
         Dn configurationDn = getDnFactory().create( "ou=configuration,ou=system" );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, configurationDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, configurationDn ) ) )
         {
             firstStart = true;
 
@@ -1365,7 +1606,7 @@ public class DefaultDirectoryService imp
 
         Dn partitionsDn = getDnFactory().create( "ou=partitions,ou=configuration,ou=system" );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, partitionsDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, partitionsDn ) ) )
         {
             firstStart = true;
 
@@ -1386,7 +1627,7 @@ public class DefaultDirectoryService imp
 
         Dn servicesDn = getDnFactory().create( "ou=services,ou=configuration,ou=system" );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, servicesDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, servicesDn ) ) )
         {
             firstStart = true;
 
@@ -1408,7 +1649,7 @@ public class DefaultDirectoryService imp
 
         Dn interceptorsDn = getDnFactory().create( "ou=interceptors,ou=configuration,ou=system" );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, interceptorsDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, interceptorsDn ) ) )
         {
             firstStart = true;
 
@@ -1430,7 +1671,7 @@ public class DefaultDirectoryService imp
 
         Dn sysPrefRootDn = getDnFactory().create( ServerDNConstants.SYSPREFROOT_SYSTEM_DN );
 
-        if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, sysPrefRootDn ) ) )
+        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, sysPrefRootDn ) ) )
         {
             firstStart = true;
 
@@ -1508,24 +1749,24 @@ public class DefaultDirectoryService imp
             }
         }
     }
-    
-    
+
+
     private void initializeSystemPartition() throws Exception
     {
         Partition system = getSystemPartition();
-        
+
         // Add root context entry for system partition
         Dn systemSuffixDn = getDnFactory().create( ServerDNConstants.SYSTEM_DN );
         CoreSession adminSession = getAdminSession();
 
-        if ( !system.hasEntry( new EntryOperationContext( adminSession, systemSuffixDn ) ) )
+        if ( !system.hasEntry( new HasEntryOperationContext( adminSession, systemSuffixDn ) ) )
         {
             Entry systemEntry = new DefaultEntry( schemaManager, systemSuffixDn );
-            
+
             // Add the ObjectClasses
             systemEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                 SchemaConstants.ORGANIZATIONAL_UNIT_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );
-            
+
             // Add some operational attributes
             systemEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN );
             systemEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
@@ -1533,7 +1774,7 @@ public class DefaultDirectoryService imp
             systemEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );
             systemEntry.put( DnUtils.getRdnAttributeType( ServerDNConstants.SYSTEM_DN ), DnUtils
                 .getRdnValue( ServerDNConstants.SYSTEM_DN ) );
-            
+
             AddOperationContext addOperationContext = new AddOperationContext( adminSession, systemEntry );
             system.add( addOperationContext );
         }
@@ -1551,7 +1792,7 @@ public class DefaultDirectoryService imp
         {
             LOG.debug( "---> Initializing the DefaultDirectoryService " );
         }
-        
+
         cacheService = new CacheService();
         cacheService.initialize( this );
 
@@ -1562,7 +1803,7 @@ public class DefaultDirectoryService imp
         triggerExecutionAPCache = new DnNode<TriggerExecutionAdministrativePoint>();
 
         dnFactory = new DefaultDnFactory( schemaManager, cacheService.getCache( "dnCache" ) );
-        
+
         // triggers partition to load schema fully from schema partition
         schemaPartition.initialize();
         partitions.add( schemaPartition );
@@ -1577,15 +1818,15 @@ public class DefaultDirectoryService imp
         partitionNexus.initialize( );
 
         initializeSystemPartition();
-        
+
         // --------------------------------------------------------------------
         // Create all the bootstrap entries before initializing chain
         // --------------------------------------------------------------------
 
         firstStart = createBootstrapEntries();
-        
-        interceptorChain = new InterceptorChain();
-        interceptorChain.init( this );
+
+        // Initialize the interceptors
+        initInterceptors();
 
         // --------------------------------------------------------------------
         // Initialize the changeLog if it's enabled
@@ -1598,7 +1839,7 @@ public class DefaultDirectoryService imp
             if( changeLog.isExposed() && changeLog.isTagSearchSupported() )
             {
                 String clSuffix = ( ( TaggableSearchableChangeLogStore ) changeLog.getChangeLogStore() ).getPartition().getSuffixDn().getName();
-                partitionNexus.getRootDSE( null ).add( SchemaConstants.CHANGELOG_CONTEXT_AT, clSuffix );
+                partitionNexus.getRootDse( null ).add( SchemaConstants.CHANGELOG_CONTEXT_AT, clSuffix );
             }
         }
 
@@ -1774,15 +2015,61 @@ public class DefaultDirectoryService imp
      */
     public Interceptor getInterceptor( String interceptorName )
     {
-        for ( Interceptor interceptor:interceptors )
+        try
         {
-            if ( interceptor.getName().equalsIgnoreCase( interceptorName ) )
+            readLock.lock();
+
+            for ( Interceptor interceptor:interceptors )
             {
-                return interceptor;
+                if ( interceptor.getName().equalsIgnoreCase( interceptorName ) )
+                {
+                    return interceptor;
+                }
             }
+
+            return null;
         }
+        finally
+        {
+            readLock.unlock();
+        }
+    }
+
 
-        return null;
+    /**
+     * {@inheritDoc}
+     * @throws LdapException
+     */
+    public void addFirst( Interceptor interceptor ) throws LdapException
+    {
+        addInterceptor( interceptor, 0 );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws LdapException
+     */
+    public void addLast( Interceptor interceptor ) throws LdapException
+    {
+        addInterceptor( interceptor, -1 );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addAfter( String interceptorName, Interceptor interceptor )
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void remove( String interceptorName )
+    {
+        removeOperationsList( interceptorName );
     }
 
 
@@ -1941,24 +2228,24 @@ public class DefaultDirectoryService imp
     {
         return triggerExecutionAPCache;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
     public boolean isPwdPolicyEnabled()
     {
-        AuthenticationInterceptor authenticationInterceptor = (AuthenticationInterceptor)getInterceptor( AuthenticationInterceptor.class.getSimpleName() );
-        
+        AuthenticationInterceptor authenticationInterceptor = (AuthenticationInterceptor)getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() );
+
         if ( authenticationInterceptor == null )
         {
             return false;
         }
 
         PpolicyConfigContainer pwdPolicyContainer = authenticationInterceptor.getPwdPolicyContainer();
-        
-        return ( ( pwdPolicyContainer != null ) 
-                && ( ( pwdPolicyContainer.getDefaultPolicy() != null ) 
+
+        return ( ( pwdPolicyContainer != null )
+            && ( ( pwdPolicyContainer.getDefaultPolicy() != null )
                 || ( pwdPolicyContainer.hasCustomConfigs() ) ) );
     }
 
@@ -1979,8 +2266,8 @@ public class DefaultDirectoryService imp
     {
         return subentryCache;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
@@ -1988,5 +2275,4 @@ public class DefaultDirectoryService imp
     {
         return evaluator;
     }
-
 }
\ No newline at end of file