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


import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.util.*;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.Control;

import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.partition.PartitionNexus;
import org.apache.directory.server.core.security.CoreKeyStoreSpi;
import org.apache.directory.server.ldap.handlers.AbandonHandler;
import org.apache.directory.server.ldap.handlers.AddHandler;
import org.apache.directory.server.ldap.handlers.BindHandler;
import org.apache.directory.server.ldap.handlers.CompareHandler;
import org.apache.directory.server.ldap.handlers.DefaultAbandonHandler;
import org.apache.directory.server.ldap.handlers.DefaultAddHandler;
import org.apache.directory.server.ldap.handlers.DefaultBindHandler;
import org.apache.directory.server.ldap.handlers.DefaultCompareHandler;
import org.apache.directory.server.ldap.handlers.DefaultDeleteHandler;
import org.apache.directory.server.ldap.handlers.DefaultExtendedHandler;
import org.apache.directory.server.ldap.handlers.DefaultModifyDnHandler;
import org.apache.directory.server.ldap.handlers.DefaultModifyHandler;
import org.apache.directory.server.ldap.handlers.DefaultSearchHandler;
import org.apache.directory.server.ldap.handlers.DefaultUnbindHandler;
import org.apache.directory.server.ldap.handlers.DeleteHandler;
import org.apache.directory.server.ldap.handlers.ExtendedHandler;
import org.apache.directory.server.ldap.handlers.ModifyDnHandler;
import org.apache.directory.server.ldap.handlers.ModifyHandler;
import org.apache.directory.server.ldap.handlers.SearchHandler;
import org.apache.directory.server.ldap.handlers.UnbindHandler;
import org.apache.directory.server.ldap.handlers.bind.*;
import org.apache.directory.server.ldap.handlers.ssl.LdapsInitializer;
import org.apache.directory.server.protocol.shared.DirectoryBackedService;
import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
import org.apache.directory.shared.asn1.codec.Asn1CodecDecoder;
import org.apache.directory.shared.asn1.codec.Asn1CodecEncoder;
import org.apache.directory.shared.ldap.constants.SaslQoP;
import org.apache.directory.shared.ldap.exception.LdapConfigurationException;
import org.apache.directory.shared.ldap.message.AbandonRequest;
import org.apache.directory.shared.ldap.message.AddRequest;
import org.apache.directory.shared.ldap.message.BindRequest;
import org.apache.directory.shared.ldap.message.CascadeControl;
import org.apache.directory.shared.ldap.message.CompareRequest;
import org.apache.directory.shared.ldap.message.DeleteRequest;
import org.apache.directory.shared.ldap.message.EntryChangeControl;
import org.apache.directory.shared.ldap.message.ExtendedRequest;
import org.apache.directory.shared.ldap.message.ExtendedRequestImpl;
import org.apache.directory.shared.ldap.message.ManageDsaITControl;
import org.apache.directory.shared.ldap.message.MessageDecoder;
import org.apache.directory.shared.ldap.message.MessageEncoder;
import org.apache.directory.shared.ldap.message.ModifyDnRequest;
import org.apache.directory.shared.ldap.message.ModifyRequest;
import org.apache.directory.shared.ldap.message.MutableControl;
import org.apache.directory.shared.ldap.message.PersistentSearchControl;
import org.apache.directory.shared.ldap.message.Request;
import org.apache.directory.shared.ldap.message.ResponseCarryingMessageException;
import org.apache.directory.shared.ldap.message.ResultCodeEnum;
import org.apache.directory.shared.ldap.message.ResultResponse;
import org.apache.directory.shared.ldap.message.ResultResponseRequest;
import org.apache.directory.shared.ldap.message.SearchRequest;
import org.apache.directory.shared.ldap.message.SubentriesControl;
import org.apache.directory.shared.ldap.message.UnbindRequest;
import org.apache.directory.shared.ldap.message.extended.NoticeOfDisconnect;
import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.mina.common.DefaultIoFilterChainBuilder;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoFilterChainBuilder;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.ThreadModel;
import org.apache.mina.common.WriteFuture;
import org.apache.mina.filter.SSLFilter;
import org.apache.mina.filter.codec.ProtocolCodecFactory;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.handler.demux.DemuxingIoHandler;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
import org.apache.mina.util.SessionLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An LDAP protocol provider implementation which dynamically associates
 * handlers.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$
 * @org.apache.xbean.XBean
 */
