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


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
import org.apache.directory.api.ldap.model.cursor.SingletonCursor;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
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.ModificationOperation;
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.LdapNoSuchAttributeException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
import org.apache.directory.api.ldap.model.exception.LdapOperationErrorException;
import org.apache.directory.api.ldap.model.exception.LdapOtherException;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.filter.ObjectClassNode;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions;
import org.apache.directory.api.ldap.model.schema.UsageEnum;
import org.apache.directory.api.ldap.util.tree.DnNode;
import org.apache.directory.api.util.exception.MultiException;
import org.apache.directory.server.constants.ServerDNConstants;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.api.InterceptorEnum;
import org.apache.directory.server.core.api.entry.ClonedServerEntry;
import org.apache.directory.server.core.api.filtering.CursorList;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
import org.apache.directory.server.core.api.filtering.EntryFilteringCursorImpl;
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
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.ModifyOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
import org.apache.directory.server.core.api.partition.AbstractPartition;
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.PartitionReadTxn;
import org.apache.directory.server.core.api.partition.PartitionTxn;
import org.apache.directory.server.core.api.partition.PartitionWriteTxn;
import org.apache.directory.server.core.api.partition.Subordinates;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A root {@link Partition} that contains all other partitions, and
 * routes all operations to the child partition that matches to its base suffixes.
 * It also provides some extended operations such as accessing rootDSE and
 * listing base suffixes.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class DefaultPartitionNexus extends AbstractPartition implements PartitionNexus
{
    /** A logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( DefaultPartitionNexus.class );

    /** the fixed id: 'NEXUS' */
    private static final String NEXUS_ID = "NEXUS";

    /** Speedup for logs */
    private static final boolean IS_DEBUG = LOG.isDebugEnabled();

    /** the vendorName string proudly set to: Apache Software Foundation*/
    private static final String ASF = "Apache Software Foundation";

    /** the read only rootDSE attributes */
    private final Entry rootDse;

    /** The DirectoryService instance */
    private DirectoryService directoryService;

    /** the partitions keyed by normalized suffix strings */
    private Map<String, Partition> partitions = new HashMap<>();

    /** A structure to hold all the partitions */
    private DnNode<Partition> partitionLookupTree = new DnNode<>();

    private final List<Modification> mods = new ArrayList<>( 2 );

    /** The cn=schema Dn */
    private Dn subschemaSubentryDn;


    /**
     * Creates the root nexus singleton of the entire system.  The root DSE has
     * several attributes that are injected into it besides those that may
     * already exist.  As partitions are added to the system more namingContexts
     * attributes are added to the rootDSE.
     *
     * @see <a href="http://www.faqs.org/rfcs/rfc3045.html">Vendor Information</a>
     * @param rootDse the root entry for the DSA
     * @throws LdapException on failure to initialize
     */
    public DefaultPartitionNexus( Entry rootDse ) throws LdapException
    {
        id = NEXUS_ID;
        suffixDn = null;

        // setup that root DSE
        this.rootDse = rootDse;

        // Add the basic informations
        rootDse.put( SchemaConstants.SUBSCHEMA_SUBENTRY_AT, ServerDNConstants.CN_SCHEMA_DN );
        rootDse.put( SchemaConstants.SUPPORTED_LDAP_VERSION_AT, "3" );
        rootDse.put( SchemaConstants.SUPPORTED_FEATURES_AT, 
            SchemaConstants.FEATURE_ALL_OPERATIONAL_ATTRIBUTES,
            SchemaConstants.FEATURE_MODIFY_INCREMENT );
        rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, NoticeOfDisconnect.EXTENSION_OID );

        // Add the objectClasses
        rootDse.put( SchemaConstants.OBJECT_CLASS_AT, SchemaConstants.TOP_OC, SchemaConstants.EXTENSIBLE_OBJECT_OC );

        // Add the 'vendor' name and version infos
        rootDse.put( SchemaConstants.VENDOR_NAME_AT, ASF );

        Properties props = new Properties();

        try
        {
            props.load( getClass().getResourceAsStream( "version.properties" ) );
        }
        catch ( IOException e )
        {
            LOG.error( I18n.err( I18n.ERR_33 ) );
        }

        rootDse.put( SchemaConstants.VENDOR_VERSION_AT, props.getProperty( "apacheds.version", "UNKNOWN" ) );

        // The rootDSE uuid has been randomly created
        rootDse.put( SchemaConstants.ENTRY_UUID_AT, "f290425c-8272-4e62-8a67-92b06f38dbf5" );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void repair() throws LdapException
    {
        // Nothing to do
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void doRepair() throws LdapException
    {
        // Nothing to do
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected void doInit() throws LdapException
    {
        // NOTE: We ignore ContextPartitionConfiguration parameter here.
        if ( !initialized )
        {
            // Add the supported request controls
            Iterator<String> ctrlOidItr = directoryService.getLdapCodecService().registeredRequestControls();

            while ( ctrlOidItr.hasNext() )
            {
                rootDse.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
            }

            // Add the supported response controls
            ctrlOidItr = directoryService.getLdapCodecService().registeredResponseControls();

            while ( ctrlOidItr.hasNext() )
            {
                rootDse.add( SchemaConstants.SUPPORTED_CONTROL_AT, ctrlOidItr.next() );
            }

            schemaManager = directoryService.getSchemaManager();

            Value attr = rootDse.get( SchemaConstants.SUBSCHEMA_SUBENTRY_AT ).get();
            subschemaSubentryDn = directoryService.getDnFactory().create( attr.getString() );

            List<Partition> initializedPartitions = new ArrayList<>();

            initializedPartitions.add( 0, directoryService.getSystemPartition() );
            addContextPartition( directoryService.getSystemPartition() );

            try
            {
                for ( Partition partition : directoryService.getPartitions() )
                {
                    addContextPartition( partition );
                    initializedPartitions.add( partition );
                }

                createContextCsnModList();

                initialized = true;
            }
            finally
            {
                if ( !initialized )
                {
                    Iterator<Partition> i = initializedPartitions.iterator();

                    while ( i.hasNext() )
                    {
                        Partition partition = i.next();
                        i.remove();

                        try
                        {
                            partition.destroy( partition.beginReadTransaction() );
                        }
                        catch ( Exception e )
                        {
                            LOG.warn( "Failed to destroy a partition: " + partition.getSuffixDn(), e );
                        }
                        finally
                        {
                            unregister( partition );
                        }
                    }
                }
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    protected synchronized void doDestroy( PartitionTxn partitionTxn )
    {
        if ( !initialized )
        {
            return;
        }

        // make sure this loop is not fail fast so all backing stores can
        // have an attempt at closing down and synching their cached entries
        for ( String suffix : new HashSet<>( this.partitions.keySet() ) )
        {
            try
            {
                removeContextPartition( suffix );
            }
            catch ( Exception e )
            {
                LOG.warn( "Failed to destroy a partition: " + suffixDn, e );
            }
        }

        initialized = false;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setId( String id )
    {
        throw new UnsupportedOperationException( I18n.err( I18n.ERR_264 ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setSuffixDn( Dn suffix )
    {
        throw new UnsupportedOperationException();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void sync() throws LdapException
    {
        MultiException errors = null;

        for ( Partition partition : this.partitions.values() )
        {
            try
            {
                partition.saveContextCsn( partition.beginReadTransaction() );
                partition.sync();
            }
            catch ( Exception e )
            {
                LOG.warn( "Failed to flush partition data out.", e );

                if ( errors == null )
                {
                    //noinspection ThrowableInstanceNeverThrown
                    errors = new MultiException( I18n.err( I18n.ERR_265 ) );
                }

                // @todo really need to send this info to a monitor
                errors.addThrowable( e );
            }
        }

        if ( errors != null )
        {
            throw new LdapOtherException( errors.getMessage(), errors );
        }
    }


    // ------------------------------------------------------------------------
    // DirectoryPartition Interface Method Implementations
    // ------------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public void add( AddOperationContext addContext ) throws LdapException
    {
        Partition partition = addContext.getPartition();
        partition.add( addContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( CompareOperationContext compareContext ) throws LdapException
    {
        Attribute attr = compareContext.getOriginalEntry().get( compareContext.getAttributeType() );

        // complain if the attribute being compared does not exist in the entry
        if ( attr == null )
        {
            throw new LdapNoSuchAttributeException();
        }

        // see first if simple match without normalization succeeds
        if ( attr.contains( compareContext.getValue() ) )
        {
            return true;
        }

        // now must apply normalization to all values (attr and in request) to compare

        /*
         * Get ahold of the normalizer for the attribute and normalize the request
         * assertion value for comparisons with normalized attribute values.  Loop
         * through all values looking for a match.
         */
        Value reqVal = compareContext.getValue();

        for ( Value value : attr )
        {
            if ( value.equals( reqVal ) )
            {
                return true;
            }
        }

        return false;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry delete( DeleteOperationContext deleteContext ) throws LdapException
    {
        Partition partition = getPartition( deleteContext.getDn() );
        return partition.delete( deleteContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
    {
        Dn dn = hasEntryContext.getDn();

        if ( IS_DEBUG )
        {
            LOG.debug( "Check if Dn '{}' exists.", dn );
        }

        if ( dn.isRootDse() )
        {
            return true;
        }

        Partition partition = getPartition( dn );

        return partition.hasEntry( hasEntryContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
    {
        Dn dn = lookupContext.getDn();

        if ( dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
        {
            return new ClonedServerEntry( rootDse.clone() );
        }

        // This is for the case we do a lookup on the rootDSE
        if ( dn.isRootDse() )
        {
            return new ClonedServerEntry( rootDse );
        }

        Partition partition = getPartition( dn );
        Entry entry = partition.lookup( lookupContext );

        if ( entry == null )
        {
            throw new LdapNoSuchObjectException( "Attempt to lookup non-existant entry: "
                + dn.getName() );
        }

        return entry;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        // Special case : if we don't have any modification to apply, just return
        if ( modifyContext.getModItems().isEmpty() )
        {
            return;
        }

        Partition partition = getPartition( modifyContext.getDn() );

        partition.modify( modifyContext );

        if ( modifyContext.isPushToEvtInterceptor() )
        {
            directoryService.getInterceptor( InterceptorEnum.EVENT_INTERCEPTOR.getName() ).modify( modifyContext );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void move( MoveOperationContext moveContext ) throws LdapException
    {
        // Get the current partition
        Partition partition = getPartition( moveContext.getDn() );

        partition.move( moveContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
    {
        Partition partition = getPartition( moveAndRenameContext.getDn() );
        partition.moveAndRename( moveAndRenameContext );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( RenameOperationContext renameContext ) throws LdapException
    {
        Partition partition = getPartition( renameContext.getDn() );
        partition.rename( renameContext );
    }


    private EntryFilteringCursor searchRootDse( SearchOperationContext searchContext ) throws LdapException
    {
        Set<AttributeTypeOptions> ids = searchContext.getReturningAttributes();

        // -----------------------------------------------------------
        // If nothing is asked for then we just return the entry asis.
        // We let other mechanisms filter out operational attributes.
        // -----------------------------------------------------------
        if ( ( ids == null ) || ( ids.isEmpty() ) )
        {
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( getRootDse( null ) ), searchContext,
                directoryService.getSchemaManager() );
        }

        // -----------------------------------------------------------
        // Collect all the real attributes besides 1.1, +, and * and
        // note if we've seen these special attributes as well.
        // -----------------------------------------------------------

        Set<String> realIds = new HashSet<>();
        boolean allUserAttributes = searchContext.isAllUserAttributes();
        boolean allOperationalAttributes = searchContext.isAllOperationalAttributes();
        boolean noAttribute = searchContext.isNoAttributes();

        for ( AttributeTypeOptions id : ids )
        {
            try
            {
                realIds.add( id.getAttributeType().getOid() );
            }
            catch ( Exception e )
            {
                realIds.add( id.getAttributeType().getName() );
            }
        }

        // return nothing
        if ( noAttribute )
        {
            Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
                directoryService.getSchemaManager() );
        }

        // return everything
        if ( allUserAttributes && allOperationalAttributes )
        {
            Entry foundRootDse = getRootDse( null );
            return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( foundRootDse ), searchContext,
                directoryService.getSchemaManager() );
        }

        Entry serverEntry = new DefaultEntry( schemaManager, Dn.ROOT_DSE );
        GetRootDseOperationContext getRootDseContext = new GetRootDseOperationContext( searchContext.getSession() );
        getRootDseContext.setPartition( searchContext.getPartition() );
        getRootDseContext.setTransaction( searchContext.getTransaction() );

        Entry foundRootDse = getRootDse( getRootDseContext );

        for ( Attribute attribute : foundRootDse )
        {
            AttributeType type = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );

            if ( realIds.contains( type.getOid() )
                    || ( allUserAttributes && ( type.getUsage() == UsageEnum.USER_APPLICATIONS ) )
                    || ( allOperationalAttributes && ( type.getUsage() != UsageEnum.USER_APPLICATIONS ) ) )
            {
                serverEntry.put( attribute );
            }
        }

        return new EntryFilteringCursorImpl( new SingletonCursor<Entry>( serverEntry ), searchContext,
            directoryService.getSchemaManager() );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
    {
        Dn baseDn = searchContext.getDn();

        // TODO since we're handling the *, and + in the EntryFilteringCursor
        // we may not need this code: we need see if this is actually the
        // case and remove this code.
        if ( baseDn.size() == 0 )
        {
            return searchFromRoot( searchContext );
        }

        // Not sure we need this code...
        if ( !baseDn.isSchemaAware() )
        {
            searchContext.setDn( new Dn( schemaManager, baseDn ) );
        }

        // Normal case : do a search on the specific partition
        Partition backend = searchContext.getPartition();

        return backend.search( searchContext );
    }


    /**
     * Do a search from the root of the DIT. We have a few use cases to consider :
     * A) The scope is OBJECT
     * If the filter is (ObjectClass = *), then this is a RootDSE fetch, otherwise, we just
     * return nothing.
     * B) The scope is ONELEVEL
     * We just return the contextEntries of all the existing partitions
     * C) The scope is SUBLEVEL :
     * In this case, we have to do a search in each of the existing partition. We will get
     * back a list of cursors and we will wrap this list in the resulting EntryFilteringCursor.
     *
     * @param searchContext
     * @return
     * @throws LdapException
     */
    private EntryFilteringCursor searchFromRoot( SearchOperationContext searchContext )
        throws LdapException
    {
        ExprNode filter = searchContext.getFilter();

        // We are searching from the rootDSE. We have to distinguish three cases :
        // 1) The scope is OBJECT : we have to return the rootDSE entry, filtered
        // 2) The scope is ONELEVEL : we have to return all the Naming Contexts
        boolean isObjectScope = searchContext.getScope() == SearchScope.OBJECT;

        boolean isOnelevelScope = searchContext.getScope() == SearchScope.ONELEVEL;

        // test for (objectClass=*)
        boolean isSearchAll = false;

        // We have to be careful, as we may have a filter which is not a PresenceFilter
        if ( filter instanceof ObjectClassNode )
        {
            isSearchAll = true;
        }

        if ( isObjectScope )
        {
            if ( isSearchAll )
            {
                // if basedn is "", filter is "(objectclass=*)" and scope is object
                // then we have a request for the rootDSE
                return searchRootDse( searchContext );
            }
            else
            {
                // Nothing to return in this case
                return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
                    directoryService.getSchemaManager() );
            }
        }
        else if ( isOnelevelScope )
        {
            // Loop on all the partitions
            // We will look into all the partitions, thus we create a list of cursors.
            List<EntryFilteringCursor> cursors = new ArrayList<>();

            for ( Partition partition : partitions.values() )
            {
                Dn contextDn = partition.getSuffixDn();
                PartitionTxn partitionTxn = partition.beginReadTransaction();
                HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
                    searchContext.getSession(), contextDn );
                hasEntryContext.setPartition( partition );
                hasEntryContext.setTransaction( partitionTxn );
                searchContext.setPartition( partition );
                searchContext.setTransaction( partitionTxn );

                // search only if the context entry exists
                if ( partition.hasEntry( hasEntryContext ) )
                {
                    searchContext.setDn( contextDn );
                    searchContext.setScope( SearchScope.OBJECT );
                    cursors.add( partition.search( searchContext ) );
                }
            }

            return new CursorList( cursors, searchContext );
        }
        else
        {
            // This is a SUBLEVEL search. We will do multiple searches and wrap
            // a CursorList into the EntryFilteringCursor
            List<EntryFilteringCursor> cursors = new ArrayList<>();

            for ( Partition partition : partitions.values() )
            {
                PartitionTxn partitionTxn = partition.beginReadTransaction();
                Dn contextDn = partition.getSuffixDn();
                HasEntryOperationContext hasEntryContext = new HasEntryOperationContext(
                    searchContext.getSession(), contextDn );
                hasEntryContext.setPartition( partition );
                hasEntryContext.setTransaction( partitionTxn );
                searchContext.setPartition( partition );
                searchContext.setTransaction( partitionTxn );

                if ( partition.hasEntry( hasEntryContext ) )
                {
                    searchContext.setDn( contextDn );
                    EntryFilteringCursor cursor = partition.search( searchContext );

                    try
                    {
                        if ( cursor.first() )
                        {
                            cursor.beforeFirst();
                            cursors.add( cursor );
                        }
                    }
                    catch ( CursorException e )
                    {
                        // Do nothing
                    }
                }
            }

            // don't feed the above Cursors' list to a BaseEntryFilteringCursor it is skipping the naming context entry of each partition
            if ( cursors.isEmpty() )
            {
                // No candidate, return an emtpy cursor
                return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext,
                    directoryService.getSchemaManager() );
            }
            else
            {
                return new CursorList( cursors, searchContext );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void unbind( UnbindOperationContext unbindContext ) throws LdapException
    {
        Dn unbindContextDn = unbindContext.getDn();

        if ( !Dn.isNullOrEmpty( unbindContextDn ) )
        {
            Partition partition = getPartition( unbindContext.getDn() );
            partition.unbind( unbindContext );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry getRootDse( GetRootDseOperationContext getRootDseContext )
    {
        return rootDse.clone();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Value getRootDseValue( AttributeType attributeType )
    {
        return rootDse.get( attributeType ).get();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void addContextPartition( Partition partition ) throws LdapException
    {
        // Turn on default indices
        String key = partition.getSuffixDn().getNormName();

        if ( partitions.containsKey( key ) )
        {
            throw new LdapOtherException( I18n.err( I18n.ERR_263, key ) );
        }

        if ( !partition.isInitialized() )
        {
            partition.initialize();
        }

        synchronized ( partitionLookupTree )
        {
            Dn partitionSuffix = partition.getSuffixDn();

            if ( partitionSuffix == null )
            {
                throw new LdapOtherException( I18n.err( I18n.ERR_267, partition.getId() ) );
            }

            partitions.put( partitionSuffix.getNormName(), partition );
            partitionLookupTree.add( partition.getSuffixDn(), partition );

            Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

            if ( namingContexts == null )
            {
                namingContexts = new DefaultAttribute( schemaManager
                    .lookupAttributeTypeRegistry( SchemaConstants.NAMING_CONTEXTS_AT ), partitionSuffix.getName() );
                rootDse.put( namingContexts );
            }
            else
            {
                namingContexts.add( partitionSuffix.getName() );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void removeContextPartition( String partitionDn )
        throws LdapException
    {
        // Retrieve this partition from the aprtition's table
        Partition partition = partitions.get( partitionDn );

        if ( partition == null )
        {
            String msg = I18n.err( I18n.ERR_34, partitionDn );
            LOG.error( msg );
            throw new LdapNoSuchObjectException( msg );
        }

        String partitionSuffix = partition.getSuffixDn().getNormName();

        // Retrieve the namingContexts from the RootDSE : the partition
        // suffix must be present in those namingContexts
        Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

        if ( namingContexts != null )
        {
            Value foundNC = null;

            for ( Value namingContext : namingContexts )
            {
                String normalizedNC = new Dn( schemaManager, namingContext.getString() ).getNormName();

                if ( partitionSuffix.equals( normalizedNC ) )
                {
                    foundNC = namingContext;
                    break;
                }
            }

            if ( foundNC != null )
            {
                namingContexts.remove( foundNC );
            }
            else
            {
                String msg = I18n.err( I18n.ERR_35, partitionDn );
                LOG.error( msg );
                throw new LdapNoSuchObjectException( msg );
            }
        }

        // Update the partition tree
        synchronized ( partitionLookupTree )
        {
            partitionLookupTree.remove( partition.getSuffixDn() );
        }

        partitions.remove( partitionDn );

        try
        {
            partition.destroy( partition.beginReadTransaction() );
        }
        catch ( Exception e )
        {
            throw new LdapOperationErrorException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Partition getPartition( Dn dn ) throws LdapException
    {
        Partition parent;

        if ( dn == null )
        {
            dn = Dn.ROOT_DSE;
        }

        if ( !dn.isSchemaAware() )
        {
            dn = new Dn( schemaManager, dn );
        }

        if ( dn.isRootDse() || dn.getNormName().equals( subschemaSubentryDn.getNormName() ) )
        {
            return new RootPartition( schemaManager );
        }

        synchronized ( partitionLookupTree )
        {
            parent = partitionLookupTree.getElement( dn );
        }

        if ( parent == null )
        {
            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_268, dn ) );
        }
        else
        {
            return parent;
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Dn getSuffixDn( Dn dn ) throws LdapException
    {
        Partition partition = getPartition( dn );

        return partition.getSuffixDn();
    }


    /* (non-Javadoc)
     */
    @Override
    public Set<String> listSuffixes() throws LdapException
    {
        return Collections.unmodifiableSet( partitions.keySet() );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void registerSupportedExtensions( Set<String> extensionOids ) throws LdapException
    {
        Attribute supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );

        if ( supportedExtension == null )
        {
            rootDse.put( SchemaConstants.SUPPORTED_EXTENSION_AT, ( String ) null );
            supportedExtension = rootDse.get( SchemaConstants.SUPPORTED_EXTENSION_AT );
        }

        for ( String extensionOid : extensionOids )
        {
            supportedExtension.add( extensionOid );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void registerSupportedSaslMechanisms( Set<String> supportedSaslMechanisms ) throws LdapException
    {
        Attribute supportedSaslMechanismsAt;

        supportedSaslMechanismsAt = new DefaultAttribute(
            schemaManager.lookupAttributeTypeRegistry( SchemaConstants.SUPPORTED_SASL_MECHANISMS_AT ) );

        for ( String saslMechanism : supportedSaslMechanisms )
        {
            supportedSaslMechanismsAt.add( saslMechanism );
        }

        rootDse.add( supportedSaslMechanismsAt );
    }


    /**
     * Unregisters an ContextPartition with this BackendManager.  Called for each
     * registered Backend right befor it is to be stopped.  This prevents
     * protocol server requests from reaching the Backend and effectively puts
     * the ContextPartition's naming context offline.
     *
     * Operations against the naming context should result in an LDAP BUSY
     * result code in the returnValue if the naming context is not online.
     *
     * @param partition ContextPartition component to unregister with this
     * BackendNexus.
     * @throws Exception if there are problems unregistering the partition
     */
    private void unregister( Partition partition )
    {
        Attribute namingContexts = rootDse.get( SchemaConstants.NAMING_CONTEXTS_AT );

        if ( namingContexts != null )
        {
            namingContexts.remove( partition.getSuffixDn().getName() );
        }

        partitions.remove( partition.getSuffixDn().getName() );
    }


    /**
     * @return the directoryService
     */
    public DirectoryService getDirectoryService()
    {
        return directoryService;
    }


    /**
     * @param directoryService the directoryService to set
     */
    public void setDirectoryService( DirectoryService directoryService )
    {
        this.directoryService = directoryService;
    }


    private void createContextCsnModList() throws LdapException
    {
        Modification contextCsnMod = new DefaultModification();
        contextCsnMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
        DefaultAttribute contextCsnAt = new DefaultAttribute( schemaManager
            .lookupAttributeTypeRegistry( SchemaConstants.CONTEXT_CSN_AT ) );
        contextCsnMod.setAttribute( contextCsnAt );

        mods.add( contextCsnMod );

        Modification timeStampMod = new DefaultModification();
        timeStampMod.setOperation( ModificationOperation.REPLACE_ATTRIBUTE );
        DefaultAttribute timeStampAt = new DefaultAttribute( schemaManager
            .lookupAttributeTypeRegistry( SchemaConstants.MODIFY_TIMESTAMP_AT ) );
        timeStampMod.setAttribute( timeStampAt );

        mods.add( timeStampMod );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public String getContextCsn( PartitionTxn partitionTxn )
    {
        // nexus doesn't contain a contextCSN
        return null;
    }


    @Override
    public void saveContextCsn( PartitionTxn partitionTxn ) throws LdapException
    {
    }


    /**
     * Return the number of children and subordinates for a given entry
     *
     * @param partitionTxn The Partition transaction
     * @param entry The entry for which we want to find the subordinates
     * @return The Subordinate instance that contains the values.
     * @throws LdapException If we had an issue while processing the request
     */
    @Override
    public Subordinates getSubordinates( PartitionTxn partitionTxn, Entry entry ) throws LdapException
    {
        return new Subordinates();
    }


    @Override
    public PartitionReadTxn beginReadTransaction()
    {
        return new PartitionReadTxn();
    }


    @Override
    public PartitionWriteTxn beginWriteTransaction()
    {
        return new PartitionWriteTxn();
    }
}
