/*
 *  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.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.exception.LdapOtherException;
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.partition.PartitionTxn;
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;

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

    /** A list of LDIF entries to inject at startup */
    private List<? extends LdifEntry> testEntries = new ArrayList<>(); // 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.
     * 
     * @throws LdapException If the instance cannot be created
     */
    public DefaultDirectoryService() throws LdapException
    {
        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<>();
        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<>();
        cloned.addAll( partitions );
        Set<String> names = new HashSet<>();

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

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

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

            for ( OperationEnum operation : OperationEnum.getOperations() )
            {
                List<String> operationList = new ArrayList<>();

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

            // check for the correct signature
            if ( ( param != null ) && ( param.length == 1 ) 
                    && OperationContext.class.isAssignableFrom( param[0] ) && 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 ConcurrentHashMap<>();

        // 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<>();
        cloned.addAll( testEntries );

        return cloned;
    }


    /**
     * Sets test directory entries 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<>();
        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() && !instanceLayout.getInstanceDirectory().mkdirs() )
        {
            throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECTORY,
                instanceLayout.getInstanceDirectory() ) );
        }

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

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

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

        if ( !instanceLayout.getConfDirectory().exists() && !instanceLayout.getConfDirectory().mkdirs() )
        {
            throw new IOException( I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECTORY,
                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;
    }


    /**
     * {@inheritDoc}
     */
    public void addPartition( Partition partition ) throws LdapException
    {
        partition.setSchemaManager( schemaManager );

        // can be null when called before starting up
        if ( partitionNexus != null )
        {
            partitionNexus.addContextPartition( partition );
        }

        // Now, add the partition to the set of managed partitions
        partitions.add( partition );
    }


    /**
     * {@inheritDoc}
     */
    public void removePartition( Partition partition ) throws LdapException
    {
        // Do the backend cleanup first
        // can be null when called before starting up
        if ( partitionNexus != null )
        {
            partitionNexus.removeContextPartition( partition.getSuffixDn().getNormName() );
        }

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

        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 );
        
        if ( principalDn.isSchemaAware() )
        {
            bindContext.setDn( principalDn );
        }
        else
        {
            bindContext.setDn( new Dn( schemaManager, principalDn ) );
        }
        
        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 LdapException
    {
        synchronized ( this )
        {
            if ( !started )
            {
                throw new IllegalStateException( "Service has not started." );

            }
        }

        BindOperationContext bindContext = new BindOperationContext( null );
        bindContext.setTransaction( partitionNexus.beginReadTransaction() );
        bindContext.setCredentials( credentials );

        if ( principalDn.isSchemaAware() )
        {
            bindContext.setDn( principalDn );
        }
        else
        {
            bindContext.setDn( new Dn( schemaManager, principalDn ) );
        }

        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, 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 LdapException if the LDAP server cannot be started
     */
    public synchronized void startup() throws LdapException
    {
        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 LdapException
    {
        if ( !started )
        {
            return;
        }

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


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

        if ( !started )
        {
            return;
        }

        // --------------------------------------------------------------------
        // Shutdown the sync thread
        // --------------------------------------------------------------------
        LOG.debug( "--- Syncing the nexus " );
        LOG.debug( "--- Flushing everything before quitting" );
        operationManager.lockWrite();
        partitionNexus.sync();
        operationManager.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( null );
        
        // --------------------------------------------------------------------
        // Shutdown the interceptors
        // --------------------------------------------------------------------
        LOG.debug( "--- Destroying the interceptors" );
        
        for ( Interceptor interceptor : interceptors )
        {
            interceptor.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 );
    }
    
    
    /**
     * Add a new entry into the server
     */
    private void addEntry( Entry serverEntry ) throws LdapException
    {
        Partition partition = partitionNexus.getPartition( serverEntry.getDn() );
        AddOperationContext addContext = new AddOperationContext( adminSession, serverEntry );
        PartitionTxn partitionTxn = null;

        try
        {
            partitionTxn = partition.beginWriteTransaction();
            addContext.setTransaction( partitionTxn );
            addContext.setPartition( partition );
            partitionNexus.add( addContext );
            partitionTxn.commit();
        }
        catch ( LdapException le )
        {
            try
            {
                partitionTxn.abort();
            }
            catch ( IOException ioe )
            {
                throw new LdapOtherException( ioe.getMessage(), ioe );
            }
            
            throw le;
        }
        catch ( IOException ioe )
        {
            try
            {
                partitionTxn.abort();
            }
            catch ( IOException ioe2 )
            {
                throw new LdapOtherException( ioe2.getMessage(), ioe2 );
            }
            
            throw new LdapOtherException( ioe.getMessage(), ioe );
        }
    }


    /**
     * 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 LdapException if entries cannot be created
     */
    private boolean createBootstrapEntries() throws LdapException, IOException
    {
        boolean firstStart = false;

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

        /*
         * If the admin entry is there, then the database was already created
         */
        Partition partition = partitionNexus.getPartition( adminDn );
        
        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, adminDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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 );
                
                addEntry( serverEntry );
            }
        }

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

        Dn userDn = getDnFactory().create( ServerDNConstants.USERS_SYSTEM_DN );
        partition = partitionNexus.getPartition( userDn );

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, userDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
                
                addEntry( serverEntry );
            }
        }

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

        Dn groupDn = getDnFactory().create( ServerDNConstants.GROUPS_SYSTEM_DN );
        partition = partitionNexus.getPartition( groupDn );

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, groupDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }
        
        // -------------------------------------------------------------------
        // create administrator group
        // -------------------------------------------------------------------

        Dn name = getDnFactory().create( ServerDNConstants.ADMINISTRATORS_GROUP_DN );
        partition = partitionNexus.getPartition( name );

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, name );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

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

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

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, configurationDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

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

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

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, partitionsDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

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

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

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, servicesDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

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

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

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, interceptorsDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

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

        Dn sysPrefRootDn = getDnFactory().create( ServerDNConstants.SYSPREFROOT_SYSTEM_DN );
        partition = partitionNexus.getPartition( sysPrefRootDn );

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( adminSession, sysPrefRootDn );
            hasEntryContext.setPartition( partition );
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !partitionNexus.hasEntry( hasEntryContext ) )
            {
                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() );
    
                addEntry( serverEntry );
            }
        }

        return firstStart;
    }


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

        Dn admin = getDnFactory().create( ServerDNConstants.ADMIN_SYSTEM_DN );
        Partition partition = partitionNexus.getPartition( admin );
        LookupOperationContext lookupContext = new LookupOperationContext( adminSession, admin );
        lookupContext.setPartition( partition );
        
        Entry adminEntry;

        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            lookupContext.setTransaction( partitionTxn );
            adminEntry = partitionNexus.lookup( lookupContext );
        }
        catch ( IOException ioe )
        {
            throw new LdapOtherException( ioe.getMessage(), ioe );
        }
        
        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 '{}'.  "
                + "Please update the admin password as soon as possible to prevent a possible security breach.", instanceId );
        }
    }


    /**
     * Adds test entries into the core.
     *
     * TODO this may no longer be needed when JNDI is not used for bootstrapping
     *
     * @throws LdapException if the creation of test entries fails.
     */
    private void createTestEntries() throws LdapException
    {
        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 LdapException, IOException
    {
        Partition system = getSystemPartition();

        // Add root context entry for system partition
        Dn systemSuffixDn = getDnFactory().create( ServerDNConstants.SYSTEM_DN );
        CoreSession admin = getAdminSession();

        HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( admin, systemSuffixDn );
        Partition partition = getPartitionNexus().getPartition( systemSuffixDn );
        hasEntryContext.setPartition( partition );
        
        try ( PartitionTxn partitionTxn = partition.beginReadTransaction() )
        {
            hasEntryContext.setTransaction( partitionTxn );
            
            if ( !system.hasEntry( hasEntryContext ) )
            {
                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( admin, systemEntry );
                addOperationContext.setPartition( partition );
                
                PartitionTxn writeTxn = null;
                
                try
                {
                    writeTxn = partition.beginWriteTransaction();
                    addOperationContext.setTransaction( writeTxn );
                    system.add( addOperationContext );
                    
                    writeTxn.commit();
                }
                catch ( LdapException le )
                {
                    try
                    {
                        writeTxn.abort();
                    }
                    catch ( IOException ioe )
                    {
                        throw new LdapOtherException( ioe.getMessage(), ioe );
                    }
                    
                    throw le;
                }
                catch ( IOException ioe )
                {
                    try
                    {
                        writeTxn.abort();
                    }
                    catch ( IOException ioe2 )
                    {
                        throw new LdapOtherException( ioe2.getMessage(), ioe2 );
                    }
                    
                    throw new LdapOtherException( ioe.getMessage(), ioe );
                }
            }
        }
    }


    /**
     * Kicks off the initialization of the entire system.
     *
     * @throws LdapException if there are problems along the way
     */
    private void initialize() throws LdapException
    {
        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<>();
        collectiveAttributeAPCache = new DnNode<>();
        subschemaAPCache = new DnNode<>();
        triggerExecutionAPCache = new DnNode<>();

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

        // triggers partition to load schema fully from schema partition
        schemaPartition.setCacheService( cacheService );
        schemaPartition.initialize();
        partitions.add( schemaPartition );
        systemPartition.setCacheService( cacheService );
        
        if ( !systemPartition.getSuffixDn().isSchemaAware() )
        {
            systemPartition.setSuffixDn( new Dn( schemaManager, systemPartition.getSuffixDn() ) );
        }

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

        try
        {
            initializeSystemPartition();
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }

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

        try
        {
            firstStart = createBootstrapEntries();
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }

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

            return new DefaultEntry( schemaManager, entry );
        }
        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 )
    {
        return interceptorNames.get( interceptorName );
    }


    /**
     * {@inheritDoc}
     */
    public void addFirst( Interceptor interceptor ) throws LdapException
    {
        addInterceptor( interceptor, 0 );
    }


    /**
     * {@inheritDoc}
     */
    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;
    }

}