public class LdapServer extends DirectoryBackedService
{
    @SuppressWarnings( { "UnusedDeclaration" } )
    private static final long serialVersionUID = 3757127143811666817L;

    /** logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( LdapServer.class.getName() );

    /** The default maximum size limit. */
    private static final int MAX_SIZE_LIMIT_DEFAULT = 100;

    /** The default maximum time limit. */
    private static final int MAX_TIME_LIMIT_DEFAULT = 10000;

    /**
     * The default service pid.
     */
    private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ldap";

    /**
     * The default service name.
     */
    private static final String SERVICE_NAME_DEFAULT = "ApacheDS LDAP Service";

    /** The default IP port. */
    private static final int IP_PORT_DEFAULT = 389;

    /** the constant service name of this ldap protocol provider **/
    public static final String SERVICE_NAME = "ldap";

    /** a set of supported controls */
    private Set<String> supportedControls;

    /** The maximum size limit. */
    private int maxSizeLimit = MAX_SIZE_LIMIT_DEFAULT; // set to default value

    /** The maximum time limit. */
    private int maxTimeLimit = MAX_TIME_LIMIT_DEFAULT; // set to default value (milliseconds)

    /** Whether LDAPS is enabled. */
    private boolean enableLdaps;

    /** Whether to allow anonymous access: allowed by default */
    private boolean allowAnonymousAccess = true;
    
    /** 
     * Whether or not confidentiality (TLS secured connection) is required: 
     * disabled by default. 
     */
    private boolean confidentialityRequired;

    /** The extended operation handlers. */
    private final Collection<ExtendedOperationHandler> extendedOperationHandlers =
        new ArrayList<ExtendedOperationHandler>();

    /** The supported authentication mechanisms. */
    private Map<String, MechanismHandler> saslMechanismHandlers =
        new HashMap<String, MechanismHandler>();

    /** The name of this host, validated during SASL negotiation. */
    private String saslHost = "ldap.example.com";

    /** The service principal, used by GSSAPI. */
    private String saslPrincipal = "ldap/ldap.example.com@EXAMPLE.COM";

    /** The quality of protection (QoP), used by DIGEST-MD5 and GSSAPI. */
    private Set<String> saslQop;
    private String      saslQopString;

    /** The list of realms serviced by this host. */
    private List<String> saslRealms;

    private AbandonHandler abandonHandler;
    private AddHandler addHandler;
    private BindHandler bindHandler;
    private CompareHandler compareHandler;
    private DeleteHandler deleteHandler;
    private ExtendedHandler extendedHandler;
    private ModifyHandler modifyHandler;
    private ModifyDnHandler modifyDnHandler;
    private SearchHandler searchHandler;
    private UnbindHandler unbindHandler;


    private SessionRegistry registry;

    /** the underlying provider codec factory */
    private ProtocolCodecFactory codecFactory;

    /** the MINA protocol handler */
    private final LdapProtocolHandler handler = new LdapProtocolHandler();

    /** tracks state of the server */
    private boolean started;


    /**
     * Creates an LDAP protocol provider.
     */
    public LdapServer()
    {
        super.setIpPort( IP_PORT_DEFAULT );
        super.setEnabled( true );
        super.setServiceId( SERVICE_PID_DEFAULT );
        super.setServiceName( SERVICE_NAME_DEFAULT );

        saslQop = new HashSet<String>();
        saslQop.add( SaslQoP.QOP_AUTH );
        saslQop.add( SaslQoP.QOP_AUTH_INT );
        saslQop.add( SaslQoP.QOP_AUTH_CONF );
        saslQopString = SaslQoP.QOP_AUTH + ',' + SaslQoP.QOP_AUTH_INT + ',' + SaslQoP.QOP_AUTH_CONF;

        saslRealms = new ArrayList<String>();
        saslRealms.add( "example.com" );

        this.supportedControls = new HashSet<String>();
        this.supportedControls.add( PersistentSearchControl.CONTROL_OID );
        this.supportedControls.add( EntryChangeControl.CONTROL_OID );
        this.supportedControls.add( SubentriesControl.CONTROL_OID );
        this.supportedControls.add( ManageDsaITControl.CONTROL_OID );
        this.supportedControls.add( CascadeControl.CONTROL_OID );
    }


