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


import java.io.BufferedReader;
import java.io.File;
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 org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.csn.Csn;
import org.apache.directory.api.ldap.model.csn.CsnFactory;
import org.apache.directory.api.ldap.model.cursor.Cursor;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
import org.apache.directory.api.ldap.model.exception.LdapOperationException;
import org.apache.directory.api.ldap.model.ldif.ChangeType;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.ldap.model.ldif.LdifReader;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.DnUtils;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.util.tree.DnNode;
import org.apache.directory.api.util.DateUtils;
import org.apache.directory.api.util.Strings;
import org.apache.directory.api.util.exception.NotImplementedException;
import org.apache.directory.server.constants.ApacheSchemaConstants;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.admin.AdministrativePointInterceptor;
import org.apache.directory.server.core.api.AttributeTypeProvider;
import org.apache.directory.server.core.api.CacheService;
import org.apache.directory.server.core.api.CoreSession;
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.ObjectClassProvider;
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;
import org.apache.directory.server.core.api.administrative.CollectiveAttributeAdministrativePoint;
import org.apache.directory.server.core.api.administrative.SubschemaAdministrativePoint;
import org.apache.directory.server.core.api.administrative.TriggerExecutionAdministrativePoint;
import org.apache.directory.server.core.api.changelog.ChangeLog;
import org.apache.directory.server.core.api.changelog.ChangeLogEvent;
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.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
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;
import org.apache.directory.server.core.api.schema.SchemaPartition;
import org.apache.directory.server.core.api.subtree.SubentryCache;
import org.apache.directory.server.core.api.subtree.SubtreeEvaluator;
import org.apache.directory.server.core.authn.AuthenticationInterceptor;
import org.apache.directory.server.core.authn.ppolicy.PpolicyConfigContainer;
import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
import org.apache.directory.server.core.changelog.ChangeLogInterceptor;
import org.apache.directory.server.core.changelog.DefaultChangeLog;
import org.apache.directory.server.core.collective.CollectiveAttributeInterceptor;
import org.apache.directory.server.core.event.EventInterceptor;
import org.apache.directory.server.core.exception.ExceptionInterceptor;
import org.apache.directory.server.core.journal.DefaultJournal;
import org.apache.directory.server.core.journal.JournalInterceptor;
import org.apache.directory.server.core.normalization.NormalizationInterceptor;
import org.apache.directory.server.core.operational.OperationalAttributeInterceptor;
import org.apache.directory.server.core.referral.ReferralInterceptor;
import org.apache.directory.server.core.schema.SchemaInterceptor;
import org.apache.directory.server.core.security.TlsKeyGenerator;
import org.apache.directory.server.core.shared.DefaultCoreSession;
import org.apache.directory.server.core.shared.DefaultDnFactory;
import org.apache.directory.server.core.shared.partition.DefaultPartitionNexus;
import org.apache.directory.server.core.subtree.SubentryInterceptor;
import org.apache.directory.server.core.trigger.TriggerInterceptor;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Default implementation of {@link DirectoryService}.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class DefaultDirectoryService implements DirectoryService
{
    /** The logger */
    private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryService.class );

    private SchemaPartition schemaPartition;

    /** A reference on the SchemaManager */
    private SchemaManager schemaManager;

    /** The LDAP Codec Service */
    private LdapApiService ldapCodecService = LdapApiServiceFactory.getSingleton();

    /** the root nexus */
    private DefaultPartitionNexus partitionNexus;

    /** whether or not server is started for the first time */
    private boolean firstStart;

    /** whether or not this instance has been shutdown */
    private boolean started;

    /** the change log service */
    private ChangeLog changeLog;

    /** the journal service */
    private Journal journal;

    /**
     * the interface used to perform various operations on this
     * DirectoryService
     */
    private OperationManager operationManager = new DefaultOperationManager( this );

    /** the distinguished name of the administrative user */
    private Dn adminDn;

    /** session used as admin for internal operations */
    private CoreSession adminSession;

    /** The referral manager */
    private ReferralManager referralManager;

    /** A flag to tell if the userPassword attribute's value must be hidden */
    private boolean passwordHidden = false;

    /** The service's CSN factory */
    private CsnFactory csnFactory;

    /** The directory instance replication ID */
    private int replicaId;

    /** remove me after implementation is completed */
    private static final String PARTIAL_IMPL_WARNING =
        "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";

    /** The delay to wait between each sync on disk */
    private long syncPeriodMillis;

    /** The default delay to wait between sync on disk : 15 seconds */
    private static final long DEFAULT_SYNC_PERIOD = 15000;

    /** */
    private Thread workerThread;

    /** The default timeLimit : 100 entries */
    public static final int MAX_SIZE_LIMIT_DEFAULT = 100;

    /** The default timeLimit : 10 seconds */
    public static final int MAX_TIME_LIMIT_DEFAULT = 10000;

    /** The instance Id */
    private String instanceId;

    /** The server directory layout*/
    private InstanceLayout instanceLayout;

    /**
     * A flag used to shutdown the VM when stopping the server. Useful
     * when the server is standalone. If the server is embedded, we don't
     * want to shutdown the VM
     */
    private boolean exitVmOnShutdown = true; // allow by default

    /** A flag used to indicate that a shutdown hook has been installed */
    private boolean shutdownHookEnabled = true; // allow by default

    /** Manage anonymous access to entries other than the RootDSE */
    private boolean allowAnonymousAccess = false; // forbid by default

    /** Manage the basic access control checks */
    private boolean accessControlEnabled; // off by default

    /** Manage the operational attributes denormalization */
    private boolean denormalizeOpAttrsEnabled; // off by default

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

    /** The set of all declared partitions */
    private Set<Partition> partitions = new HashSet<Partition>();

    /** A list of LDIF entries to inject at startup */
    private List<? extends LdifEntry> testEntries = new ArrayList<LdifEntry>(); // List<Attributes>

    /** The event service */
    private EventService eventService;

    /** The maximum size for an incoming PDU */
    private int maxPDUSize = Integer.MAX_VALUE;

    /** lock file for directory service's working directory */
    private RandomAccessFile lockFile = null;

    private static final String LOCK_FILE_NAME = ".dirservice.lock";

    /** the ehcache based cache service */
    private CacheService cacheService;

    /** The AccessControl AdministrativePoint cache */
    private DnNode<AccessControlAdministrativePoint> accessControlAPCache;

    /** The CollectiveAttribute AdministrativePoint cache */
    private DnNode<CollectiveAttributeAdministrativePoint> collectiveAttributeAPCache;

    /** The Subschema AdministrativePoint cache */
    private DnNode<SubschemaAdministrativePoint> subschemaAPCache;

    /** The TriggerExecution AdministrativePoint cache */
    private DnNode<TriggerExecutionAdministrativePoint> triggerExecutionAPCache;

    /** The Dn factory */
    private DnFactory dnFactory;

    /** The Subentry cache */
    SubentryCache subentryCache = new SubentryCache();

    /** The Subtree evaluator instance */
    private SubtreeEvaluator evaluator;

    /** The attribute type provider */
    private AttributeTypeProvider atProvider;

    /** The object class provider */
    private ObjectClassProvider ocProvider;


    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------

    /**
     * Creates a new instance of the directory service.
     */
    public DefaultDirectoryService() throws Exception
    {
        changeLog = new DefaultChangeLog();
        journal = new DefaultJournal();
        syncPeriodMillis = DEFAULT_SYNC_PERIOD;
        csnFactory = new CsnFactory( replicaId );
        evaluator = new SubtreeEvaluator( schemaManager );
        setDefaultInterceptorConfigurations();
    }


    // ------------------------------------------------------------------------
    // C O N F I G U R A T I O N   M E T H O D S
    // ------------------------------------------------------------------------

    public void setInstanceId( String instanceId )
    {
        this.instanceId = instanceId;
    }


    public String getInstanceId()
    {
        return instanceId;
    }


    /**
     * Gets the {@link Partition}s used by this DirectoryService.
     *
     * @return the set of partitions used
     */
    public Set<? extends Partition> getPartitions()
    {
        Set<Partition> cloned = new HashSet<Partition>();
        cloned.addAll( partitions );
        return cloned;
    }


    /**
     * Sets {@link Partition}s used by this DirectoryService.
     *
     * @param partitions the partitions to used
     */
    public void setPartitions( Set<? extends Partition> partitions )
    {
        Set<Partition> cloned = new HashSet<Partition>();
        cloned.addAll( partitions );
        Set<String> names = new HashSet<String>();

        for ( Partition partition : cloned )
        {
            String id = partition.getId();

            if ( names.contains( id ) )
            {
                LOG.warn( "Encountered duplicate partition {} identifier.", id );
            }

            names.add( id );
        }

        this.partitions = cloned;
    }


    /**
     * Returns <tt>true</tt> if access control checks are enabled.
     *
     * @return true if access control checks are enabled, false otherwise
     */
    public boolean isAccessControlEnabled()
    {
        return accessControlEnabled;
    }


    /**
     * Sets whether to enable basic access control checks or not.
     *
     * @param accessControlEnabled true to enable access control checks, false otherwise
     */
    public void setAccessControlEnabled( boolean accessControlEnabled )
    {
        this.accessControlEnabled = accessControlEnabled;
    }


    /**
     * Returns <tt>true</tt> if anonymous access is allowed on entries besides the RootDSE.
     * If the access control subsystem is enabled then access to some entries may not be
     * allowed even when full anonymous access is enabled.
     *
     * @return true if anonymous access is allowed on entries besides the RootDSE, false
     * if anonymous access is allowed to all entries.
     */
    public boolean isAllowAnonymousAccess()
    {
        return allowAnonymousAccess;
    }


    /**
     * Sets whether to allow anonymous access to entries other than the RootDSE.  If the
     * access control subsystem is enabled then access to some entries may not be allowed
     * even when full anonymous access is enabled.
     *
     * @param enableAnonymousAccess true to enable anonymous access, false to disable it
     */
    public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
    {
        this.allowAnonymousAccess = enableAnonymousAccess;
    }


    /**
     * Returns interceptors in the server.
     *
     * @return the interceptors in the server.
     */
    public List<Interceptor> getInterceptors()
    {
        List<Interceptor> cloned = new ArrayList<Interceptor>();

        readLock.lock();

        try
        {
            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>();

        readLock.lock();

        try
        {
            cloned.addAll( operationInterceptors.get( operation ) );

            return cloned;
        }
        finally
        {
            readLock.unlock();
        }

    }


    /**
     * Compute the list of  to call for each operation
     */
    private void initOperationsList()
    {
        writeLock.lock();

        try
        {
            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;
        }

        // We don't call getMethods() because it would get back the default methods
        // from the BaseInterceptor, something we don't want.
        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() ) )
            {
                if ( !selectedInterceptorList.contains( interceptor.getName() ) )
                {
                    selectedInterceptorList.add( interceptor.getName() );
                }

                break;
            }
        }

        // Recurse on extended classes, as we have used getDeclaredMethods() instead of getmethods()
        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 );

        writeLock.lock();

        try
        {
            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 );

        writeLock.lock();

        try
        {
            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();
        }
    }


    /**
     * Sets the interceptors in the server.
     *
     * @param interceptors the interceptors to be used in the server.
     */
    public void setInterceptors( List<Interceptor> interceptors )
    {
        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 ( interceptorNames.containsKey( interceptor.getName() ) )
            {
                LOG.warn( "Encountered duplicate definitions for {} interceptor", interceptor.getName() );
                continue;
            }

            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 );
        }
    }


    /**
     * Returns test directory entries({@link LdifEntry}) to be loaded while
     * bootstrapping.
     *
     * @return test entries to load during bootstrapping
     */
    public List<LdifEntry> getTestEntries()
    {
        List<LdifEntry> cloned = new ArrayList<LdifEntry>();
        cloned.addAll( testEntries );

        return cloned;
    }


    /**
     * Sets test directory entries({@link Attributes}) to be loaded while
     * bootstrapping.
     *
     * @param testEntries the test entries to load while bootstrapping
     */
    public void setTestEntries( List<? extends LdifEntry> testEntries )
    {
        //noinspection MismatchedQueryAndUpdateOfCollection
        List<LdifEntry> cloned = new ArrayList<LdifEntry>();
        cloned.addAll( testEntries );
        this.testEntries = testEntries;
    }


    /**
     * {@inheritDoc}
     */
    public InstanceLayout getInstanceLayout()
    {
        return instanceLayout;
    }


    /**
     * {@inheritDoc}
     */
    public void setInstanceLayout( InstanceLayout instanceLayout ) throws IOException
    {
        this.instanceLayout = instanceLayout;

        // Create the directories if they are missing
        if ( !instanceLayout.getInstanceDirectory().exists() )
        {
            if ( !instanceLayout.getInstanceDirectory().mkdirs() )
            {
                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
                    instanceLayout.getInstanceDirectory() ) );
            }
        }

        if ( !instanceLayout.getLogDirectory().exists() )
        {
            if ( !instanceLayout.getLogDirectory().mkdirs() )
            {
                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
                    instanceLayout.getLogDirectory() ) );
            }
        }

        if ( !instanceLayout.getRunDirectory().exists() )
        {
            if ( !instanceLayout.getRunDirectory().mkdirs() )
            {
                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
                    instanceLayout.getRunDirectory() ) );
            }
        }

        if ( !instanceLayout.getPartitionsDirectory().exists() )
        {
            if ( !instanceLayout.getPartitionsDirectory().mkdirs() )
            {
                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
                    instanceLayout.getPartitionsDirectory() ) );
            }
        }

        if ( !instanceLayout.getConfDirectory().exists() )
        {
            if ( !instanceLayout.getConfDirectory().mkdirs() )
            {
                throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY,
                    instanceLayout.getConfDirectory() ) );
            }
        }
    }


    public void setShutdownHookEnabled( boolean shutdownHookEnabled )
    {
        this.shutdownHookEnabled = shutdownHookEnabled;
    }


    public boolean isShutdownHookEnabled()
    {
        return shutdownHookEnabled;
    }


    public void setExitVmOnShutdown( boolean exitVmOnShutdown )
    {
        this.exitVmOnShutdown = exitVmOnShutdown;
    }


    public boolean isExitVmOnShutdown()
    {
        return exitVmOnShutdown;
    }


    public void setSystemPartition( Partition systemPartition )
    {
        this.systemPartition = systemPartition;
    }


    public Partition getSystemPartition()
    {
        return systemPartition;
    }


    /**
     * return true if the operational attributes must be normalized when returned
     */
    public boolean isDenormalizeOpAttrsEnabled()
    {
        return denormalizeOpAttrsEnabled;
    }


    /**
     * Sets whether the operational attributes are denormalized when returned
     * @param denormalizeOpAttrsEnabled The flag value
     */
    public void setDenormalizeOpAttrsEnabled( boolean denormalizeOpAttrsEnabled )
    {
        this.denormalizeOpAttrsEnabled = denormalizeOpAttrsEnabled;
    }


    /**
     * {@inheritDoc}
     */
    public ChangeLog getChangeLog()
    {
        return changeLog;
    }


    /**
     * {@inheritDoc}
     */
    public Journal getJournal()
    {
        return journal;
    }


    /**
     * {@inheritDoc}
     */
    public void setChangeLog( ChangeLog changeLog )
    {
        this.changeLog = changeLog;
    }


    /**
     * {@inheritDoc}
     */
    public void setJournal( Journal journal )
    {
        this.journal = journal;
    }


    public void addPartition( Partition partition ) throws Exception
    {
        partition.setSchemaManager( schemaManager );

        try
        {
            // can be null when called before starting up
            if ( partitionNexus != null )
            {
                partitionNexus.addContextPartition( partition );
            }
        }
        catch ( LdapException le )
        {
            // 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 );
    }


    public void removePartition( Partition partition ) throws Exception
    {
        // Do the backend cleanup first
        try
        {
            // can be null when called before starting up
            if ( partitionNexus != null )
            {
                partitionNexus.removeContextPartition( partition.getSuffixDn().getNormName() );
            }
        }
        catch ( LdapException le )
        {
            // Bad ! We can't go any further
            throw le;
        }

        // And update the set of managed partitions
        partitions.remove( partition );
    }


    // ------------------------------------------------------------------------
    // BackendSubsystem Interface Method Implementations
    // ------------------------------------------------------------------------
    /**
     * Define a default list of interceptors that has to be used if no other
     * configuration is defined.
     */
    private void setDefaultInterceptorConfigurations()
    {
        // Set default interceptor chains
        List<Interceptor> list = new ArrayList<Interceptor>();

        list.add( new NormalizationInterceptor() );
        list.add( new AuthenticationInterceptor() );
        list.add( new ReferralInterceptor() );
        list.add( new AciAuthorizationInterceptor() );
        list.add( new DefaultAuthorizationInterceptor() );
        list.add( new AdministrativePointInterceptor() );
        list.add( new ExceptionInterceptor() );
        list.add( new SchemaInterceptor() );
        list.add( new OperationalAttributeInterceptor() );
        list.add( new CollectiveAttributeInterceptor() );
        list.add( new SubentryInterceptor() );
        list.add( new EventInterceptor() );
        list.add( new TriggerInterceptor() );
        list.add( new ChangeLogInterceptor() );
        list.add( new JournalInterceptor() );

        setInterceptors( list );
    }


    public CoreSession getAdminSession()
    {
        return adminSession;
    }


    /**
     * Get back an anonymous session
     */
    public CoreSession getSession()
    {
        return new DefaultCoreSession( new LdapPrincipal( schemaManager ), this );
    }


    /** 
     * Get back a session for a given principal
     */
    public CoreSession getSession( LdapPrincipal principal )
    {
        return new DefaultCoreSession( principal, this );
    }


    /**
     * Get back a session for the give user and credentials bound with Simple Bind
     */
    public CoreSession getSession( Dn principalDn, byte[] credentials ) throws LdapException
    {
        synchronized ( this )
        {
            if ( !started )
            {
                throw new IllegalStateException( "Service has not started." );
            }
        }

        BindOperationContext bindContext = new BindOperationContext( null );
        bindContext.setCredentials( credentials );
        bindContext.setDn( principalDn.apply( schemaManager ) );
        bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );

        operationManager.bind( bindContext );

        return bindContext.getSession();
    }


    /**
     * Get back a session for a given user bound with SASL Bind
     */
    public CoreSession getSession( Dn principalDn, byte[] credentials, String saslMechanism, String saslAuthId )
        throws Exception
    {
        synchronized ( this )
        {
            if ( !started )
            {
                throw new IllegalStateException( "Service has not started." );

            }
        }

        BindOperationContext bindContext = new BindOperationContext( null );
        bindContext.setCredentials( credentials );
        bindContext.setDn( principalDn.apply( schemaManager ) );
        bindContext.setSaslMechanism( saslMechanism );
        bindContext.setInterceptors( getInterceptors( OperationEnum.BIND ) );

        operationManager.bind( bindContext );

        return bindContext.getSession();
    }


    public long revert() throws LdapException
    {
        if ( changeLog == null || !changeLog.isEnabled() )
        {
            throw new IllegalStateException( I18n.err( I18n.ERR_310 ) );
        }

        Tag latest = changeLog.getLatest();

        if ( null != latest )
        {
            if ( latest.getRevision() < changeLog.getCurrentRevision() )
            {
                return revert( latest.getRevision() );
            }
            else
            {
                LOG.info( "Ignoring request to revert without changes since the latest tag." );
                return changeLog.getCurrentRevision();
            }
        }

        throw new IllegalStateException( I18n.err( I18n.ERR_311 ) );
    }


    /**
     * We handle the ModDN/ModRDN operation for the revert here.
     */
    private void moddn( Dn oldDn, Dn newDn, boolean delOldRdn ) throws LdapException
    {
        if ( oldDn.size() == 0 )
        {
            throw new LdapNoPermissionException( I18n.err( I18n.ERR_312 ) );
        }

        // calculate parents
        Dn oldBase = oldDn.getParent();
        Dn newBase = newDn.getParent();

        // Compute the Rdn for each of the Dn
        Rdn newRdn = newDn.getRdn();
        Rdn oldRdn = oldDn.getRdn();

        /*
         * We need to determine if this rename operation corresponds to a simple
         * Rdn name change or a move operation.  If the two names are the same
         * except for the Rdn then it is a simple modifyRdn operation.  If the
         * names differ in size or have a different baseDN then the operation is
         * a move operation.  Furthermore if the Rdn in the move operation
         * changes it is both an Rdn change and a move operation.
         */
        if ( ( oldDn.size() == newDn.size() ) && oldBase.equals( newBase ) )
        {
            adminSession.rename( oldDn, newRdn, delOldRdn );
        }
        else
        {
            Dn target = newDn.getParent();

            if ( newRdn.equals( oldRdn ) )
            {
                adminSession.move( oldDn, target );
            }
            else
            {
                adminSession.moveAndRename( oldDn, target, new Rdn( newRdn ), delOldRdn );
            }
        }
    }


    public long revert( long revision ) throws LdapException
    {
        if ( changeLog == null || !changeLog.isEnabled() )
        {
            throw new IllegalStateException( I18n.err( I18n.ERR_310 ) );
        }

        if ( revision < 0 )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_239 ) );
        }

        if ( revision >= changeLog.getChangeLogStore().getCurrentRevision() )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_314 ) );
        }

        Cursor<ChangeLogEvent> cursor = changeLog.getChangeLogStore().findAfter( revision );

        /*
         * BAD, BAD, BAD!!!
         *
         * No synchronization no nothing.  Just getting this to work for now
         * so we can revert tests.  Any production grade use of this feature
         * needs to synchronize on all changes while the revert is in progress.
         *
         * How about making this operation transactional?
         *
         * First of all just stop using JNDI and construct the operations to
         * feed into the interceptor pipeline.
         *
         * TODO review this code.
         */

        try
        {
            LOG.warn( PARTIAL_IMPL_WARNING );
            cursor.afterLast();

            while ( cursor.previous() ) // apply ldifs in reverse order
            {
                ChangeLogEvent event = cursor.get();
                List<LdifEntry> reverses = event.getReverseLdifs();

                for ( LdifEntry reverse : reverses )
                {
                    switch ( reverse.getChangeType().getChangeType() )
                    {
                        case ChangeType.ADD_ORDINAL:
                            adminSession.add(
                                new DefaultEntry( schemaManager, reverse.getEntry() ), true );
                            break;

                        case ChangeType.DELETE_ORDINAL:
                            adminSession.delete( reverse.getDn(), true );
                            break;

                        case ChangeType.MODIFY_ORDINAL:
                            List<Modification> mods = reverse.getModifications();

                            adminSession.modify( reverse.getDn(), mods, true );
                            break;

                        case ChangeType.MODDN_ORDINAL:
                            // NO BREAK - both ModDN and ModRDN handling is the same

                        case ChangeType.MODRDN_ORDINAL:
                            Dn forwardDn = event.getForwardLdif().getDn();
                            Dn reverseDn = reverse.getDn();

                            moddn( reverseDn, forwardDn, reverse.isDeleteOldRdn() );

                            break;

                        default:
                            LOG.error( I18n.err( I18n.ERR_75 ) );
                            throw new NotImplementedException( I18n.err( I18n.ERR_76, reverse.getChangeType() ) );
                    }
                }
            }
        }
        catch ( Exception e )
        {
            throw new LdapOperationException( e.getMessage(), e );
        }
        finally
        {
            try
            {
                cursor.close();
            }
            catch ( Exception e )
            {
                throw new LdapOperationException( e.getMessage(), e );
            }
        }

        return changeLog.getCurrentRevision();
    }


    public OperationManager getOperationManager()
    {
        return operationManager;
    }


    /**
     * @throws Exception if the LDAP server cannot be started
     */
    public synchronized void startup() throws Exception
    {
        if ( started )
        {
            return;
        }

        lockWorkDir();

        if ( shutdownHookEnabled )
        {
            Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
            {
                public void run()
                {
                    try
                    {
                        shutdown();
                    }
                    catch ( Exception e )
                    {
                        LOG.warn( "Failed to shut down the directory service: "
                            + DefaultDirectoryService.this.instanceId, e );
                    }
                }
            }, "ApacheDS Shutdown Hook (" + instanceId + ')' ) );

            LOG.info( "ApacheDS shutdown hook has been registered with the runtime." );
        }
        else if ( LOG.isWarnEnabled() )
        {
            LOG.warn( "ApacheDS shutdown hook has NOT been registered with the runtime."
                + "  This default setting for standalone operation has been overriden." );
        }

        initialize();
        showSecurityWarnings();

        started = true;

        if ( !testEntries.isEmpty() )
        {
            createTestEntries();
        }
    }


    public synchronized void sync() throws Exception
    {
        if ( !started )
        {
            return;
        }

        this.changeLog.sync();
        this.partitionNexus.sync();
    }


    public synchronized void shutdown() throws Exception
    {
        LOG.debug( "+++ DirectoryService Shutdown required" );

        if ( !started )
        {
            return;
        }

        // --------------------------------------------------------------------
        // Shutdown the sync thread
        // --------------------------------------------------------------------
        LOG.debug( "--- Syncing the nexus " );
        LOG.debug( "--- Flushing everything before quitting" );
        getOperationManager().lockWrite();
        partitionNexus.sync();
        getOperationManager().unlockWrite();

        // --------------------------------------------------------------------
        // Shutdown the changelog
        // --------------------------------------------------------------------
        LOG.debug( "--- Syncing the changeLog " );
        changeLog.sync();
        changeLog.destroy();

        // --------------------------------------------------------------------
        // Shutdown the journal if enabled
        // --------------------------------------------------------------------
        if ( journal.isEnabled() )
        {
            LOG.debug( "--- Destroying the journal " );
            journal.destroy();
        }

        
        // --------------------------------------------------------------------
        // Shutdown the partition
        // --------------------------------------------------------------------

        LOG.debug( "--- Destroying the nexus" );
        partitionNexus.destroy();
        
        // --------------------------------------------------------------------
        // And shutdown the server
        // --------------------------------------------------------------------
        LOG.debug( "--- Deleting the cache service" );
        cacheService.destroy();

        LOG.debug( "---Deleting the DnCache" );
        dnFactory = null;

        if ( lockFile != null )
        {
            try
            {
                lockFile.close();
                // no need to delete the lock file
            }
            catch ( IOException e )
            {
                LOG.warn( "couldn't delete the lock file {}", LOCK_FILE_NAME );
            }
        }

        LOG.debug( "+++ DirectoryService stopped" );
        started = false;
    }


    /**
     * @return The referral manager
     */
    public ReferralManager getReferralManager()
    {
        return referralManager;
    }


    /**
     * Set the referralManager
     * @param referralManager The initialized referralManager
     */
    public void setReferralManager( ReferralManager referralManager )
    {
        this.referralManager = referralManager;
    }


    /**
     * @return the SchemaManager
     */
    public SchemaManager getSchemaManager()
    {
        return schemaManager;
    }


    /**
     * Set the SchemaManager instance.
     *
     * @param schemaManager The server schemaManager
     */
    public void setSchemaManager( SchemaManager schemaManager )
    {
        this.schemaManager = schemaManager;
    }


    public LdapApiService getLdapCodecService()
    {
        return ldapCodecService;
    }


    /**
     * {@inheritDoc}
     */
    public SchemaPartition getSchemaPartition()
    {
        return schemaPartition;
    }


    /**
     * {@inheritDoc}
     */
    public void setSchemaPartition( SchemaPartition schemaPartition )
    {
        this.schemaPartition = schemaPartition;
    }


    public DefaultPartitionNexus getPartitionNexus()
    {
        return partitionNexus;
    }


    public boolean isFirstStart()
    {
        return firstStart;
    }


    public synchronized boolean isStarted()
    {
        return started;
    }


    public Entry newEntry( Dn dn )
    {
        return new DefaultEntry( schemaManager, dn );
    }


    /**
     * Returns true if we had to create the bootstrap entries on the first
     * start of the server.  Otherwise if all entries exist, meaning none
     * had to be created, then we are not starting for the first time.
     *
     * @return true if the bootstrap entries had to be created, false otherwise
     * @throws Exception if entries cannot be created
     */
    private boolean createBootstrapEntries() throws Exception
    {
        boolean firstStart = false;

        // -------------------------------------------------------------------
        // create admin entry
        // -------------------------------------------------------------------

        /*
         * If the admin entry is there, then the database was already created
         */
        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 );

            serverEntry.put( SchemaConstants.UID_AT, PartitionNexus.ADMIN_UID );
            serverEntry.put( SchemaConstants.USER_PASSWORD_AT, PartitionNexus.ADMIN_PASSWORD_BYTES );
            serverEntry.put( SchemaConstants.DISPLAY_NAME_AT, "Directory Superuser" );
            serverEntry.put( SchemaConstants.CN_AT, "system administrator" );
            serverEntry.put( SchemaConstants.SN_AT, "administrator" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.put( SchemaConstants.DISPLAY_NAME_AT, "Directory Superuser" );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            TlsKeyGenerator.addKeyPair( serverEntry );
            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system users area
        // -------------------------------------------------------------------

        Dn userDn = getDnFactory().create( ServerDNConstants.USERS_SYSTEM_DN );

        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 );

            serverEntry.put( SchemaConstants.OU_AT, "users" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system groups area
        // -------------------------------------------------------------------

        Dn groupDn = getDnFactory().create( ServerDNConstants.GROUPS_SYSTEM_DN );

        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 );

            serverEntry.put( SchemaConstants.OU_AT, "groups" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create administrator group
        // -------------------------------------------------------------------

        Dn name = getDnFactory().create( ServerDNConstants.ADMINISTRATORS_GROUP_DN );

        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 );

            serverEntry.put( SchemaConstants.CN_AT, "Administrators" );
            serverEntry.put( SchemaConstants.UNIQUE_MEMBER_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system configuration area
        // -------------------------------------------------------------------

        Dn configurationDn = getDnFactory().create( "ou=configuration,ou=system" );

        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, configurationDn ) ) )
        {
            firstStart = true;

            Entry serverEntry = new DefaultEntry( schemaManager, configurationDn );
            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC );

            serverEntry.put( SchemaConstants.OU_AT, "configuration" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system configuration area for partition information
        // -------------------------------------------------------------------

        Dn partitionsDn = getDnFactory().create( "ou=partitions,ou=configuration,ou=system" );

        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, partitionsDn ) ) )
        {
            firstStart = true;

            Entry serverEntry = new DefaultEntry( schemaManager, partitionsDn );
            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC );
            serverEntry.put( SchemaConstants.OU_AT, "partitions" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system configuration area for services
        // -------------------------------------------------------------------

        Dn servicesDn = getDnFactory().create( "ou=services,ou=configuration,ou=system" );

        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, servicesDn ) ) )
        {
            firstStart = true;

            Entry serverEntry = new DefaultEntry( schemaManager, servicesDn );
            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC );

            serverEntry.put( SchemaConstants.OU_AT, "services" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system configuration area for interceptors
        // -------------------------------------------------------------------

        Dn interceptorsDn = getDnFactory().create( "ou=interceptors,ou=configuration,ou=system" );

        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, interceptorsDn ) ) )
        {
            firstStart = true;

            Entry serverEntry = new DefaultEntry( schemaManager, interceptorsDn );
            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC );

            serverEntry.put( SchemaConstants.OU_AT, "interceptors" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        // -------------------------------------------------------------------
        // create system preferences area
        // -------------------------------------------------------------------

        Dn sysPrefRootDn = getDnFactory().create( ServerDNConstants.SYSPREFROOT_SYSTEM_DN );

        if ( !partitionNexus.hasEntry( new HasEntryOperationContext( adminSession, sysPrefRootDn ) ) )
        {
            firstStart = true;

            Entry serverEntry = new DefaultEntry( schemaManager, sysPrefRootDn );
            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
                SchemaConstants.TOP_OC,
                SchemaConstants.ORGANIZATIONAL_UNIT_OC,
                SchemaConstants.EXTENSIBLE_OBJECT_OC );

            serverEntry.put( "prefNodeName", "sysPrefRoot" );
            serverEntry.put( SchemaConstants.CREATORS_NAME_AT, ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED );
            serverEntry.put( SchemaConstants.CREATE_TIMESTAMP_AT, DateUtils.getGeneralizedTime() );
            serverEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            serverEntry.add( SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString() );

            partitionNexus.add( new AddOperationContext( adminSession, serverEntry ) );
        }

        return firstStart;
    }


    /**
     * Displays security warning messages if any possible secutiry issue is found.
     * @throws Exception if there are failures parsing and accessing internal structures
     */
    // made protected as per the request in DIRSERVER-1920
    protected void showSecurityWarnings() throws Exception
    {
        // Warn if the default password is not changed.
        boolean needToChangeAdminPassword = false;

        Dn adminDn = getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );

        Entry adminEntry = partitionNexus.lookup( new LookupOperationContext( adminSession, adminDn ) );
        Value<?> userPassword = adminEntry.get( SchemaConstants.USER_PASSWORD_AT ).get();
        needToChangeAdminPassword = Arrays.equals( PartitionNexus.ADMIN_PASSWORD_BYTES, userPassword.getBytes() );

        if ( needToChangeAdminPassword )
        {
            LOG.warn( "You didn't change the admin password of directory service " + "instance '" + instanceId + "'.  "
                + "Please update the admin password as soon as possible " + "to prevent a possible security breach." );
        }
    }


    /**
     * Adds test entries into the core.
     *
     * @todo this may no longer be needed when JNDI is not used for bootstrapping
     *
     * @throws Exception if the creation of test entries fails.
     */
    private void createTestEntries() throws Exception
    {
        for ( LdifEntry testEntry : testEntries )
        {
            try
            {
                LdifEntry ldifEntry = testEntry.clone();
                Entry entry = ldifEntry.getEntry();
                String dn = ldifEntry.getDn().getName();

                try
                {
                    getAdminSession().add( new DefaultEntry( schemaManager, entry ) );
                }
                catch ( Exception e )
                {
                    LOG.warn( dn + " test entry already exists.", e );
                }
            }
            catch ( CloneNotSupportedException cnse )
            {
                LOG.warn( "Cannot clone the entry ", cnse );
            }
        }
    }


    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 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() );
            systemEntry.add( SchemaConstants.ENTRY_CSN_AT, getCSN().toString() );
            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 );
        }
    }


    /**
     * Kicks off the initialization of the entire system.
     *
     * @throws Exception if there are problems along the way
     */
    private void initialize() throws Exception
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( "---> Initializing the DefaultDirectoryService " );
        }

        csnFactory.setReplicaId( replicaId );

        // If no interceptor list is defined, setup a default list
        if ( interceptors == null )
        {
            setDefaultInterceptorConfigurations();
        }

        if ( cacheService == null )
        {
            // Initialize a default cache service
            cacheService = new CacheService();
        }

        cacheService.initialize( instanceLayout, instanceId );

        // Initialize the AP caches
        accessControlAPCache = new DnNode<AccessControlAdministrativePoint>();
        collectiveAttributeAPCache = new DnNode<CollectiveAttributeAdministrativePoint>();
        subschemaAPCache = new DnNode<SubschemaAdministrativePoint>();
        triggerExecutionAPCache = new DnNode<TriggerExecutionAdministrativePoint>();

        if ( dnFactory == null )
        {
            dnFactory = new DefaultDnFactory( schemaManager, cacheService.getCache( "dnCache" ) );
        }

        // triggers partition to load schema fully from schema partition
        schemaPartition.setCacheService( cacheService );
        schemaPartition.initialize();
        partitions.add( schemaPartition );
        systemPartition.setCacheService( cacheService );
        systemPartition.getSuffixDn().apply( schemaManager );

        adminDn = getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
        adminSession = new DefaultCoreSession( new LdapPrincipal( schemaManager, adminDn, AuthenticationLevel.STRONG ),
            this );

        // @TODO - NOTE: Need to find a way to instantiate without dependency on DPN
        partitionNexus = new DefaultPartitionNexus( new DefaultEntry( schemaManager, Dn.ROOT_DSE ) );
        partitionNexus.setDirectoryService( this );
        partitionNexus.initialize();

        initializeSystemPartition();

        // --------------------------------------------------------------------
        // Create all the bootstrap entries before initializing chain
        // --------------------------------------------------------------------

        firstStart = createBootstrapEntries();

        // initialize schema providers
        atProvider = new AttributeTypeProvider( schemaManager );
        ocProvider = new ObjectClassProvider( schemaManager );

        // Initialize the interceptors
        initInterceptors();

        // --------------------------------------------------------------------
        // Initialize the changeLog if it's enabled
        // --------------------------------------------------------------------

        if ( changeLog.isEnabled() )
        {
            changeLog.init( this );

            if ( changeLog.isExposed() && changeLog.isTagSearchSupported() )
            {
                String clSuffix = ( ( TaggableSearchableChangeLogStore ) changeLog.getChangeLogStore() ).getPartition()
                    .getSuffixDn().getName();
                partitionNexus.getRootDse( null ).add( ApacheSchemaConstants.CHANGELOG_CONTEXT_AT, clSuffix );
            }
        }

        // --------------------------------------------------------------------
        // Initialize the journal if it's enabled
        // --------------------------------------------------------------------
        if ( journal.isEnabled() )
        {
            journal.init( this );
        }

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( "<--- DefaultDirectoryService initialized" );
        }
    }


    /**
     * Read an entry (without Dn)
     *
     * @param text The ldif format file
     * @return An entry.
     */
    // This will suppress PMD.EmptyCatchBlock warnings in this method
    @SuppressWarnings("PMD.EmptyCatchBlock")
    private Entry readEntry( String text )
    {
        StringReader strIn = new StringReader( text );
        BufferedReader in = new BufferedReader( strIn );

        String line = null;
        Entry entry = new DefaultEntry();

        try
        {
            while ( ( line = in.readLine() ) != null )
            {
                if ( line.length() == 0 )
                {
                    continue;
                }

                String addedLine = line.trim();

                if ( Strings.isEmpty( addedLine ) )
                {
                    continue;
                }

                Attribute attribute = LdifReader.parseAttributeValue( addedLine );
                Attribute oldAttribute = entry.get( attribute.getId() );

                if ( oldAttribute != null )
                {
                    try
                    {
                        oldAttribute.add( attribute.get() );
                        entry.put( oldAttribute );
                    }
                    catch ( LdapException ne )
                    {
                        // Do nothing
                    }
                }
                else
                {
                    try
                    {
                        entry.put( attribute );
                    }
                    catch ( LdapException ne )
                    {
                        // TODO do nothing ...
                    }
                }
            }
        }
        catch ( IOException ioe )
        {
            // Do nothing : we can't reach this point !
        }

        return entry;
    }


    /**
     * Create a new Entry
     *
     * @param ldif The String representing the attributes, as a LDIF file
     * @param dn The Dn for this new entry
     */
    public Entry newEntry( String ldif, String dn )
    {
        try
        {
            Entry entry = readEntry( ldif );
            Dn newDn = getDnFactory().create( dn );

            entry.setDn( newDn );

            // TODO Let's get rid of this Attributes crap
            Entry serverEntry = new DefaultEntry( schemaManager, entry );
            return serverEntry;
        }
        catch ( Exception e )
        {
            LOG.error( I18n.err( I18n.ERR_78, ldif, dn ) );
            // do nothing
            return null;
        }
    }


    public EventService getEventService()
    {
        return eventService;
    }


    public void setEventService( EventService eventService )
    {
        this.eventService = eventService;
    }


    /**
     * {@inheritDoc}
     */
    public boolean isPasswordHidden()
    {
        return passwordHidden;
    }


    /**
     * {@inheritDoc}
     */
    public void setPasswordHidden( boolean passwordHidden )
    {
        this.passwordHidden = passwordHidden;
    }


    /**
     * @return The maximum allowed size for an incoming PDU
     */
    public int getMaxPDUSize()
    {
        return maxPDUSize;
    }


    /**
     * Set the maximum allowed size for an incoming PDU
     * @param maxPDUSize A positive number of bytes for the PDU. A negative or
     * null value will be transformed to {@link Integer#MAX_VALUE}
     */
    public void setMaxPDUSize( int maxPDUSize )
    {
        if ( maxPDUSize <= 0 )
        {
            maxPDUSize = Integer.MAX_VALUE;
        }

        this.maxPDUSize = maxPDUSize;
    }


    /**
     * {@inheritDoc}
     */
    public Interceptor getInterceptor( String interceptorName )
    {
        readLock.lock();

        try
        {
            return interceptorNames.get( interceptorName );
        }
        finally
        {
            readLock.unlock();
        }
    }


    /**
     * {@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 )
    {
        writeLock.lock();

        try
        {
            int position = 0;

            // Find the position
            for ( Interceptor inter : interceptors )
            {
                if ( interceptorName.equals( inter.getName() ) )
                {
                    break;
                }

                position++;
            }

            if ( position == interceptors.size() )
            {
                interceptors.add( interceptor );
            }
            else
            {
                interceptors.add( position, interceptor );
            }
        }
        finally
        {
            writeLock.unlock();
        }
    }


    /**
     * {@inheritDoc}
     */
    public void remove( String interceptorName )
    {
        removeOperationsList( interceptorName );
    }


    /**
     * Get a new CSN
     * @return The CSN generated for this directory service
     */
    public Csn getCSN()
    {
        return csnFactory.newInstance();
    }


    /**
     * @return the replicaId
     */
    public int getReplicaId()
    {
        return replicaId;
    }


    /**
     * @param replicaId the replicaId to set
     */
    public void setReplicaId( int replicaId )
    {
        if ( ( replicaId < 0 ) || ( replicaId > 999 ) )
        {
            LOG.error( I18n.err( I18n.ERR_79 ) );
            this.replicaId = 0;
        }
        else
        {
            this.replicaId = replicaId;
        }
    }


    /**
     * {@inheritDoc}
     */
    public long getSyncPeriodMillis()
    {
        return syncPeriodMillis;
    }


    /**
     * {@inheritDoc}
     */
    public void setSyncPeriodMillis( long syncPeriodMillis )
    {
        this.syncPeriodMillis = syncPeriodMillis;
    }


    /**
     * checks if the working directory is already in use by some other directory service, if yes
     * then throws a runtime exception else will obtain the lock on the working directory
     */
    private void lockWorkDir()
    {
        FileLock fileLock = null;

        try
        {
            lockFile = new RandomAccessFile( new File( instanceLayout.getInstanceDirectory(), LOCK_FILE_NAME ), "rw" );
            try
            {
                fileLock = lockFile.getChannel().tryLock( 0, 1, false );
            }
            catch ( IOException e )
            {
                // shoudn't happen, but log
                LOG.error( "failed to lock the work directory", e );
            }
            catch ( OverlappingFileLockException e ) // thrown if we can't get a lock
            {
                fileLock = null;
            }
        }
        catch ( FileNotFoundException e )
        {
            // shouldn't happen, but log anyway
            LOG.error( "failed to lock the work directory", e );
        }

        if ( ( fileLock == null ) || ( !fileLock.isValid() ) )
        {
            String message = "the working directory " + instanceLayout.getRunDirectory()
                + " has been locked by another directory service.";
            LOG.error( message );
            throw new RuntimeException( message );
        }

    }


    /**
     * {@inheritDoc}
     */
    public CacheService getCacheService()
    {
        return cacheService;
    }


    /**
     * {@inheritDoc}
     */
    public DnNode<AccessControlAdministrativePoint> getAccessControlAPCache()
    {
        return accessControlAPCache;
    }


    /**
     * {@inheritDoc}
     */
    public DnNode<CollectiveAttributeAdministrativePoint> getCollectiveAttributeAPCache()
    {
        return collectiveAttributeAPCache;
    }


    /**
     * {@inheritDoc}
     */
    public DnNode<SubschemaAdministrativePoint> getSubschemaAPCache()
    {
        return subschemaAPCache;
    }


    /**
     * {@inheritDoc}
     */
    public DnNode<TriggerExecutionAdministrativePoint> getTriggerExecutionAPCache()
    {
        return triggerExecutionAPCache;
    }


    /**
     * {@inheritDoc}
     */
    public boolean isPwdPolicyEnabled()
    {
        AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) getInterceptor( InterceptorEnum.AUTHENTICATION_INTERCEPTOR
            .getName() );

        if ( authenticationInterceptor == null )
        {
            return false;
        }

        PpolicyConfigContainer pwdPolicyContainer = authenticationInterceptor.getPwdPolicyContainer();

        return ( ( pwdPolicyContainer != null )
        && ( ( pwdPolicyContainer.getDefaultPolicy() != null )
        || ( pwdPolicyContainer.hasCustomConfigs() ) ) );
    }


    /**
     * {@inheritDoc}
     */
    public DnFactory getDnFactory()
    {
        return dnFactory;
    }


    /**
     * {@inheritDoc}
     */
    public void setDnFactory( DnFactory dnFactory )
    {
        this.dnFactory = dnFactory;
    }


    /**
     * {@inheritDoc}
     */
    public SubentryCache getSubentryCache()
    {
        return subentryCache;
    }


    /**
     * {@inheritDoc}
     */
    public SubtreeEvaluator getEvaluator()
    {
        return evaluator;
    }


    /**
     * {@inheritDoc}
     */
    public void setCacheService( CacheService cacheService )
    {
        this.cacheService = cacheService;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public AttributeTypeProvider getAtProvider()
    {
        return atProvider;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ObjectClassProvider getOcProvider()
    {
        return ocProvider;
    }

}