    /**
     * Install the LDAP request handlers.
     */
    private void installDefaultHandlers()
    {
        if ( getAbandonHandler() == null )
        {
            setAbandonHandler( new DefaultAbandonHandler() );
        }
        
        if ( getAddHandler() == null )
        {
            setAddHandler( new DefaultAddHandler() );
        }
        
        if ( getBindHandler() == null )
        {
            DefaultBindHandler handler = new DefaultBindHandler();
            handler.setSessionRegistry( registry );
            handler.setSaslMechanismHandlers( saslMechanismHandlers );
            setBindHandler( handler );
        }
        
        if ( getCompareHandler() == null )
        {
            setCompareHandler( new DefaultCompareHandler() );
        }
        
        if ( getDeleteHandler() == null )
        {
            setDeleteHandler( new DefaultDeleteHandler() );
        }
        
        if ( getExtendedHandler() == null )
        {
            setExtendedHandler( new DefaultExtendedHandler() );
        }
        
        if ( getModifyHandler() == null )
        {
            setModifyHandler( new DefaultModifyHandler() );
        }
        
        if ( getModifyDnHandler() == null )
        {
            setModifyDnHandler( new DefaultModifyDnHandler() );
        }
        
        if ( getSearchHandler() == null )
        {
            setSearchHandler( new DefaultSearchHandler() );
        }
        
        if ( getUnbindHandler() == null )
        {
            setUnbindHandler( new DefaultUnbindHandler() );
        }
    }


    /**
     * @throws IOException if we cannot bind to the specified port
     * @throws NamingException if the LDAP server cannot be started
     */
    public void start() throws NamingException, IOException
    {
        if ( ! isEnabled() )
        {
            return;
        }

        IoFilterChainBuilder chain;
        
        if ( isEnableLdaps() )
        {
            Provider provider = Security.getProvider( "SUN" );
            LOG.debug( "provider = {}", provider );
            CoreKeyStoreSpi coreKeyStoreSpi = new CoreKeyStoreSpi( getDirectoryService() );
            KeyStore keyStore = new KeyStore( coreKeyStoreSpi, provider, "JKS" ) {};
            try
            {
                keyStore.load( null, null );
            }
            catch ( Exception e )
            {
                // nothing really happens with this keystore
            }
            chain = LdapsInitializer.init( keyStore );
        }
        else
        {
            chain = new DefaultIoFilterChainBuilder();
        }

        /*
         * The serveur is now initialized, we can
         * install the default requests handlers, which need 
         * access to the DirectoryServer instance.
         */ 
        installDefaultHandlers();      

        startLDAP0( getIpPort(), chain );
        
        started = true;
    }


    public void stop()
    {
        try
        {
            // we should unbind the service before we begin sending the notice
            // of disconnect so new connections are not formed while we process
            List<WriteFuture> writeFutures = new ArrayList<WriteFuture>();

            // If the socket has already been unbound as with a successful
            // GracefulShutdownRequest then this will complain that the service
            // is not bound - this is ok because the GracefulShutdown has already
            // sent notices to to the existing active sessions
            List<IoSession> sessions;

            try
            {
                sessions = new ArrayList<IoSession>(
                        getSocketAcceptor().getManagedSessions( new InetSocketAddress( getIpPort() ) ) );
            }
            catch ( IllegalArgumentException e )
            {
                LOG.warn( "Seems like the LDAP service (" + getIpPort() + ") has already been unbound." );
                return;
            }

            getSocketAcceptor().unbind( new InetSocketAddress( getIpPort() ) );

            if ( LOG.isInfoEnabled() )
            {
                LOG.info( "Unbind of an LDAP service (" + getIpPort() + ") is complete." );
                LOG.info( "Sending notice of disconnect to existing clients sessions." );
            }

            // Send Notification of Disconnection messages to all connected clients.
            if ( sessions != null )
            {
                for ( IoSession session:sessions )
                {
                    writeFutures.add( session.write( NoticeOfDisconnect.UNAVAILABLE ) );
                }
            }

            // And close the connections when the NoDs are sent.
            Iterator<IoSession> sessionIt = sessions.iterator();

            for ( WriteFuture future:writeFutures )
            {
                future.join( 1000 );
                sessionIt.next().close();
            }
        }
        catch ( Exception e )
        {
            LOG.warn( "Failed to sent NoD.", e );
        }
    }


    private void startLDAP0( int port, IoFilterChainBuilder chainBuilder )
        throws NamingException
    {
        PartitionNexus nexus = getDirectoryService().getPartitionNexus();

        for ( ExtendedOperationHandler h : extendedOperationHandlers )
        {
            extendedHandler.addHandler( h );
            LOG.info( "Added Extended Request Handler: " + h.getOid() );
            h.setLdapProvider( this );
            nexus.registerSupportedExtensions( h.getExtensionOids() );
        }

        nexus.registerSupportedSaslMechanisms( saslMechanismHandlers.keySet() );

        try
        {
            SocketAcceptorConfig acceptorCfg = new SocketAcceptorConfig();

            // Disable the disconnection of the clients on unbind
            acceptorCfg.setDisconnectOnUnbind( false );
            acceptorCfg.setReuseAddress( true );
            acceptorCfg.setFilterChainBuilder( chainBuilder );
            acceptorCfg.setThreadModel( ThreadModel.MANUAL );

            acceptorCfg.getSessionConfig().setTcpNoDelay( true );

            getSocketAcceptor().bind( new InetSocketAddress( port ), getHandler(), acceptorCfg );
            started = true;

            if ( LOG.isInfoEnabled() )
            {
                LOG.info( "Successful bind of an LDAP Service (" + port + ") is complete." );
            }
        }
        catch ( IOException e )
        {
            String msg = "Failed to bind an LDAP service (" + port + ") to the service registry.";
            LdapConfigurationException lce = new LdapConfigurationException( msg );
            lce.setRootCause( e );
            LOG.error( msg, e );
            throw lce;
        }
    }


    public String getName()
    {
        return SERVICE_NAME;
    }


    public ProtocolCodecFactory getCodecFactory()
    {
        return codecFactory;
    }


    public IoHandler getHandler()
    {
        return handler;
    }


    // ------------------------------------------------------------------------
    // Configuration Methods
    // ------------------------------------------------------------------------


    /**
     * Registeres the specified {@link ExtendedOperationHandler} to this
     * protocol provider to provide a specific LDAP extended operation.
     *
     * @param eoh an extended operation handler
     * @throws NamingException on failure to add the handler
     */
    public void addExtendedOperationHandler( ExtendedOperationHandler eoh ) throws NamingException
    {
        if ( started )
        {
            extendedHandler.addHandler( eoh );
            eoh.setLdapProvider( this );
            PartitionNexus nexus = getDirectoryService().getPartitionNexus();
            nexus.registerSupportedExtensions( eoh.getExtensionOids() );
        }
        else
        {
            extendedOperationHandlers.add( eoh );
        }
    }


    /**
     * Deregisteres an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
     * from this protocol provider.
     *
     * @param oid the numeric identifier for the extended operation associated with
     * the handler to remove
     */
    public void removeExtendedOperationHandler( String oid )
    {
        if ( started )
        {
            extendedHandler.removeHandler( oid );

            // need to do something like this to make this work right
            //            PartitionNexus nexus = getDirectoryService().getPartitionNexus();
            //            nexus.unregisterSupportedExtensions( eoh.getExtensionOids() );
        }
        else
        {
            ExtendedOperationHandler handler = null;
            for ( ExtendedOperationHandler h : extendedOperationHandlers )
            {
                if ( h.getOid().equals( oid ) )
                {
                    handler = h;
                    break;
                }
            }
            extendedOperationHandlers.remove( handler );
        }
    }


    /**
     * Returns an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
     * which is registered to this protocol provider.
     *
     * @param oid the oid of the extended request of associated with the extended
     * request handler
     * @return the exnteded operation handler
     */
    public ExtendedOperationHandler getExtendedOperationHandler( String oid )
    {
        if ( started )
        {
            return extendedHandler.getHandler( oid );
        }
        else
        {
            for ( ExtendedOperationHandler h : extendedOperationHandlers )
            {
                if ( h.getOid().equals( oid ) )
                {
                    return h;
                }
            }
        }

        return null;
    }


    /**
     * Returns a {@link Map} of all registered OID-{@link ExtendedOperationHandler}
     * pairs.
     *
     * @return map of all extended operation handlers
     */
    public Map<String,ExtendedOperationHandler> getExtendedOperationHandlerMap()
    {
        return extendedHandler.getHandlerMap();
    }


    /**
     * Returns <tt>true</tt> if LDAPS is enabled.
     *
     * @return True if LDAPS is enabled.
     */
    public boolean isEnableLdaps()
    {
        return enableLdaps;
    }


    /**
     * Sets if LDAPS is enabled or not.
     *
     * @param enableLdaps Whether LDAPS is enabled.
     */
    public void setEnableLdaps( boolean enableLdaps )
    {
        this.enableLdaps = enableLdaps;
    }


    /**
     * Returns <code>true</code> if anonymous access is allowed.
     *
     * @return True if anonymous access is allowed.
     */
    public boolean isAllowAnonymousAccess()
    {
        return allowAnonymousAccess;
    }


    /**
     * Sets whether to allow anonymous access or not.
     *
     * @param enableAnonymousAccess Set <code>true</code> to allow anonymous access.
     */
    public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
    {
        this.allowAnonymousAccess = enableAnonymousAccess;
    }


    /**
     * Sets the maximum size limit in number of entries to return for search.
     *
     * @param maxSizeLimit the maximum number of entries to return for search
     */
    public void setMaxSizeLimit( int maxSizeLimit )
    {
        this.maxSizeLimit = maxSizeLimit;
    }


    /**
     * Returns the maximum size limit in number of entries to return for search.
     *
     * @return The maximum size limit.
     */
    public int getMaxSizeLimit()
    {
        return maxSizeLimit;
    }


    /**
     * Sets the maximum time limit in miliseconds to conduct a search.
     *
     * @param maxTimeLimit the maximum length of time in milliseconds for search
     */
    public void setMaxTimeLimit( int maxTimeLimit )
    {
        this.maxTimeLimit = maxTimeLimit;
    }


    /**
     * Returns the maximum time limit in milliseonds to conduct a search.
     *
     * @return The maximum time limit in milliseconds for search
     */
    public int getMaxTimeLimit()
    {
        return maxTimeLimit;
    }


    /**
     * Gets the {@link ExtendedOperationHandler}s.
     *
     * @return A collection of {@link ExtendedOperationHandler}s.
     */
    public Collection<ExtendedOperationHandler> getExtendedOperationHandlers()
    {
        return new ArrayList<ExtendedOperationHandler>( extendedOperationHandlers );
    }


    /**
     * Sets the {@link ExtendedOperationHandler}s.
     *
     * @org.apache.xbean.Property nestedType="org.apache.directory.server.ldap.ExtendedOperationHandler"
     *
     * @param handlers A collection of {@link ExtendedOperationHandler}s.
     */
    public void setExtendedOperationHandlers( Collection<ExtendedOperationHandler> handlers )
    {
        this.extendedOperationHandlers.clear();
        this.extendedOperationHandlers.addAll( handlers );
    }


    /**
     * Returns the FQDN of this SASL host, validated during SASL negotiation.
     *
     * @return The FQDN of this SASL host, validated during SASL negotiation.
     */
    public String getSaslHost()
    {
        return saslHost;
    }


    /**
     * Sets the FQDN of this SASL host, validated during SASL negotiation.
     *
     * @param saslHost The FQDN of this SASL host, validated during SASL negotiation.
     */
    public void setSaslHost( String saslHost )
    {
        this.saslHost = saslHost;
    }


    /**
     * Returns the Kerberos principal name for this LDAP service, used by GSSAPI.
     *
     * @return The Kerberos principal name for this LDAP service, used by GSSAPI.
     */
    public String getSaslPrincipal()
    {
        return saslPrincipal;
    }


    /**
     * Sets the Kerberos principal name for this LDAP service, used by GSSAPI.
     *
     * @param saslPrincipal The Kerberos principal name for this LDAP service, used by GSSAPI.
     */
    public void setSaslPrincipal( String saslPrincipal )
    {
        this.saslPrincipal = saslPrincipal;
    }


    /**
     * Returns the quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     *
     * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     */
    public String getSaslQopString()
    {
        return saslQopString;
    }


    /**
     * Returns the Set of quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     *
     * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     */
    public Set<String> getSaslQop()
    {
        return saslQop;
    }


    /**
     * Sets the desired quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     * 
     * We build a string from this list, where QoP are comma delimited 
     *
     * @org.apache.xbean.Property nestedType="java.lang.String"
     *
     * @param saslQop The desired quality-of-protection, used by DIGEST-MD5 and GSSAPI.
     */
    public void setSaslQop( Set<String> saslQop )
    {
        StringBuilder qopList = new StringBuilder();
        boolean isFirst = true;

        for ( String qop:saslQop )
        {
            if ( isFirst )
            {
                isFirst = false;
            }
            else
            {
                qopList.append( ',' );
            }
            
            qopList.append( qop );
        }

        this.saslQopString = qopList.toString();
        this.saslQop = saslQop;
    }


    /**
     * Returns the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
     *
     * @return The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
     */
    public List<String> getSaslRealms()
    {
        return saslRealms;
    }


    /**
     * Sets the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
     *
     * @org.apache.xbean.Property nestedType="java.lang.String"
     *
     * @param saslRealms The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
     */
    public void setSaslRealms( List<String> saslRealms )
    {
        this.saslRealms = saslRealms;
    }


    /**
     * @org.apache.xbean.Map flat="true" dups="replace" keyName="mech-name"
     */
    public Map<String, MechanismHandler> getSaslMechanismHandlers()
    {
        return saslMechanismHandlers;
    }

    public void setSaslMechanismHandlers( Map<String, MechanismHandler> saslMechanismHandlers )
    {
        this.saslMechanismHandlers = saslMechanismHandlers;
    }



    public MechanismHandler addSaslMechanismHandler( String mechanism, MechanismHandler handler )
    {
        return this.saslMechanismHandlers.put( mechanism, handler );
    }


    public MechanismHandler removeSaslMechanismHandler( String mechanism )
    {
        return this.saslMechanismHandlers.remove( mechanism );
    }


    public MechanismHandler getMechanismHandler( String mechanism )
    {
        return this.saslMechanismHandlers.get( mechanism );
    }


    public Set<String> getSupportedMechanisms()
    {
        return saslMechanismHandlers.keySet();
    }


    public void setDirectoryService( DirectoryService directoryService )
    {
        super.setDirectoryService( directoryService );
        this.codecFactory = new ProtocolCodecFactoryImpl( directoryService );
        Hashtable<String,Object> copy = new Hashtable<String,Object>();
        copy.put( Context.PROVIDER_URL, "" );
        copy.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.directory.server.core.jndi.CoreContextFactory" );
        copy.put( DirectoryService.JNDI_KEY, directoryService );
        this.registry = new SessionRegistry( this, copy );
    }


    public Set<String> getSupportedControls()
    {
        return supportedControls;
    }


    public void setSupportedControls( Set<String> supportedControls )
    {
        this.supportedControls = supportedControls;
    }


    public AbandonHandler getAbandonHandler()
    {
        return abandonHandler;
    }


    public void setAbandonHandler( AbandonHandler abandonHandler )
    {
        this.handler.removeMessageHandler( AbandonRequest.class );
        this.abandonHandler = abandonHandler;
        this.abandonHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( AbandonRequest.class, this.abandonHandler );
    }


    public AddHandler getAddHandler()
    {
        return addHandler;
    }


    public void setAddHandler( AddHandler addHandler )
    {
        this.handler.removeMessageHandler( AddRequest.class );
        this.addHandler = addHandler;
        this.addHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( AddRequest.class, this.addHandler );
    }


    public BindHandler getBindHandler()
    {
        return bindHandler;
    }


    public void setBindHandler( BindHandler bindHandler )
    {
        this.handler.removeMessageHandler( BindRequest.class );
        this.bindHandler = bindHandler;
        this.bindHandler.setProtocolProvider( this );
        this.bindHandler.setDirectoryService( getDirectoryService() );
        //noinspection unchecked
        this.handler.addMessageHandler( BindRequest.class, this.bindHandler );
    }


    public CompareHandler getCompareHandler()
    {
        return compareHandler;
    }


    public void setCompareHandler( CompareHandler compareHandler )
    {
        this.handler.removeMessageHandler( CompareRequest.class );
        this.compareHandler = compareHandler;
        this.compareHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( CompareRequest.class, this.compareHandler );
    }


    public DeleteHandler getDeleteHandler()
    {
        return deleteHandler;
    }


    public void setDeleteHandler( DeleteHandler deleteHandler )
    {
        this.handler.removeMessageHandler( DeleteRequest.class );
        this.deleteHandler = deleteHandler;
        this.deleteHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( DeleteRequest.class, this.deleteHandler );
    }


    public ExtendedHandler getExtendedHandler()
    {
        return extendedHandler;
    }


    public void setExtendedHandler( ExtendedHandler extendedHandler )
    {
        this.handler.removeMessageHandler( ExtendedRequest.class );
        this.extendedHandler = extendedHandler;
        this.extendedHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( ExtendedRequest.class, this.extendedHandler );
    }


    public ModifyHandler getModifyHandler()
    {
        return modifyHandler;
    }


    public void setModifyHandler( ModifyHandler modifyHandler )
    {
        this.handler.removeMessageHandler( ModifyRequest.class );
        this.modifyHandler = modifyHandler;
        this.modifyHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( ModifyRequest.class, this.modifyHandler );
    }


    public ModifyDnHandler getModifyDnHandler()
    {
        return modifyDnHandler;
    }


    public void setModifyDnHandler( ModifyDnHandler modifyDnHandler )
    {
        this.handler.removeMessageHandler( ModifyDnRequest.class );
        this.modifyDnHandler = modifyDnHandler;
        this.modifyDnHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( ModifyDnRequest.class, this.modifyDnHandler );
    }


    public SearchHandler getSearchHandler()
    {
        return searchHandler;
    }


    public void setSearchHandler( SearchHandler searchHandler )
    {
        this.handler.removeMessageHandler( SearchRequest.class );
        this.searchHandler = searchHandler;
        this.searchHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( SearchRequest.class, this.searchHandler );
    }


    public UnbindHandler getUnbindHandler()
    {
        return unbindHandler;
    }


    public void setUnbindHandler( UnbindHandler unbindHandler )
    {
        this.handler.removeMessageHandler( UnbindRequest.class );
        this.unbindHandler = unbindHandler;
        this.unbindHandler.setProtocolProvider( this );
        //noinspection unchecked
        this.handler.addMessageHandler( UnbindRequest.class, this.unbindHandler );
    }


    public SessionRegistry getRegistry()
    {
        return registry;
    }


    public boolean isStarted()
    {
        return started;
    }


    public void setStarted( boolean started )
    {
        this.started = started;
    }


    /**
     * Sets the mode for this LdapServer to accept requests with or without a
     * TLS secured connection via either StartTLS extended operations or using
     * LDAPS.
     * 
     * @param confidentialityRequired true to require confidentiality
     */
    public void setConfidentialityRequired( boolean confidentialityRequired ) 
    {
		this.confidentialityRequired = confidentialityRequired;
	}


    /**
     * Gets whether or not TLS secured connections are required to perform 
     * operations on this LdapServer.
     * 
     * @return true if TLS secured connections are required, false otherwise
     */
	public boolean isConfidentialityRequired() 
	{
		return confidentialityRequired;
	}


	/**
     * A snickers based BER Decoder factory.
     */
    private static final class ProtocolCodecFactoryImpl implements ProtocolCodecFactory
    {
        final DirectoryService directoryService;


        public ProtocolCodecFactoryImpl( DirectoryService directoryService )
        {
            this.directoryService = directoryService;
        }


        public ProtocolEncoder getEncoder()
        {
            return new Asn1CodecEncoder( new MessageEncoder() );
        }


        public ProtocolDecoder getDecoder()
        {
            return new Asn1CodecDecoder( new MessageDecoder( new BinaryAttributeDetector()
            {
                public boolean isBinary( String id )
                {
                    AttributeTypeRegistry attrRegistry = directoryService.getRegistries().getAttributeTypeRegistry();
                    try
                    {
                        AttributeType type = attrRegistry.lookup( id );
                        return ! type.getSyntax().isHumanReadable();
                    }
                    catch ( NamingException e )
                    {
                        return false;
                    }
                }
            }) );
        }
    }

    private class LdapProtocolHandler extends DemuxingIoHandler
    {
        public void sessionCreated( IoSession session ) throws Exception
        {
            session.setAttribute( LdapServer.class.toString(), LdapServer.this );
            IoFilterChain filters = session.getFilterChain();
            filters.addLast( "codec", new ProtocolCodecFilter( codecFactory ) );
        }


        public void sessionClosed( IoSession session )
        {
            registry.remove( session );
        }


        public void messageReceived( IoSession session, Object message ) throws Exception
        {
            // Translate SSLFilter messages into LDAP extended request
            // defined in RFC #2830, 'Lightweight Directory Access Protocol (v3):
            // Extension for Transport Layer Security'.
            // 
            // The RFC specifies the payload should be empty, but we use
            // it to notify the TLS state changes.  This hack should be
            // OK from the viewpointd of security because StartTLS
            // handler should react to only SESSION_UNSECURED message
            // and degrade authentication level to 'anonymous' as specified
            // in the RFC, and this is no threat.

            if ( message == SSLFilter.SESSION_SECURED )
            {
                ExtendedRequest req = new ExtendedRequestImpl( 0 );
                req.setOid( "1.3.6.1.4.1.1466.20037" );
                req.setPayload( "SECURED".getBytes( "ISO-8859-1" ) );
                message = req;
            }
            else if ( message == SSLFilter.SESSION_UNSECURED )
            {
                ExtendedRequest req = new ExtendedRequestImpl( 0 );
                req.setOid( "1.3.6.1.4.1.1466.20037" );
                req.setPayload( "UNSECURED".getBytes( "ISO-8859-1" ) );
                message = req;
            }

            if ( ( ( Request ) message ).getControls().size() > 0 && message instanceof ResultResponseRequest )
            {
                ResultResponseRequest req = ( ResultResponseRequest ) message;
                for ( Control control1 : req.getControls().values() )
                {
                    MutableControl control = ( MutableControl ) control1;
                    if ( control.isCritical() && !supportedControls.contains( control.getID() ) )
                    {
                        ResultResponse resp = req.getResultResponse();
                        resp.getLdapResult().setErrorMessage( "Unsupport critical control: " + control.getID() );
                        resp.getLdapResult().setResultCode( ResultCodeEnum.UNAVAILABLE_CRITICAL_EXTENSION );
                        session.write( resp );
                        return;
                    }
                }
            }

            super.messageReceived( session, message );
        }


        public void exceptionCaught( IoSession session, Throwable cause )
        {
            if ( cause.getCause() instanceof ResponseCarryingMessageException )
            {
                ResponseCarryingMessageException rcme = ( ResponseCarryingMessageException ) cause.getCause();
                
                if ( rcme.getResponse() != null )
                {
                    session.write( rcme.getResponse() );
                    return;
                }
            }
            
            SessionLog.warn( session,
                "Unexpected exception forcing session to close: sending disconnect notice to client.", cause );
            
            session.write( NoticeOfDisconnect.PROTOCOLERROR );
            registry.remove( session );
            session.close();
        }
    }
}
