/*
 *  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
 *
 *    https://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.ldap.client.api;


import static org.apache.directory.api.ldap.model.message.ResultCodeEnum.processResponse;

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.UnresolvedAddressException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.security.auth.Subject;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;

import org.apache.directory.api.asn1.DecoderException;
import org.apache.directory.api.asn1.util.Oid;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector;
import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
import org.apache.directory.api.ldap.codec.api.LdapDecoder;
import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
import org.apache.directory.api.ldap.codec.api.MessageEncoderException;
import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
import org.apache.directory.api.ldap.extras.controls.ad.TreeDelete;
import org.apache.directory.api.ldap.extras.controls.ad.TreeDeleteImpl;
import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
import org.apache.directory.api.ldap.model.constants.LdapConstants;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.Cursor;
import org.apache.directory.api.ldap.model.cursor.CursorException;
import org.apache.directory.api.ldap.model.cursor.EntryCursor;
import org.apache.directory.api.ldap.model.cursor.SearchCursor;
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.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
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.exception.LdapTlsHandshakeException;
import org.apache.directory.api.ldap.model.message.AbandonRequest;
import org.apache.directory.api.ldap.model.message.AbandonRequestImpl;
import org.apache.directory.api.ldap.model.message.AddRequest;
import org.apache.directory.api.ldap.model.message.AddRequestImpl;
import org.apache.directory.api.ldap.model.message.AddResponse;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.message.BindRequest;
import org.apache.directory.api.ldap.model.message.BindRequestImpl;
import org.apache.directory.api.ldap.model.message.BindResponse;
import org.apache.directory.api.ldap.model.message.CompareRequest;
import org.apache.directory.api.ldap.model.message.CompareRequestImpl;
import org.apache.directory.api.ldap.model.message.CompareResponse;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.DeleteRequest;
import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
import org.apache.directory.api.ldap.model.message.DeleteResponse;
import org.apache.directory.api.ldap.model.message.ExtendedRequest;
import org.apache.directory.api.ldap.model.message.ExtendedResponse;
import org.apache.directory.api.ldap.model.message.IntermediateResponse;
import org.apache.directory.api.ldap.model.message.LdapResult;
import org.apache.directory.api.ldap.model.message.Message;
import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
import org.apache.directory.api.ldap.model.message.ModifyDnRequestImpl;
import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
import org.apache.directory.api.ldap.model.message.ModifyRequest;
import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
import org.apache.directory.api.ldap.model.message.ModifyResponse;
import org.apache.directory.api.ldap.model.message.OpaqueExtendedRequest;
import org.apache.directory.api.ldap.model.message.OpaqueExtendedResponse;
import org.apache.directory.api.ldap.model.message.Request;
import org.apache.directory.api.ldap.model.message.Response;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.message.SearchRequest;
import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
import org.apache.directory.api.ldap.model.message.SearchResultDone;
import org.apache.directory.api.ldap.model.message.SearchResultEntry;
import org.apache.directory.api.ldap.model.message.SearchResultReference;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.api.ldap.model.message.UnbindRequest;
import org.apache.directory.api.ldap.model.message.UnbindRequestImpl;
import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
import org.apache.directory.api.ldap.model.message.extended.AddNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.BindNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.CompareNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.DeleteNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.ExtendedNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.ModifyDnNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.ModifyNoDResponse;
import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
import org.apache.directory.api.ldap.model.message.extended.SearchNoDResponse;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.ObjectClass;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.model.schema.parsers.OpenLdapSchemaParser;
import org.apache.directory.api.ldap.model.schema.registries.Registries;
import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
import org.apache.directory.api.util.Network;
import org.apache.directory.api.util.StringConstants;
import org.apache.directory.api.util.Strings;
import org.apache.directory.ldap.client.api.callback.SaslCallbackHandler;
import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
import org.apache.directory.ldap.client.api.exception.LdapConnectionTimeOutException;
import org.apache.directory.ldap.client.api.future.AddFuture;
import org.apache.directory.ldap.client.api.future.BindFuture;
import org.apache.directory.ldap.client.api.future.CompareFuture;
import org.apache.directory.ldap.client.api.future.DeleteFuture;
import org.apache.directory.ldap.client.api.future.ExtendedFuture;
import org.apache.directory.ldap.client.api.future.HandshakeFuture;
import org.apache.directory.ldap.client.api.future.ModifyDnFuture;
import org.apache.directory.ldap.client.api.future.ModifyFuture;
import org.apache.directory.ldap.client.api.future.ResponseFuture;
import org.apache.directory.ldap.client.api.future.SearchFuture;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.FilterEvent;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolEncoderException;
import org.apache.mina.filter.ssl.SslEvent;
import org.apache.mina.filter.ssl.SslFilter;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * This class is the base for every operations sent or received to and
 * from a LDAP server.
 *
 * A connection instance is necessary to send requests to the server. The connection
 * is valid until either the client closes it, the server closes it or the
 * client does an unbind.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class LdapNetworkConnection extends AbstractLdapConnection implements LdapAsyncConnection
{
    /** logger for reporting errors that might not be handled properly upstream */
    private static final Logger LOG = LoggerFactory.getLogger( LdapNetworkConnection.class );

    /** The timeout used for response we are waiting for */
    private long timeout = LdapConnectionConfig.DEFAULT_TIMEOUT;

    /** configuration object for the connection */
    private LdapConnectionConfig config;
    
    /** The Socket configuration */
    private SocketSessionConfig socketSessionConfig;

    /** The connector open with the remote server */
    private IoConnector connector;

    /** A mutex used to avoid a double close of the connector */
    private ReentrantLock connectorMutex = new ReentrantLock();

    /**
     * The created session, created when we open a connection with
     * the Ldap server.
     */
    private IoSession ioSession;

    /** a map to hold the ResponseFutures for all operations */
    private Map<Integer, ResponseFuture<? extends Response>> futureMap = new ConcurrentHashMap<>();

    /** list of controls supported by the server */
    private List<String> supportedControls;

    /** The ROOT DSE entry */
    private Entry rootDse;

    /** A flag indicating that the BindRequest has been issued and successfully authenticated the user */
    private AtomicBoolean authenticated = new AtomicBoolean( false );

    /** a list of listeners interested in getting notified when the
     *  connection's session gets closed cause of network issues
     */
    private List<ConnectionClosedEventListener> conCloseListeners;

    /** The Ldap codec protocol filter */
    private IoFilter ldapProtocolFilter = new ProtocolCodecFilter( codec.getProtocolCodecFactory() );

    /** the SslFilter key */
    private static final String SSL_FILTER_KEY = "sslFilter";

    /** The exception stored in the session if we've got one */
    private static final String EXCEPTION_KEY = "sessionException";

    /** The krb5 configuration property */
    private static final String KRB5_CONF = "java.security.krb5.conf";
    
    /** A future used to block any action until the handshake is completed */
    private HandshakeFuture handshakeFuture;
    
    /** A future used to wait for a connection to be closed */
    private CompletableFuture<Integer> connectionCloseFuture = new CompletableFuture<>(); 
    
    // ~~~~~~~~~~~~~~~~~ common error messages ~~~~~~~~~~~~~~~~~~~~~~~~~~
    static final String TIME_OUT_ERROR = I18n.err( I18n.ERR_04170_TIMEOUT_OCCURED );

    static final String NO_RESPONSE_ERROR = I18n.err( I18n.ERR_04169_RESPONSE_QUEUE_EMPTIED );
    
   //------------------------- The constructors --------------------------//
    /**
     * Create a new instance of a LdapConnection on localhost,
     * port 389.
     */
    public LdapNetworkConnection()
    {
        this( null, -1, false );
    }


    /**
     *
     * Creates a new instance of LdapConnection with the given connection configuration.
     *
     * @param config the configuration of the LdapConnection
     */
    public LdapNetworkConnection( LdapConnectionConfig config )
    {
        this( config, LdapApiServiceFactory.getSingleton() );
    }


    /**
     * Creates a new LdapNetworkConnection instance
     * 
     * @param config The configuration to use
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( LdapConnectionConfig config, LdapApiService ldapApiService )
    {
        super( ldapApiService );
        this.config = config;

        if ( config.getBinaryAttributeDetector() == null )
        {
            config.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );
        }
        
        this.timeout = config.getTimeout();
    }


    /**
     * Create a new instance of a LdapConnection on localhost,
     * port 389 if the SSL flag is off, or 636 otherwise.
     *
     * @param useSsl A flag to tell if it's a SSL connection or not.
     */
    public LdapNetworkConnection( boolean useSsl )
    {
        this( null, -1, useSsl );
    }


    /**
     * Creates a new LdapNetworkConnection instance
     * 
     * @param useSsl If we are going to create a secure connection or not
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( boolean useSsl, LdapApiService ldapApiService )
    {
        this( null, -1, useSsl, ldapApiService );
    }


    /**
     * Create a new instance of a LdapConnection on a given
     * server, using the default port (389).
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     */
    public LdapNetworkConnection( String server )
    {
        this( server, -1, false );
    }


    /**
     * Creates a new LdapNetworkConnection instance
     * 
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( String server, LdapApiService ldapApiService )
    {
        this( server, -1, false, ldapApiService );
    }


    /**
     * Create a new instance of a LdapConnection on a given
     * server, using the default port (389) if the SSL flag
     * is off, or 636 otherwise.
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param useSsl A flag to tell if it's a SSL connection or not.
     */
    public LdapNetworkConnection( String server, boolean useSsl )
    {
        this( server, -1, useSsl );
    }


    /**
     * Creates a new LdapNetworkConnection instance
     * 
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param useSsl A flag to tell if it's a SSL connection or not.
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( String server, boolean useSsl, LdapApiService ldapApiService )
    {
        this( server, -1, useSsl, ldapApiService );
    }


    /**
     * Create a new instance of a LdapConnection on a
     * given server and a given port. We don't use ssl.
     *
     * @param server The server we want to be connected to
     * @param port The port the server is listening to
     */
    public LdapNetworkConnection( String server, int port )
    {
        this( server, port, false );
    }


    /**
     * Create a new instance of a LdapConnection on a
     * given server and a given port. We don't use ssl.
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param port The port the server is listening on
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( String server, int port, LdapApiService ldapApiService )
    {
        this( server, port, false, ldapApiService );
    }


    /**
     * Create a new instance of a LdapConnection on a given
     * server, and a give port. We set the SSL flag accordingly
     * to the last parameter.
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param port The port the server is listening to
     * @param useSsl A flag to tell if it's a SSL connection or not.
     */
    public LdapNetworkConnection( String server, int port, boolean useSsl )
    {
        this( buildConfig( server, port, useSsl ) );
    }
    
    
    /**
     * Create a new instance of a LdapConnection on a given
     * server, and a give port. This SSL connection will use the provided
     * TrustManagers
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param port The port the server is listening to
     * @param trustManagers The TrustManager to use
     */
    public LdapNetworkConnection( String server, int port, TrustManager... trustManagers )
    {
        this( buildConfig( server, port, true ) );
        
        config.setTrustManagers( trustManagers );
    }


    /**
     * Create a new instance of a LdapConnection on a
     * given server and a given port. We don't use ssl.
     *
     * @param server The server we want to be connected to. If null or empty,
     * we will default to LocalHost.
     * @param port The port the server is listening on
     * @param useSsl A flag to tell if it's a SSL connection or not.
     * @param ldapApiService The LDAP API Service to use
     */
    public LdapNetworkConnection( String server, int port, boolean useSsl, LdapApiService ldapApiService )
    {
        this( buildConfig( server, port, useSsl ), ldapApiService );
    }


    private static LdapConnectionConfig buildConfig( String server, int port, boolean useSsl )
    {
        LdapConnectionConfig config = new LdapConnectionConfig();
        config.setUseSsl( useSsl );

        if ( port != -1 )
        {
            config.setLdapPort( port );
        }
        else
        {
            if ( useSsl )
            {
                config.setLdapPort( config.getDefaultLdapsPort() );
            }
            else
            {
                config.setLdapPort( config.getDefaultLdapPort() );
            }
        }

        // Default to localhost if null
        if ( Strings.isEmpty( server ) )
        {
            config.setLdapHost( Network.LOOPBACK_HOSTNAME );
            
        }
        else
        {
            config.setLdapHost( server );
        }

        config.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );

        return config;
    }


    /**
     * Create the connector
     * 
     * @throws LdapException If the connector can't be created
     */
    private void createConnector() throws LdapException
    {
        // Use only one thread inside the connector
        connector = new NioSocketConnector( 1 );
        
        if ( socketSessionConfig != null )
        {
            ( ( SocketSessionConfig ) connector.getSessionConfig() ).setAll( socketSessionConfig );
        }
        else
        {
            ( ( SocketSessionConfig ) connector.getSessionConfig() ).setReuseAddress( true );
        }

        // Add the codec to the chain
        connector.getFilterChain().addLast( "ldapCodec", ldapProtocolFilter );

        // If we use SSL, we have to add the SslFilter to the chain
        if ( config.isUseSsl() )
        {
            addSslFilter();
        }

        // Inject the protocolHandler
        connector.setHandler( this );
    }


    //--------------------------- Helper methods ---------------------------//
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isConnected()
    {
        return ( ioSession != null ) && ioSession.isConnected() && !ioSession.isClosing();
        
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAuthenticated()
    {
        return isConnected() && authenticated.get();
    }


    /**
     * Tells if the connection is using a secured channel
     * 
     * @return <tt>true</tt> if the session is using a secured channel
     */
    public boolean isSecured()
    {
        return isConnected() && ioSession.isSecured();
    }

    
    /**
     * {@inheritDoc}
     */
    @Override
    public Throwable exceptionCaught()
    {
        return ( Throwable ) ioSession.getAttribute( EXCEPTION_KEY );
    }
    
    
    /**
     * Check that a session is valid, ie we can send requests to the
     * server
     *
     * @throws InvalidConnectionException If the session is not valid
     */
    private void checkSession() throws InvalidConnectionException
    {
        if ( ioSession == null )
        {
            throw new InvalidConnectionException( I18n.err( I18n.ERR_04104_NULL_CONNECTION_CANNOT_CONNECT ) );
        }

        if ( !isConnected() )
        {
            throw new InvalidConnectionException( I18n.err( I18n.ERR_04108_INVALID_CONNECTION ) );
        }
    }


    private void addToFutureMap( int messageId, ResponseFuture<? extends Response> future )
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04106_ADDING, messageId, future.getClass().getName() ) );
        }
        
        futureMap.put( messageId, future );
    }


    private ResponseFuture<? extends Response> getFromFutureMap( int messageId )
    {
        ResponseFuture<? extends Response> future = futureMap.remove( messageId );

        if ( LOG.isDebugEnabled() && ( future != null ) )
        {
            LOG.debug( I18n.msg( I18n.MSG_04126_REMOVING, messageId, future.getClass().getName() ) );
        }

        return future;
    }


    private ResponseFuture<? extends Response> peekFromFutureMap( int messageId )
    {
        ResponseFuture<? extends Response> future = futureMap.get( messageId );

        // future can be null if there was a abandon operation on that messageId
        if ( LOG.isDebugEnabled() && ( future != null ) )
        {
            LOG.debug( I18n.msg( I18n.MSG_04119_GETTING, messageId, future.getClass().getName() ) );
        }

        return future;
    }


    /**
     * Get the largest timeout from the search time limit and the connection
     * timeout.
     * 
     * @param connectionTimoutInMS Connection timeout
     * @param searchTimeLimitInSeconds Search timeout
     * @return The largest timeout
     */
    public long getTimeout( long connectionTimoutInMS, int searchTimeLimitInSeconds )
    {
        if ( searchTimeLimitInSeconds < 0 )
        {
            return connectionTimoutInMS;
        }
        else if ( searchTimeLimitInSeconds == 0 )
        {
            if ( config.getTimeout() == 0 )
            {
                return Long.MAX_VALUE;
            }
            else
            {
                return config.getTimeout();
            }
        }
        else
        {
            long searchTimeLimitInMS = searchTimeLimitInSeconds * 1000L;
            return Math.max( searchTimeLimitInMS, connectionTimoutInMS );
        }
    }

    
    /**
     * Process the connect. 
     * 
     * @exception LdapException If we weren't able to connect
     * @return A Future that can be used to check the status of the connection
     */
    public ConnectFuture tryConnect() throws LdapException
    {
        // Build the connection address
        SocketAddress address = new InetSocketAddress( config.getLdapHost(), config.getLdapPort() );
        ConnectFuture connectionFuture = connector.connect( address );
        boolean result = false;

        // Wait until it's established
        try
        {
            result = connectionFuture.await( timeout );
        }
        catch ( InterruptedException e )
        {
            connector.dispose();
            connector = null;

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04120_INTERRUPTED_WAITING_FOR_CONNECTION, 
                    config.getLdapHost(),
                    config.getLdapPort() ), e );
            }
            
            throw new LdapOtherException( e.getMessage(), e );
        }

        if ( !result )
        {
            // It may be an exception, or a timeout
            Throwable connectionException = connectionFuture.getException();

            if ( ( connector != null ) && !connector.isDisposing() && !connector.isDisposed() )
            { 
                connector.dispose();
            }

            connector = null;

            if ( connectionException == null )
            {
                // This was a timeout
                String message = I18n.msg( I18n.MSG_04177_CONNECTION_TIMEOUT, timeout );
                
                if ( LOG.isDebugEnabled() )
                {
                    LOG.debug( message );
                }
                
                throw new LdapConnectionTimeOutException( message );
            }
            else
            {
                if ( LOG.isDebugEnabled() )
                {
                    if ( ( connectionException instanceof ConnectException )
                        || ( connectionException instanceof UnresolvedAddressException ) )
                    {
                        // No need to wait
                        // We know that there was a permanent error such as "connection refused".
                        LOG.debug( I18n.msg( I18n.MSG_04144_CONNECTION_ERROR, connectionFuture.getException().getMessage() ) );
                    }
    
                    LOG.debug( I18n.msg( I18n.MSG_04120_INTERRUPTED_WAITING_FOR_CONNECTION, 
                        config.getLdapHost(),
                        config.getLdapPort() ), connectionException );
                }
                
                throw new LdapOtherException( connectionException.getMessage(), connectionException );
            }
        }
        
        return connectionFuture;
    }
    
    
    /**
     * Close the connection and generate the appropriate exception
     * 
     * @exception LdapException If we weren't able to close the connection
     */
    private void close( ConnectFuture connectionFuture ) throws LdapException
    {
        // disposing connector if not connected
        close();

        Throwable e = connectionFuture.getException();

        if ( e != null )
        {
            // Special case for UnresolvedAddressException
            // (most of the time no message is associated with this exception)
            if ( ( e instanceof UnresolvedAddressException ) && ( e.getMessage() == null ) )
            {
                throw new InvalidConnectionException( I18n.err( I18n.ERR_04121_CANNOT_RESOLVE_HOSTNAME, config.getLdapHost() ), e );
            }

            // Default case
            throw new InvalidConnectionException( I18n.err( I18n.ERR_04110_CANNOT_CONNECT_TO_SERVER, e.getMessage() ), e );
        }

        // We didn't received anything : this is an error
        if ( LOG.isErrorEnabled() )
        {
            LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Connect" ) );
        }

        throw new LdapException( TIME_OUT_ERROR );
    }
    
    
    /**
     * Verify that the connection has been secured, otherwise throw a meaningful exception
     * 
     * @exception LdapException If we weren't able to check that the connection is secured
     */
    private void checkSecured( ConnectFuture connectionFuture ) throws LdapException
    {
        try
        {
            boolean isSecured = handshakeFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( !isSecured )
            {
                // check for a specific cause
                Throwable cause = connectionFuture.getException();
                
                if ( cause == null && connectionFuture.getSession() != null )
                {
                    cause = ( Throwable ) connectionFuture.getSession().getAttribute( EXCEPTION_KEY );
                }
                
                // Cancel the latch
                connectionCloseFuture.complete( 0 );

                // if there is no cause assume timeout
                if ( cause == null )
                {
                    throw new LdapException( TIME_OUT_ERROR );
                }

                throw new LdapTlsHandshakeException( I18n.err( I18n.ERR_04120_TLS_HANDSHAKE_ERROR ), cause );
            }
        }
        catch ( Exception e )
        {
            if ( e instanceof LdapException )
            {
                throw ( LdapException ) e;
            }

            String msg = I18n.err( I18n.ERR_04122_SSL_CONTEXT_INIT_FAILURE );
            LOG.error( msg, e );
            throw new LdapException( msg, e );
        }
    }
    
    
    /**
     * Set a listener associated to the closeFuture
     * 
     * @param connectionFuture A Future for which we want to set a listener
     */
    private void setCloseListener( ConnectFuture connectionFuture )
    {
        // Get the close future for this session
        CloseFuture closeFuture = connectionFuture.getSession().getCloseFuture();
        
        closeFuture.addListener( future -> 
        {
            // Process all the waiting operations and cancel them
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04137_NOD_RECEIVED ) );
            }

            for ( ResponseFuture<?> responseFuture : futureMap.values() )
            {
                if ( LOG.isDebugEnabled() )
                {
                    LOG.debug( I18n.msg( I18n.MSG_04137_NOD_RECEIVED ) );
                }

                responseFuture.cancel();

                try
                {
                    if ( responseFuture instanceof AddFuture )
                    {
                        ( ( AddFuture ) responseFuture ).set( AddNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof BindFuture )
                    {
                        ( ( BindFuture ) responseFuture ).set( BindNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof CompareFuture )
                    {
                        ( ( CompareFuture ) responseFuture ).set( CompareNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof DeleteFuture )
                    {
                        ( ( DeleteFuture ) responseFuture ).set( DeleteNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof ExtendedFuture )
                    {
                        ( ( ExtendedFuture ) responseFuture ).set( ExtendedNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof ModifyFuture )
                    {
                        ( ( ModifyFuture ) responseFuture ).set( ModifyNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof ModifyDnFuture )
                    {
                        ( ( ModifyDnFuture ) responseFuture ).set( ModifyDnNoDResponse.PROTOCOLERROR );
                    }
                    else if ( responseFuture instanceof SearchFuture )
                    {
                        ( ( SearchFuture ) responseFuture ).set( SearchNoDResponse.PROTOCOLERROR );
                    }
                }
                catch ( InterruptedException e )
                {
                    LOG.error( I18n.err( I18n.ERR_04113_ERROR_PROCESSING_NOD, responseFuture ), e );
                }

                futureMap.remove( messageId.get() );
            }

            futureMap.clear();
        } );
    }
    
    
    /**
     * Set the BinaryDetector instance in the session
     */
    private void setBinaryDetector()
    {
        @SuppressWarnings("unchecked")
        LdapMessageContainer<? extends Message> container =
            ( LdapMessageContainer<? extends Message> ) ioSession
                .getAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR );

        if ( container != null )
        {
            if ( ( schemaManager != null ) && !( container.getBinaryAttributeDetector() instanceof SchemaBinaryAttributeDetector ) )
            {
                container.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( schemaManager ) );
            }
        }
        else
        {
            BinaryAttributeDetector atDetector = new DefaultConfigurableBinaryAttributeDetector();

            if ( schemaManager != null )
            {
                atDetector = new SchemaBinaryAttributeDetector( schemaManager );
            }

            ioSession.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR,
                new LdapMessageContainer<Message>( codec, atDetector ) );
        }
    }
    

    //-------------------------- The methods ---------------------------//
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connect() throws LdapException
    {
        if ( isConnected() )
        {
            // No need to connect if we already have a connected session
            return true;
        }
        
        try
        {
            // Create the connector if needed
            if ( connector == null )
            {
                createConnector();
            }
    
            // And create the connection future
            ConnectFuture connectionFuture = tryConnect();
    
            // Check if we are good to go
            if ( !connectionFuture.isConnected() )
            {
                // Release the latch
                connectionCloseFuture.cancel( true );
                
                close( connectionFuture );
            }
    
            // Check if we are secured if requested
            if ( config.isUseSsl() )
            {
                checkSecured( connectionFuture );
            }
    
            // Add a listener to close the session in the session.
            setCloseListener( connectionFuture );
    
            // Get back the session
            ioSession = connectionFuture.getSession();
    
            // Store the container into the session if we don't have one
            setBinaryDetector();
    
            // Initialize the MessageId
            messageId.set( 0 );
            
            connectionCloseFuture = new CompletableFuture<>();
    
            // And return
            return true;
        }
        catch ( Exception e )
        {
            if ( ( connector != null ) && !connector.isDisposing() && !connector.isDisposed() ) 
            {
                connector.dispose();
                connector = null;
            }

            throw e;
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void close()
    {
        // Close the session
        if ( isConnected() )
        {
            ioSession.closeNow();
        }

        try
        {
            if ( ( ioSession != null ) && ioSession.isConnected() )
            { 
                connectionCloseFuture.get( timeout, TimeUnit.MILLISECONDS );
            }
        }
        catch ( TimeoutException | ExecutionException | InterruptedException e )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSH_04178_CLOSE_LATCH_ABORTED ) );
            }
        }
    }


    //------------------------ The LDAP operations ------------------------//
    // Add operations                                                      //
    //---------------------------------------------------------------------//
    /**
     * {@inheritDoc}
     */
    @Override
    public void add( Entry entry ) throws LdapException
    {
        if ( entry == null )
        {
            String msg = I18n.err( I18n.ERR_04123_CANNOT_ADD_EMPTY_ENTRY );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        AddRequest addRequest = new AddRequestImpl();
        addRequest.setEntry( entry );

        AddResponse addResponse = add( addRequest );

        processResponse( addResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public AddFuture addAsync( Entry entry ) throws LdapException
    {
        if ( entry == null )
        {
            String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        AddRequest addRequest = new AddRequestImpl();
        addRequest.setEntry( entry );

        return addAsync( addRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public AddResponse add( AddRequest addRequest ) throws LdapException
    {
        if ( addRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04124_CANNOT_PROCESS_NULL_ADD_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( addRequest.getEntry() == null )
        {
            String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        AddFuture addFuture = addAsync( addRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            AddResponse addResponse = addFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( addResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Add" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( addResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04108_ADD_SUCCESSFUL, addResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04107_ADD_FAILED, addResponse ) );
                }
            }

            return addResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !addFuture.isCancelled() )
            {
                abandon( addRequest.getMessageId() );
            }

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public AddFuture addAsync( AddRequest addRequest ) throws LdapException
    {
        if ( addRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04124_CANNOT_PROCESS_NULL_ADD_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( addRequest.getEntry() == null )
        {
            String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();

        addRequest.setMessageId( newId );
        AddFuture addFuture = new AddFuture( this, newId );
        addToFutureMap( newId, addFuture );

        // Send the request to the server
        writeRequest( addRequest );

        // Ok, done return the future
        return addFuture;
    }


    //------------------------ The LDAP operations ------------------------//

    /**
     * {@inheritDoc}
     */
    @Override
    public void abandon( int messageId )
    {
        if ( messageId < 0 )
        {
            String msg = I18n.err( I18n.ERR_04126_CANNOT_ABANDON_NEG_MSG_ID );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        AbandonRequest abandonRequest = new AbandonRequestImpl();
        abandonRequest.setAbandoned( messageId );

        abandonInternal( abandonRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void abandon( AbandonRequest abandonRequest )
    {
        if ( abandonRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04127_CANNOT_PROCESS_NULL_ABANDON_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        abandonInternal( abandonRequest );
    }


    /**
     * Internal AbandonRequest handling
     * 
     * @param abandonRequest The request to abandon
     */
    private void abandonInternal( AbandonRequest abandonRequest )
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, abandonRequest ) );
        }

        int newId = messageId.incrementAndGet();
        abandonRequest.setMessageId( newId );

        // Send the request to the server
        ioSession.write( abandonRequest );

        // remove the associated listener if any
        int abandonId = abandonRequest.getAbandoned();

        ResponseFuture<? extends Response> rf = getFromFutureMap( abandonId );

        // if the listener is not null, this is a async operation and no need to
        // send cancel signal on future, sending so will leave a dangling poision object in the corresponding queue
        // this is a sync operation send cancel signal to the corresponding ResponseFuture
        if ( rf != null )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04141_SENDING_CANCEL ) );
            }
            
            rf.cancel( true );
        }
        else
        {
            // this shouldn't happen
            if ( LOG.isWarnEnabled() )
            {
                LOG.warn( I18n.msg( I18n.MSG_04165_NO_FUTURE_ASSOCIATED_TO_MSG_ID_COMPLETED, abandonId ) );
            }
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void bind() throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg(  I18n.MSG_04112_BIND ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( config.getName(), Strings.getBytesUtf8( config.getCredentials() ) );

        BindResponse bindResponse = bind( bindRequest );

        processResponse( bindResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void anonymousBind() throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        { 
            LOG.debug( I18n.msg( I18n.MSG_04109_ANONYMOUS_BIND ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( StringConstants.EMPTY, Strings.EMPTY_BYTES );

        BindResponse bindResponse = bind( bindRequest );

        processResponse( bindResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindFuture bindAsync() throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04111_ASYNC_BIND ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( config.getName(), Strings.getBytesUtf8( config.getCredentials() ) );

        return bindAsync( bindRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindFuture anonymousBindAsync() throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        { 
            LOG.debug( I18n.msg( I18n.MSG_04110_ANONYMOUS_ASYNC_BIND ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( StringConstants.EMPTY, Strings.EMPTY_BYTES );

        return bindAsync( bindRequest );
    }


    /**
     * Asynchronous unauthenticated authentication bind
     *
     * @param name The name we use to authenticate the user. It must be a
     * valid Dn
     * @return The BindResponse LdapResponse
     * @throws LdapException if some error occurred
     */
    public BindFuture bindAsync( String name ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( name, Strings.EMPTY_BYTES );

        return bindAsync( bindRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindFuture bindAsync( String name, String credentials ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
        }

        // The password must not be empty or null
        if ( Strings.isEmpty( credentials ) && Strings.isNotEmpty( name ) )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
            }
            
            throw new LdapAuthenticationException( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( name, Strings.getBytesUtf8( credentials ) );

        return bindAsync( bindRequest );
    }


    /**
     * Asynchronous unauthenticated authentication Bind on a server.
     *
     * @param name The name we use to authenticate the user. It must be a
     * valid Dn
     * @return The BindResponse LdapResponse
     * @throws LdapException if some error occurred
     */
    public BindFuture bindAsync( Dn name ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( name, Strings.EMPTY_BYTES );

        return bindAsync( bindRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindFuture bindAsync( Dn name, String credentials ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
        }

        // The password must not be empty or null
        if ( Strings.isEmpty( credentials ) && ( !Dn.EMPTY_DN.equals( name ) ) )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
            }
            
            throw new LdapAuthenticationException( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
        }

        // Create the BindRequest
        BindRequest bindRequest = createBindRequest( name, Strings.getBytesUtf8( credentials ) );

        return bindAsync( bindRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindResponse bind( BindRequest bindRequest ) throws LdapException
    {
        if ( bindRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04128_CANNOT_PROCESS_NULL_BIND_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( bindRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );
            
            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Create a Simple BindRequest ready to be sent.
     * 
     * @param name The Bind name
     * @param credentials The Bind credentials
     * @return The created BindRequest instance
     */
    private BindRequest createBindRequest( String name, byte[] credentials )
    {
        return createBindRequest( name, credentials, null, ( Control[] ) null );
    }


    /**
     * Create a Simple BindRequest ready to be sent.
     * 
     * @param name The Bind name
     * @param credentials The Bind credentials
     * @return The created BindRequest instance
     */
    private BindRequest createBindRequest( Dn name, byte[] credentials )
    {
        return createBindRequest( name.getName(), credentials, null, ( Control[] ) null );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BindFuture bindAsync( BindRequest bindRequest ) throws LdapException
    {
        if ( bindRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04128_CANNOT_PROCESS_NULL_BIND_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // First switch to anonymous state
        authenticated.set( false );

        // try to connect, if we aren't already connected.
        connect();

        // establish TLS layer if TLS is enabled and SSL is NOT
        if ( config.isUseTls() && !config.isUseSsl() )
        {
            startTls();
        }

        // If the session has not been establish, or is closed, we get out immediately
        checkSession();

        // Update the messageId
        int newId = messageId.incrementAndGet();
        bindRequest.setMessageId( newId );

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, bindRequest ) );
        }

        // Create a future for this Bind operation
        BindFuture bindFuture = new BindFuture( this, newId );

        addToFutureMap( newId, bindFuture );

        writeRequest( bindRequest );

        // Ok, done return the future
        return bindFuture;
    }


    /**
     * SASL PLAIN Bind on a server.
     *
     * @param authcid The Authentication identity
     * @param credentials The password. It can't be null
     * @return The BindResponse LdapResponse
     * @throws LdapException if some error occurred
     */
    public BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException
    {
        return bindSaslPlain( null, authcid, credentials );
    }


    /**
     * SASL PLAIN Bind on a server.
     *
     * @param authzid The Authorization identity
     * @param authcid The Authentication identity
     * @param credentials The password. It can't be null
     * @return The BindResponse LdapResponse
     * @throws LdapException if some error occurred
     */
    public BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04127_SASL_PLAIN_BIND ) );
        }

        // Create the BindRequest
        SaslPlainRequest saslRequest = new SaslPlainRequest();
        saslRequest.setAuthorizationId( authzid );
        saslRequest.setUsername( authcid );
        saslRequest.setCredentials( credentials );

        BindFuture bindFuture = bindAsync( saslRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Bind to the server using a SaslRequest object.
     *
     * @param request The SaslRequest POJO containing all the needed parameters
     * @return A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bind( SaslRequest request ) throws LdapException
    {
        if ( request == null )
        {
            String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( request );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Bind to the server using the SASL CRAM-MD5 mechanism.
     *
     * @param userName The user name
     * @param credentials The user credentials
     * @return  A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bindSaslCramMd5( String userName, String credentials ) throws LdapException
    {
        SaslCramMd5Request request = new SaslCramMd5Request();
        request.setUsername( userName );
        request.setCredentials( "secret" );

        return bind( request );
    }


    /**
     * Bind to the server using the SASL DIGEST-MD5 mechanism.
     *
     * @param userName The user name
     * @param credentials The user credentials
     * @return  A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bindSaslDigestMd5( String userName, String credentials ) throws LdapException
    {
        SaslDigestMd5Request request = new SaslDigestMd5Request();
        request.setUsername( userName );
        request.setCredentials( "secret" );

        return bind( request );
    }


    /**
     * Bind to the server using a CramMd5Request object.
     *
     * @param request The CramMd5Request POJO containing all the needed parameters
     * @return A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bind( SaslCramMd5Request request ) throws LdapException
    {
        if ( request == null )
        {
            String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( request );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Do an asynchronous bind, based on a SaslPlainRequest.
     *
     * @param request The SaslPlainRequest POJO containing all the needed parameters
     * @return The bind operation's future
     * @throws LdapException if some error occurred
     */
    public BindFuture bindAsync( SaslRequest request )
        throws LdapException
    {
        return bindSasl( request );
    }


    /**
     * Bind to the server using a DigestMd5Request object.
     *
     * @param request The DigestMd5Request POJO containing all the needed parameters
     * @return A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bind( SaslDigestMd5Request request ) throws LdapException
    {
        if ( request == null )
        {
            String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( request );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Bind to the server using a GssApiRequest object.
     *
     * @param request The GssApiRequest POJO containing all the needed parameters
     * @return A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bind( SaslGssApiRequest request ) throws LdapException
    {
        if ( request == null )
        {
            String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( request );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Bind to the server using a SaslExternalRequest object.
     *
     * @param request The SaslExternalRequest POJO containing all the needed parameters
     * @return A LdapResponse containing the result
     * @throws LdapException if some error occurred
     */
    public BindResponse bind( SaslExternalRequest request ) throws LdapException
    {
        if ( request == null )
        {
            String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        BindFuture bindFuture = bindAsync( request );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            BindResponse bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( bindResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                { 
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                authenticated.set( true );

                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
                }
            }

            return bindResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * Do an asynchronous bind, based on a GssApiRequest.
     *
     * @param request The GssApiRequest POJO containing all the needed parameters
     * @return The bind operation's future
     * @throws LdapException if some error occurred
     */
    public BindFuture bindAsync( SaslGssApiRequest request )
        throws LdapException
    {
        // Krb5.conf file
        if ( request.getKrb5ConfFilePath() != null )
        {
            // Using the krb5.conf file provided by the user
            System.setProperty( KRB5_CONF, request.getKrb5ConfFilePath() );
        }
        else if ( ( request.getRealmName() != null ) && ( request.getKdcHost() != null )
            && ( request.getKdcPort() != 0 ) )
        {
            try
            {
                // Using a custom krb5.conf we create from the settings provided by the user
                String krb5ConfPath = createKrb5ConfFile( request.getRealmName(), request.getKdcHost(),
                    request.getKdcPort() );
                System.setProperty( KRB5_CONF, krb5ConfPath );
            }
            catch ( IOException ioe )
            {
                throw new LdapException( ioe );
            }
        }
        else
        {
            // Using the system Kerberos configuration
            System.clearProperty( KRB5_CONF );
        }

        // Login Module configuration
        if ( request.getLoginModuleConfiguration() != null )
        {
            // Using the configuration provided by the user
            Configuration.setConfiguration( request.getLoginModuleConfiguration() );
        }
        else
        {
            // Using the default configuration
            Configuration.setConfiguration( new Krb5LoginConfiguration() );
        }

        try
        {
            System.setProperty( "javax.security.auth.useSubjectCredsOnly", "true" );
            LoginContext loginContext = new LoginContext( request.getLoginContextName(),
                new SaslCallbackHandler( request ) );
            loginContext.login();

            final SaslGssApiRequest requetFinal = request;
            return ( BindFuture ) Subject.doAs( loginContext.getSubject(), new PrivilegedExceptionAction<Object>()
            {
                @Override
                public Object run() throws Exception
                {
                    return bindSasl( requetFinal );
                }
            } );
        }
        catch ( Exception e )
        {
            connectionCloseFuture.complete( 0 );
            throw new LdapException( e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public EntryCursor search( Dn baseDn, String filter, SearchScope scope, String... attributes )
        throws LdapException
    {
        if ( baseDn == null )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04138_NULL_DN_SEARCH ) );
            }
            
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04129_NULL_BASE_DN ) );
        }

        // Create a new SearchRequest object
        SearchRequest searchRequest = new SearchRequestImpl();

        searchRequest.setBase( baseDn );
        searchRequest.setFilter( filter );
        searchRequest.setScope( scope );
        searchRequest.addAttributes( attributes );
        searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );

        // Process the request in blocking mode
        return new EntryCursorImpl( search( searchRequest ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes )
        throws LdapException
    {
        return search( new Dn( baseDn ), filter, scope, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public SearchFuture searchAsync( Dn baseDn, String filter, SearchScope scope, String... attributes )
        throws LdapException
    {
        // Create a new SearchRequest object
        SearchRequest searchRequest = new SearchRequestImpl();

        searchRequest.setBase( baseDn );
        searchRequest.setFilter( filter );
        searchRequest.setScope( scope );
        searchRequest.addAttributes( attributes );
        searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );

        // Process the request in blocking mode
        return searchAsync( searchRequest );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public SearchFuture searchAsync( String baseDn, String filter, SearchScope scope, String... attributes )
        throws LdapException
    {
        return searchAsync( new Dn( baseDn ), filter, scope, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public SearchFuture searchAsync( SearchRequest searchRequest ) throws LdapException
    {
        if ( searchRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04130_CANNOT_PROCESS_NULL_SEARCH_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( searchRequest.getBase() == null )
        {
            String msg = I18n.err( I18n.ERR_04131_CANNOT_PROCESS_SEARCH_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        // If the session has not been establish, or is closed, we get out immediately
        checkSession();

        int newId = messageId.incrementAndGet();
        searchRequest.setMessageId( newId );

        if ( searchRequest.isIgnoreReferrals() )
        {
            // We want to ignore the referral, inject the ManageDSAIT control in the request
            searchRequest.addControl( new ManageDsaITImpl() );
        }

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, searchRequest ) );
        }

        SearchFuture searchFuture = new SearchFuture( this, searchRequest.getMessageId() );
        addToFutureMap( searchRequest.getMessageId(), searchFuture );

        // Send the request to the server
        writeRequest( searchRequest );

        // Check that the future hasn't be canceled
        if ( searchFuture.isCancelled() )
        {
            // Throw an exception here
            throw new LdapException( searchFuture.getCause() );
        }

        // Ok, done return the future
        return searchFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public SearchCursor search( SearchRequest searchRequest ) throws LdapException
    {
        if ( searchRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04130_CANNOT_PROCESS_NULL_SEARCH_REQ );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        SearchFuture searchFuture = searchAsync( searchRequest );

        long searchTimeout = getTimeout( timeout, searchRequest.getTimeLimit() );

        return new SearchCursorImpl( searchFuture, searchTimeout, TimeUnit.MILLISECONDS );
    }


    //------------------------ The LDAP operations ------------------------//
    // Unbind operations                                                   //
    //---------------------------------------------------------------------//
    /**
     * {@inheritDoc}
     */
    @Override
    public void unBind() throws LdapException
    {
        // If the session has not been establish, or is closed, we get out immediately
        checkSession();

        // Creates the messageID and stores it into the
        // initial message and the transmitted message.
        int newId = messageId.incrementAndGet();

        // Create the UnbindRequest
        UnbindRequest unbindRequest = new UnbindRequestImpl();
        unbindRequest.setMessageId( newId );

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04132_SENDING_UNBIND, unbindRequest ) );
        }

        // Send the request to the server
        // Use this for logging instead: WriteFuture unbindFuture = ldapSession.write( unbindRequest )
        WriteFuture unbindFuture = ioSession.write( unbindRequest );

        unbindFuture.awaitUninterruptibly( timeout );

        try
        {
            connectionCloseFuture.get( timeout, TimeUnit.MILLISECONDS );
        }
        catch ( TimeoutException | ExecutionException | InterruptedException e )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSH_04178_CLOSE_LATCH_ABORTED ) );
            }
        }

        // And get out
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04133_UNBINDSUCCESSFUL ) );
        }
    }


    /**
     * Set the connector to use.
     *
     * @param connector The connector to use
     */
    public void setConnector( IoConnector connector )
    {
        this.connector = connector;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setTimeOut( long timeout )
    {
        if ( timeout <= 0 )
        {
            // Set a date in the far future : 100 years
            this.timeout = 1000L * 60L * 60L * 24L * 365L * 100L;
        }
        else
        {
            this.timeout = timeout;
        }
    }


    /**
     * Handle the exception we got.
     *
     * @param session The session we got the exception on
     * @param cause The exception cause
     * @throws Exception If we have had another exception
     */
    @Override
    public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
    {
        if ( LOG.isWarnEnabled() )
        {
            LOG.warn( cause.getMessage(), cause );
        }

        session.setAttribute( EXCEPTION_KEY, cause );

        if ( cause instanceof ProtocolEncoderException )
        {
            Throwable realCause = ( ( ProtocolEncoderException ) cause ).getCause();

            if ( realCause instanceof MessageEncoderException )
            {
                int messageId = ( ( MessageEncoderException ) realCause ).getMessageId();

                ResponseFuture<?> response = futureMap.get( messageId );
                response.cancel( true );
                response.setCause( realCause );
            }
        }

        session.closeNow();
    }


    /**
     * Check if the message is a NoticeOfDisconnect message
     * 
     * @param message The message to check
     * @return <tt>true</tt> if the message is a Notice of Disconnect
     */
    private boolean isNoticeOfDisconnect( Message message )
    {
        if ( message instanceof ExtendedResponse )
        {
            String responseName = ( ( ExtendedResponse ) message ).getResponseName();

            if ( NoticeOfDisconnect.EXTENSION_OID.equals( responseName ) )
            {
                return true;
            }
        }

        return false;
    }


    /**
     * Process the AddResponse received from the server
     * 
     * @param addResponse The AddResponse to process
     * @param addFuture The AddFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void addReceived( AddResponse addResponse, AddFuture addFuture, int responseId ) throws InterruptedException
    {
        // remove the listener from the listener map
        if ( LOG.isDebugEnabled() )
        {
            if ( addResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04108_ADD_SUCCESSFUL, addResponse ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04107_ADD_FAILED, addResponse ) );
            }
        }

        // Store the response into the future
        addFuture.set( addResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the BindResponse received from the server
     * 
     * @param bindResponse The BindResponse to process
     * @param bindFuture The BindFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void bindReceived( BindResponse bindResponse, BindFuture bindFuture, int responseId ) 
        throws InterruptedException
    {
        // remove the listener from the listener map
        if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
        {
            authenticated.set( true );

            // Everything is fine, return the response
            if ( LOG.isDebugEnabled() )
            { 
                LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
            }
        }
        else
        {
            // We have had an error
            if ( LOG.isDebugEnabled() )
            { 
                LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
            }
        }

        // Store the response into the future
        bindFuture.set( bindResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the CompareResponse received from the server
     * 
     * @param compareResponse The CompareResponse to process
     * @param compareFuture The CompareFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void compareReceived( CompareResponse compareResponse, CompareFuture compareFuture, int responseId ) 
       throws InterruptedException
    {
        // remove the listener from the listener map
        if ( LOG.isDebugEnabled() )
        {
            if ( compareResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04114_COMPARE_SUCCESSFUL, compareResponse ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04113_COMPARE_FAILED, compareResponse ) );
            }
        }

        // Store the response into the future
        compareFuture.set( compareResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the DeleteResponse received from the server
     * 
     * @param deleteResponse The DeleteResponse to process
     * @param deleteFuture The DeleteFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void deleteReceived( DeleteResponse deleteResponse, DeleteFuture deleteFuture, int responseId ) 
        throws InterruptedException
    {
        if ( LOG.isDebugEnabled() )
        {
            if ( deleteResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04116_DELETE_SUCCESSFUL, deleteResponse ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04115_DELETE_FAILED, deleteResponse ) );
            }
        }

        // Store the response into the future
        deleteFuture.set( deleteResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the ExtendedResponse received from the server
     * 
     * @param extendedResponse The ExtendedResponse to process
     * @param extendedFuture The ExtendedFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     * @throws DecoderException If the response cannot be decoded
     */
    private void extendedReceived( ExtendedResponse extendedResponse, ExtendedFuture extendedFuture, int responseId ) 
        throws InterruptedException, DecoderException
    {
        if ( LOG.isDebugEnabled() )
        {
            if ( extendedResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04118_EXTENDED_SUCCESSFUL, extendedResponse ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04117_EXTENDED_FAILED, extendedResponse ) );
            }
        }
        
        extendedResponse = handleOpaqueResponse( extendedResponse, extendedFuture );

        // Store the response into the future
        extendedFuture.set( extendedResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the IntermediateResponse received from the server
     * 
     * @param intermediateResponse The IntermediateResponse to process
     * @param responseFuture The ResponseFuture to feed
     * @throws InterruptedException If the Future is interrupted
     */
    private void intermediateReceived( IntermediateResponse intermediateResponse, ResponseFuture<? extends Response> responseFuture ) 
        throws InterruptedException
    {
        // Store the response into the future
        if ( responseFuture instanceof SearchFuture )
        {
            ( ( SearchFuture ) responseFuture ).set( intermediateResponse );
        }
        else if ( responseFuture instanceof ExtendedFuture )
        {
            ( ( ExtendedFuture ) responseFuture ).set( intermediateResponse );
        }
        else
        {
            // currently we only support IR for search and extended operations
            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04111_UNKNOWN_RESPONSE_FUTURE_TYPE,
                responseFuture.getClass().getName() ) );
        }

        // Do not remove the future from the map, that's done when receiving search result done
    }


    /**
     * Process the ModifyResponse received from the server
     * 
     * @param modifyResponse The ModifyResponse to process
     * @param modifyFuture The ModifyFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void modifyReceived( ModifyResponse modifyResponse, ModifyFuture modifyFuture, int responseId ) 
        throws InterruptedException
    {
        if ( LOG.isDebugEnabled() )
        {
            if ( modifyResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04123_MODIFY_SUCCESSFUL, modifyResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04122_MODIFY_FAILED, modifyResponse ) );
                }
            }
        }

        // Store the response into the future
        modifyFuture.set( modifyResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the ModifyDnResponse received from the server
     * 
     * @param modifyDnResponse The ModifyDnResponse to process
     * @param modifyDnFuture The ModifyDnFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void modifyDnReceived( ModifyDnResponse modifyDnResponse, ModifyDnFuture modifyDnFuture, int responseId ) 
        throws InterruptedException
    {
        if ( LOG.isDebugEnabled() )
        {
            if ( modifyDnResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04125_MODIFYDN_SUCCESSFUL, modifyDnResponse ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04124_MODIFYDN_FAILED, modifyDnResponse ) );
            }
        }

        // Store the response into the future
        modifyDnFuture.set( modifyDnResponse );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the SearchResultDone received from the server
     * 
     * @param searchResultDone The SearchResultDone to process
     * @param searchFuture The SearchFuture to feed
     * @param responseId The associated request message ID
     * @throws InterruptedException If the Future is interrupted
     */
    private void searchResultDoneReceived( SearchResultDone searchResultDone, SearchFuture searchFuture, 
        int responseId ) throws InterruptedException
    {
        if ( LOG.isDebugEnabled() )
        {
            if ( searchResultDone.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                LOG.debug( I18n.msg( I18n.MSG_04131_SEARCH_SUCCESSFUL, searchResultDone ) );
            }
            else
            {
                // We have had an error
                LOG.debug( I18n.msg( I18n.MSG_04129_SEARCH_FAILED, searchResultDone ) );
            }
        }

        // Store the response into the future
        searchFuture.set( searchResultDone );

        // Remove the future from the map
        removeFromFutureMaps( responseId );
    }


    /**
     * Process the SearchResultEntry received from the server
     * 
     * @param searchResultEntry The SearchResultEntry to process
     * @param searchFuture The SearchFuture to feed
     * @throws InterruptedException If the Future is interrupted
     * @throws LdapException If we weren't able to create a new Entry
     */
    private void searchResultEntryReceived( SearchResultEntry searchResultEntry, SearchFuture searchFuture ) 
        throws InterruptedException, LdapException
    {
        if ( schemaManager != null )
        {
            searchResultEntry.setEntry( new DefaultEntry( schemaManager, searchResultEntry.getEntry() ) );
        }

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04128_SEARCH_ENTRY_FOUND, searchResultEntry ) );
        }

        // Store the response into the future
        searchFuture.set( searchResultEntry );
    }
    
    
    /**
     * Process the SearchResultEntry received from the server
     * 
     * @param searchResultReference The SearchResultReference to process
     * @param searchFuture The SearchFuture to feed
     * @throws InterruptedException If the Future is interrupted
     */
    private void searchResultReferenceReceived( SearchResultReference searchResultReference, SearchFuture searchFuture ) 
        throws InterruptedException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04130_SEARCH_REFERENCE_FOUND, searchResultReference ) );
        }

        // Store the response into the future
        searchFuture.set( searchResultReference );
    }
    

    /**
     * Handle the incoming LDAP messages. This is where we feed the cursor for search
     * requests, or call the listener.
     *
     * @param session The session that received a message
     * @param message The received message
     * @throws Exception If there is some error while processing the message
     */
    @Override
    public void messageReceived( IoSession session, Object message ) throws Exception
    {
        // Feed the response and store it into the session
        Response response = ( Response ) message;

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04142_MESSAGE_RECEIVED, response ) );
        }
        
        int responseId = response.getMessageId();

        // this check is necessary to prevent adding an abandoned operation's
        // result(s) to corresponding queue
        ResponseFuture<? extends Response> responseFuture = peekFromFutureMap( responseId );

        boolean isNoD = isNoticeOfDisconnect( response );

        if ( ( responseFuture == null ) && !isNoD )
        {
            if ( LOG.isInfoEnabled() )
            {
                LOG.info( I18n.msg( I18n.MSG_04166_NO_FUTURE_ASSOCIATED_TO_MSG_ID_IGNORING, responseId ) );
            }
            
            return;
        }

        if ( isNoD )
        {
            // close the session
            session.closeNow();

            return;
        }

        switch ( response.getType() )
        {
            case ADD_RESPONSE:
                addReceived( ( AddResponse ) response, ( AddFuture ) responseFuture, responseId );

                break;

            case BIND_RESPONSE:
                bindReceived( ( BindResponse ) response, ( BindFuture ) responseFuture, responseId );

                break;

            case COMPARE_RESPONSE:
                compareReceived( ( CompareResponse ) response, ( CompareFuture ) responseFuture, responseId );

                break;

            case DEL_RESPONSE:
                deleteReceived( ( DeleteResponse ) response, ( DeleteFuture ) responseFuture, responseId );

                break;

            case EXTENDED_RESPONSE:
                extendedReceived( ( ExtendedResponse ) response, ( ExtendedFuture ) responseFuture, responseId );

                break;

            case INTERMEDIATE_RESPONSE:
                intermediateReceived( ( IntermediateResponse ) response, responseFuture );

                break;

            case MODIFY_RESPONSE:
                modifyReceived( ( ModifyResponse ) response, ( ModifyFuture ) responseFuture, responseId );

                break;

            case MODIFYDN_RESPONSE:
                modifyDnReceived( ( ModifyDnResponse ) response, ( ModifyDnFuture ) responseFuture, responseId );

                break;

            case SEARCH_RESULT_DONE:
                searchResultDoneReceived( ( SearchResultDone ) response, ( SearchFuture ) responseFuture, responseId );

                break;

            case SEARCH_RESULT_ENTRY:
                searchResultEntryReceived( ( SearchResultEntry ) response, ( SearchFuture ) responseFuture );

                break;

            case SEARCH_RESULT_REFERENCE:
                searchResultReferenceReceived( ( SearchResultReference ) response, ( SearchFuture ) responseFuture );

                break;

            default:
                throw new IllegalStateException( I18n.err( I18n.ERR_04132_UNEXPECTED_RESPONSE_TYPE, response.getType() ) );
        }
    }

    
    private ExtendedResponse handleOpaqueResponse( ExtendedResponse extendedResponse, ExtendedFuture extendedFuture ) 
        throws DecoderException
    {
        if ( ( extendedResponse instanceof OpaqueExtendedResponse ) 
            && ( Strings.isEmpty( extendedResponse.getResponseName() ) ) ) 
        {
            ExtendedOperationFactory factory = codec.getExtendedResponseFactories().
                get( extendedFuture.getExtendedRequest().getRequestName() );

            byte[] responseValue = ( ( OpaqueExtendedResponse ) extendedResponse ).getResponseValue();

            ExtendedResponse response;
            if ( responseValue != null )
            {
                response = factory.newResponse( responseValue );
            }
            else
            {
                response = factory.newResponse();
            }

            // Copy the controls
            for ( Control control : extendedResponse.getControls().values() )
            {
                response.addControl( control );
            }
            
            // copy the LDAPResult
            response.getLdapResult().setDiagnosticMessage( extendedResponse.getLdapResult().getDiagnosticMessage() );
            response.getLdapResult().setMatchedDn( extendedResponse.getLdapResult().getMatchedDn() );
            response.getLdapResult().setReferral( extendedResponse.getLdapResult().getReferral() );
            response.getLdapResult().setResultCode( extendedResponse.getLdapResult().getResultCode() );
            
            return response;
        }
        else
        {
            return extendedResponse;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( Entry entry, ModificationOperation modOp ) throws LdapException
    {
        if ( entry == null )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04140_NULL_ENTRY_MODIFY ) );
            }
            
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04133_NULL_MODIFIED_ENTRY ) );
        }

        ModifyRequest modReq = new ModifyRequestImpl();
        modReq.setName( entry.getDn() );

        Iterator<Attribute> itr = entry.iterator();

        while ( itr.hasNext() )
        {
            modReq.addModification( itr.next(), modOp );
        }

        ModifyResponse modifyResponse = modify( modReq );

        processResponse( modifyResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( Dn dn, Modification... modifications ) throws LdapException
    {
        if ( dn == null )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04139_NULL_DN_MODIFY ) );
            }
            
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04134_NULL_MODIFIED_DN ) );
        }

        if ( ( modifications == null ) || ( modifications.length == 0 ) )
        {
            String msg = I18n.err( I18n.ERR_04135_CANNOT_PROCESS_NO_MODIFICATION_MOD );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ModifyRequest modReq = new ModifyRequestImpl();
        modReq.setName( dn );

        for ( Modification modification : modifications )
        {
            modReq.addModification( modification );
        }

        ModifyResponse modifyResponse = modify( modReq );

        processResponse( modifyResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void modify( String dn, Modification... modifications ) throws LdapException
    {
        modify( new Dn( dn ), modifications );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ModifyResponse modify( ModifyRequest modRequest ) throws LdapException
    {
        if ( modRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04136_CANNOT_PROCESS_NULL_MOD_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ModifyFuture modifyFuture = modifyAsync( modRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            ModifyResponse modifyResponse = modifyFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( modifyResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Modify" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( modifyResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04123_MODIFY_SUCCESSFUL, modifyResponse ) );
                }
            }
            else
            {
                if ( modifyResponse instanceof ModifyNoDResponse )
                {
                    // A NoticeOfDisconnect : deserves a special treatment
                    throw new LdapException( modifyResponse.getLdapResult().getDiagnosticMessage() );
                }

                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04122_MODIFY_FAILED, modifyResponse ) );
                }
            }

            return modifyResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !modifyFuture.isCancelled() )
            {
                abandon( modRequest.getMessageId() );
            }

            throw new LdapException( ie.getMessage(), ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ModifyFuture modifyAsync( ModifyRequest modRequest ) throws LdapException
    {
        if ( modRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04136_CANNOT_PROCESS_NULL_MOD_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( modRequest.getName() == null )
        {
            String msg = I18n.err( I18n.ERR_04137_CANNOT_PROCESS_MOD_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();
        modRequest.setMessageId( newId );

        ModifyFuture modifyFuture = new ModifyFuture( this, newId );
        addToFutureMap( newId, modifyFuture );

        // Send the request to the server
        writeRequest( modRequest );

        // Ok, done return the future
        return modifyFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( String entryDn, String newRdn ) throws LdapException
    {
        rename( entryDn, newRdn, true );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( Dn entryDn, Rdn newRdn ) throws LdapException
    {
        rename( entryDn, newRdn, true );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( String entryDn, String newRdn, boolean deleteOldRdn ) throws LdapException
    {
        if ( entryDn == null )
        {
            String msg = I18n.err( I18n.ERR_04138_CANNOT_PROCESS_RENAME_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( newRdn == null )
        {
            String msg = I18n.err( I18n.ERR_04139_CANNOT_PROCESS_RENAME_NULL_RDN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        try
        {
            rename( new Dn( entryDn ), new Rdn( newRdn ), deleteOldRdn );
        }
        catch ( LdapInvalidDnException e )
        {
            LOG.error( e.getMessage(), e );
            throw new LdapException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void rename( Dn entryDn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
    {
        if ( entryDn == null )
        {
            String msg = I18n.err( I18n.ERR_04138_CANNOT_PROCESS_RENAME_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( newRdn == null )
        {
            String msg = I18n.err( I18n.ERR_04139_CANNOT_PROCESS_RENAME_NULL_RDN );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
        modDnRequest.setName( entryDn );
        modDnRequest.setNewRdn( newRdn );
        modDnRequest.setDeleteOldRdn( deleteOldRdn );

        ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );

        processResponse( modifyDnResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void move( String entryDn, String newSuperiorDn ) throws LdapException
    {
        if ( entryDn == null )
        {
            String msg = I18n.err( I18n.ERR_04140_CANNOT_PROCESS_MOVE_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( newSuperiorDn == null )
        {
            String msg = I18n.err( I18n.ERR_04141_CANNOT_PROCESS_MOVE_NULL_SUPERIOR );
            
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        try
        {
            move( new Dn( entryDn ), new Dn( newSuperiorDn ) );
        }
        catch ( LdapInvalidDnException e )
        {
            LOG.error( e.getMessage(), e );
            throw new LdapException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void move( Dn entryDn, Dn newSuperiorDn ) throws LdapException
    {
        if ( entryDn == null )
        {
            String msg = I18n.err( I18n.ERR_04140_CANNOT_PROCESS_MOVE_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( newSuperiorDn == null )
        {
            String msg = I18n.err( I18n.ERR_04141_CANNOT_PROCESS_MOVE_NULL_SUPERIOR );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
        modDnRequest.setName( entryDn );
        modDnRequest.setNewSuperior( newSuperiorDn );

        modDnRequest.setNewRdn( entryDn.getRdn() );

        ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );

        processResponse( modifyDnResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( Dn entryDn, Dn newDn ) throws LdapException
    {
        moveAndRename( entryDn, newDn, true );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( String entryDn, String newDn ) throws LdapException
    {
        moveAndRename( new Dn( entryDn ), new Dn( newDn ), true );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( Dn entryDn, Dn newDn, boolean deleteOldRdn ) throws LdapException
    {
        // Check the parameters first
        if ( entryDn == null )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04142_NULL_ENTRY_DN ) );
        }

        if ( entryDn.isRootDse() )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04143_CANNOT_MOVE_ROOT_DSE ) );
        }

        if ( newDn == null )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04144_NULL_NEW_DN ) );
        }

        if ( newDn.isRootDse() )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET ) );
        }

        // Create the request
        ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
        modDnRequest.setName( entryDn );
        modDnRequest.setNewRdn( newDn.getRdn() );
        
        // Check if we really need to specify newSuperior.
        // newSuperior is optional [RFC4511, section 4.9]
        // Some servers (e.g. OpenDJ 2.6) require a special privilege if
        // newSuperior is specified even if it is the same as the old one. Therefore let's not
        // specify it if we do not need it. This is better interoperability. 
        Dn newDnParent = newDn.getParent();
        if ( newDnParent != null && !newDnParent.equals( entryDn.getParent() ) )
        {
            modDnRequest.setNewSuperior( newDnParent );
        }
        
        modDnRequest.setDeleteOldRdn( deleteOldRdn );

        ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );

        processResponse( modifyDnResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void moveAndRename( String entryDn, String newDn, boolean deleteOldRdn ) throws LdapException
    {
        moveAndRename( new Dn( entryDn ), new Dn( newDn ), true );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ModifyDnResponse modifyDn( ModifyDnRequest modDnRequest ) throws LdapException
    {
        if ( modDnRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ModifyDnFuture modifyDnFuture = modifyDnAsync( modDnRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            ModifyDnResponse modifyDnResponse = modifyDnFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( modifyDnResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "ModifyDn" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( modifyDnResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04125_MODIFYDN_SUCCESSFUL, modifyDnResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04124_MODIFYDN_FAILED, modifyDnResponse ) );
                }
            }

            return modifyDnResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !modifyDnFuture.isCancelled() )
            {
                abandon( modDnRequest.getMessageId() );
            }

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ModifyDnFuture modifyDnAsync( ModifyDnRequest modDnRequest ) throws LdapException
    {
        if ( modDnRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( modDnRequest.getName() == null )
        {
            String msg = I18n.err( I18n.ERR_04137_CANNOT_PROCESS_MOD_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( ( modDnRequest.getNewSuperior() == null ) && ( modDnRequest.getNewRdn() == null ) )
        {
            String msg = I18n.err( I18n.ERR_04147_CANNOT_PROCESS_MOD_NULL_DN_SUP );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();
        modDnRequest.setMessageId( newId );

        ModifyDnFuture modifyDnFuture = new ModifyDnFuture( this, newId );
        addToFutureMap( newId, modifyDnFuture );

        // Send the request to the server
        writeRequest( modDnRequest );

        // Ok, done return the future
        return modifyDnFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void delete( String dn ) throws LdapException
    {
        delete( new Dn( dn ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void delete( Dn dn ) throws LdapException
    {
        DeleteRequest deleteRequest = new DeleteRequestImpl();
        deleteRequest.setName( dn );

        DeleteResponse deleteResponse = delete( deleteRequest );

        processResponse( deleteResponse );
    }


    /**
     * deletes the entry with the given Dn, and all its children
     *
     * @param dn the target entry's Dn
     * @throws LdapException If the Dn is not valid or if the deletion failed
     */
    public void deleteTree( Dn dn ) throws LdapException
    {
        if ( isControlSupported( TreeDelete.OID ) )
        {
            DeleteRequest deleteRequest = new DeleteRequestImpl();
            deleteRequest.setName( dn );
            deleteRequest.addControl( new TreeDeleteImpl() );
            DeleteResponse deleteResponse = delete( deleteRequest );

            processResponse( deleteResponse );
        }
        else
        {
            String msg = I18n.err( I18n.ERR_04148_SUBTREE_CONTROL_NOT_SUPPORTED );
            LOG.error( msg );
            throw new LdapException( msg );
        }
    }


    /**
     * deletes the entry with the given Dn, and all its children
     *
     * @param dn the target entry's Dn as a String
     * @throws LdapException If the Dn is not valid or if the deletion failed
     */
    public void deleteTree( String dn ) throws LdapException
    {
        try
        {
            String treeDeleteOid = "1.2.840.113556.1.4.805";
            Dn newDn = new Dn( dn );

            if ( isControlSupported( treeDeleteOid ) )
            {
                DeleteRequest deleteRequest = new DeleteRequestImpl();
                deleteRequest.setName( newDn );
                deleteRequest.addControl( new OpaqueControl( treeDeleteOid ) );
                DeleteResponse deleteResponse = delete( deleteRequest );

                processResponse( deleteResponse );
            }
            else
            {
                String msg = I18n.err( I18n.ERR_04148_SUBTREE_CONTROL_NOT_SUPPORTED );
                LOG.error( msg );
                throw new LdapException( msg );
            }
        }
        catch ( LdapInvalidDnException e )
        {
            LOG.error( e.getMessage(), e );
            throw new LdapException( e.getMessage(), e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public DeleteResponse delete( DeleteRequest deleteRequest ) throws LdapException
    {
        if ( deleteRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04149_CANNOT_PROCESS_NULL_DEL_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        DeleteFuture deleteFuture = deleteAsync( deleteRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            DeleteResponse delResponse = deleteFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( delResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Delete" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( delResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04116_DELETE_SUCCESSFUL, delResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04115_DELETE_FAILED, delResponse ) );
                }
            }

            return delResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !deleteFuture.isCancelled() )
            {
                abandon( deleteRequest.getMessageId() );
            }

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public DeleteFuture deleteAsync( DeleteRequest deleteRequest ) throws LdapException
    {
        if ( deleteRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04149_CANNOT_PROCESS_NULL_DEL_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( deleteRequest.getName() == null )
        {
            String msg = I18n.err( I18n.ERR_04150_CANNOT_PROCESS_NULL_DEL_NULL_DN );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();

        deleteRequest.setMessageId( newId );

        DeleteFuture deleteFuture = new DeleteFuture( this, newId );
        addToFutureMap( newId, deleteFuture );

        // Send the request to the server
        writeRequest( deleteRequest );

        // Ok, done return the future
        return deleteFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( String dn, String attributeName, String value ) throws LdapException
    {
        return compare( new Dn( dn ), attributeName, value );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( String dn, String attributeName, byte[] value ) throws LdapException
    {
        return compare( new Dn( dn ), attributeName, value );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( String dn, String attributeName, Value value ) throws LdapException
    {
        return compare( new Dn( dn ), attributeName, value );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( Dn dn, String attributeName, String value ) throws LdapException
    {
        CompareRequest compareRequest = new CompareRequestImpl();
        compareRequest.setName( dn );
        compareRequest.setAttributeId( attributeName );
        compareRequest.setAssertionValue( value );

        CompareResponse compareResponse = compare( compareRequest );

        return processResponse( compareResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( Dn dn, String attributeName, byte[] value ) throws LdapException
    {
        CompareRequest compareRequest = new CompareRequestImpl();
        compareRequest.setName( dn );
        compareRequest.setAttributeId( attributeName );
        compareRequest.setAssertionValue( value );

        CompareResponse compareResponse = compare( compareRequest );

        return processResponse( compareResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean compare( Dn dn, String attributeName, Value value ) throws LdapException
    {
        CompareRequest compareRequest = new CompareRequestImpl();
        compareRequest.setName( dn );
        compareRequest.setAttributeId( attributeName );

        if ( value.isHumanReadable() )
        {
            compareRequest.setAssertionValue( value.getString() );
        }
        else
        {
            compareRequest.setAssertionValue( value.getBytes() );
        }

        CompareResponse compareResponse = compare( compareRequest );

        return processResponse( compareResponse );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public CompareResponse compare( CompareRequest compareRequest ) throws LdapException
    {
        if ( compareRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04151_CANNOT_PROCESS_NULL_COMP_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        CompareFuture compareFuture = compareAsync( compareRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            CompareResponse compareResponse = compareFuture.get( timeout, TimeUnit.MILLISECONDS );

            if ( compareResponse == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Compare" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( compareResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04114_COMPARE_SUCCESSFUL, compareResponse ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04113_COMPARE_FAILED, compareResponse ) );
                }
            }

            return compareResponse;
        }
        catch ( Exception ie )
        {
            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !compareFuture.isCancelled() )
            {
                abandon( compareRequest.getMessageId() );
            }

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public CompareFuture compareAsync( CompareRequest compareRequest ) throws LdapException
    {
        if ( compareRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04151_CANNOT_PROCESS_NULL_COMP_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        if ( compareRequest.getName() == null )
        {
            String msg = I18n.err( I18n.ERR_04152_CANNOT_PROCESS_NULL_DN_COMP_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();

        compareRequest.setMessageId( newId );

        CompareFuture compareFuture = new CompareFuture( this, newId );
        addToFutureMap( newId, compareFuture );

        // Send the request to the server
        writeRequest( compareRequest );

        // Ok, done return the future
        return compareFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedResponse extended( String oid ) throws LdapException
    {
        return extended( oid, null );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
    {
        try
        {
            return extended( Oid.fromString( oid ), value );
        }
        catch ( DecoderException e )
        {
            String msg = I18n.err( I18n.ERR_04153_OID_DECODING_FAILURE, oid );
            LOG.error( msg );
            throw new LdapException( msg, e );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedResponse extended( Oid oid ) throws LdapException
    {
        return extended( oid, null );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
    {
        Map<String, ExtendedOperationFactory> factories = LdapApiServiceFactory.getSingleton().getExtendedRequestFactories();
        String oidStr = oid.toString();
        
        ExtendedOperationFactory factory = factories.get( oidStr );
        
        if ( factory != null )
        {
            try
            {
                if ( value == null )
                {
                    return extended( factory.newRequest() );
                }
                else
                {
                    return extended( factory.newRequest( value ) );
                }
            }
            catch ( DecoderException de )
            {
                throw new LdapNoSuchObjectException( de.getMessage() );
            }
        }
        else
        {
            return extended( new OpaqueExtendedRequest( oidStr, value ) );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
    {
        if ( extendedRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04154_CANNOT_PROCESS_NULL_EXT_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        ExtendedFuture extendedFuture = extendedAsync( extendedRequest );

        // Get the result from the future
        try
        {
            // Read the response, waiting for it if not available immediately
            // Get the response, blocking
            ExtendedResponse response = ( ExtendedResponse ) extendedFuture
                .get( timeout, TimeUnit.MILLISECONDS );

            if ( response == null )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Extended" ) );
                }
                
                throw new LdapException( TIME_OUT_ERROR );
            }

            if ( response.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
            {
                // Everything is fine, return the response
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04118_EXTENDED_SUCCESSFUL, response ) );
                }
            }
            else
            {
                // We have had an error
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04117_EXTENDED_FAILED, response ) );
                }
            }

            // Get back the response. It's still an opaque response
            if ( Strings.isEmpty( response.getResponseName() ) )
            {
                response.setResponseName( extendedRequest.getRequestName() );
            }

            // Decode the payload now
            return response;
        }
        catch ( Exception ie )
        {
            if ( ie instanceof LdapException )
            {
                throw ( LdapException ) ie;
            }

            // Catch all other exceptions
            LOG.error( NO_RESPONSE_ERROR, ie );

            // Send an abandon request
            if ( !extendedFuture.isCancelled() )
            {
                abandon( extendedRequest.getMessageId() );
            }

            throw new LdapException( NO_RESPONSE_ERROR, ie );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public ExtendedFuture extendedAsync( ExtendedRequest extendedRequest ) throws LdapException
    {
        if ( extendedRequest == null )
        {
            String msg = I18n.err( I18n.ERR_04154_CANNOT_PROCESS_NULL_EXT_REQ );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( msg );
            }
            
            throw new IllegalArgumentException( msg );
        }

        // try to connect, if we aren't already connected.
        connect();

        checkSession();

        int newId = messageId.incrementAndGet();

        extendedRequest.setMessageId( newId );
        ExtendedFuture extendedFuture = new ExtendedFuture( this, newId );
        extendedFuture.setExtendedRequest( extendedRequest );
        addToFutureMap( newId, extendedFuture );

        // Send the request to the server
        writeRequest( extendedRequest );

        // Ok, done return the future
        return extendedFuture;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean exists( String dn ) throws LdapException
    {
        return exists( new Dn( dn ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean exists( Dn dn ) throws LdapException
    {
        try
        {
            Entry entry = lookup( dn, SchemaConstants.NO_ATTRIBUTE_ARRAY );

            return entry != null;
        }
        catch ( LdapNoPermissionException lnpe )
        {
            // Special case to deal with insufficient permissions
            return false;
        }
        catch ( LdapException le )
        {
            throw le;
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry getRootDse() throws LdapException
    {
        return lookup( Dn.ROOT_DSE, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry getRootDse( String... attributes ) throws LdapException
    {
        return lookup( Dn.ROOT_DSE, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( Dn dn ) throws LdapException
    {
        return lookup( dn, SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( String dn ) throws LdapException
    {
        return lookup( dn, SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( Dn dn, String... attributes ) throws LdapException
    {
        return lookup( dn, null, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( Dn dn, Control[] controls, String... attributes ) throws LdapException
    {
        Entry entry = null;

        try
        {
            SearchRequest searchRequest = new SearchRequestImpl();

            searchRequest.setBase( dn );
            searchRequest.setFilter( LdapConstants.OBJECT_CLASS_STAR );
            searchRequest.setScope( SearchScope.OBJECT );
            searchRequest.addAttributes( attributes );
            searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );

            if ( ( controls != null ) && ( controls.length > 0 ) )
            {
                searchRequest.addAllControls( controls );
            }

            try ( Cursor<Response> cursor = search( searchRequest ) )
            {
                // Read the response
                if ( cursor.next() )
                {
                    // cursor will always hold SearchResultEntry objects cause there is no ManageDsaITControl passed with search request
                    entry = ( ( SearchResultEntry ) cursor.get() ).getEntry();
                }
    
                // Pass through the SaerchResultDone, or stop
                // if we have other responses
                cursor.next();
            }
        }
        catch ( CursorException e )
        {
            throw new LdapException( e.getMessage(), e );
        }
        catch ( IOException ioe )
        {
            throw new LdapException( ioe.getMessage(), ioe );
        }

        return entry;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( String dn, String... attributes ) throws LdapException
    {
        return lookup( new Dn( dn ), null, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public Entry lookup( String dn, Control[] controls, String... attributes ) throws LdapException
    {
        return lookup( new Dn( dn ), controls, attributes );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isControlSupported( String controlOID ) throws LdapException
    {
        return getSupportedControls().contains( controlOID );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public List<String> getSupportedControls() throws LdapException
    {
        if ( supportedControls != null )
        {
            return supportedControls;
        }

        if ( rootDse == null )
        {
            fetchRootDSE();
        }

        supportedControls = new ArrayList<>();

        Attribute attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );

        if ( attr == null )
        {
            // Unlikely. Perhaps the server does not respond properly to "+" attribute query
            // (such as 389ds server). So let's try again and let's be more explicit.
            fetchRootDSE( SchemaConstants.ALL_USER_ATTRIBUTES, 
                SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.SUPPORTED_CONTROL_AT );
            attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );
            if ( attr == null )
            {
                return supportedControls;
            }
        }
        
        for ( Value value : attr )
        {
            supportedControls.add( value.getString() );
        }

        return supportedControls;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void loadSchema() throws LdapException
    {
        loadSchema( new DefaultSchemaLoader( this ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void loadSchemaRelaxed() throws LdapException
    {
        loadSchema( new DefaultSchemaLoader( this, true ) );
    }


    /**
     * loads schema using the specified schema loader
     *
     * @param loader the {@link SchemaLoader} to be used to load schema
     * @throws LdapException If the schema loading failed
     */
    public void loadSchema( SchemaLoader loader ) throws LdapException
    {
        try
        {
            SchemaManager tmp = new DefaultSchemaManager( loader );

            tmp.loadAllEnabled();

            if ( !tmp.getErrors().isEmpty() && loader.isStrict() )
            {
                String msg = I18n.err( I18n.ERR_04115_ERROR_LOADING_SCHEMA );
                
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_05114_ERROR_MESSAGE, msg, Strings.listToString( tmp.getErrors() ) ) );
                }
                
                throw new LdapException( msg );
            }

            schemaManager = tmp;

            // Change the container's BinaryDetector
            ioSession.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR,
                new LdapMessageContainer<>( codec,
                    new SchemaBinaryAttributeDetector( schemaManager ) ) );

        }
        catch ( LdapException le )
        {
            throw le;
        }
        catch ( Exception e )
        {
            LOG.error( I18n.err( I18n.ERR_04116_FAIL_LOAD_SCHEMA ), e );
            throw new LdapException( e );
        }
    }


    /**
     * parses the given schema file present in OpenLDAP schema format
     * and adds all the SchemaObjects present in it to the SchemaManager
     *
     * @param schemaFile the schema file in OpenLDAP schema format
     * @throws LdapException in case of any errors while parsing
     */
    public void addSchema( File schemaFile ) throws LdapException
    {
        try
        {
            if ( schemaManager == null )
            {
                loadSchema();
            }
            
            if ( schemaManager == null )
            {
                throw new LdapException( I18n.err( I18n.ERR_04116_FAIL_LOAD_SCHEMA ) );
            }

            OpenLdapSchemaParser olsp = new OpenLdapSchemaParser();
            olsp.setQuirksMode( true );
            olsp.parse( schemaFile );

            Registries registries = schemaManager.getRegistries();

            for ( AttributeType atType : olsp.getAttributeTypes() )
            {
                registries.buildReference( atType );
                registries.getAttributeTypeRegistry().register( atType );
            }

            for ( ObjectClass oc : olsp.getObjectClasses() )
            {
                registries.buildReference( oc );
                registries.getObjectClassRegistry().register( oc );
            }

            if ( LOG.isInfoEnabled() )
            {
                LOG.info( I18n.msg( I18n.MSG_04167_SCHEMA_LOADED_SUCCESSFULLY, schemaFile.getAbsolutePath() ) );
            }
        }
        catch ( Exception e )
        {
            LOG.error( I18n.err( I18n.ERR_04117_FAIL_LOAD_SCHEMA_FILE, schemaFile.getAbsolutePath() ) );
            throw new LdapException( e );
        }
    }


    /**
     * @see #addSchema(File)
     * @param schemaFileName The schema file name to add
     * @throws LdapException If the schema addition failed
     */
    public void addSchema( String schemaFileName ) throws LdapException
    {
        addSchema( new File( schemaFileName ) );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public LdapApiService getCodecService()
    {
        return codec;
    }


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


    /**
     * fetches the rootDSE from the server
     * 
     * @param explicitAttributes The list of requested attributes
     * @throws LdapException If we weren't bale to fetch the RootDSE
     */
    private void fetchRootDSE( String... explicitAttributes ) throws LdapException
    {
        EntryCursor cursor = null;

        String[] attributes = explicitAttributes;
        if ( attributes.length == 0 )
        {
            attributes = new String[]
                { SchemaConstants.ALL_USER_ATTRIBUTES, SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES };
        }
        
        try
        {
            cursor = search( "", LdapConstants.OBJECT_CLASS_STAR, SearchScope.OBJECT, attributes );
            if ( cursor.next() )
            {
                rootDse = cursor.get();
                // We have to call cursor.next() here, as we need to make sure that the "done" status of the cursor
                // is properly updated. Otherwise the subsequent cursor.close() initiates an ABANDON operation to
                // stop the search, which is in fact finished already.
                cursor.next();
            }
            else
            {
                throw new LdapException( I18n.err( I18n.ERR_04155_ROOT_DSE_SEARCH_FAILED ) );
            }
        }
        catch ( Exception e )
        {
            String msg = I18n.err( I18n.ERR_04156_FAILED_FETCHING_ROOT_DSE );
            LOG.error( msg );
            throw new LdapException( msg, e );
        }
        finally
        {
            if ( cursor != null )
            {
                try
                {
                    cursor.close();
                }
                catch ( Exception e )
                {
                    LOG.error( I18n.err( I18n.ERR_04114_CURSOR_CLOSE_FAIL ), e );
                }
            }
        }
    }


    /**
     * gives the configuration information of the connection
     *
     * @return the configuration of the connection
     */
    @Override
    public LdapConnectionConfig getConfig()
    {
        return config;
    }


    /**
     * removes the Objects associated with the given message ID
     * from future and response queue maps
     *
     * @param msgId id of the message
     */
    private void removeFromFutureMaps( int msgId )
    {
        getFromFutureMap( msgId );
    }


    /**
     * clears the async listener, responseQueue and future mapppings to the corresponding request IDs
     */
    private void clearMaps()
    {
        futureMap.clear();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRequestCompleted( int messageId )
    {
        ResponseFuture<?> responseFuture = futureMap.get( messageId );
        
        return responseFuture == null;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public boolean doesFutureExistFor( int messageId )
    {
        ResponseFuture<?> responseFuture = futureMap.get( messageId );
        return responseFuture != null;
    }


    /**
     * Adds the connection closed event listener.
     *
     * @param ccListener the connection closed listener
     */
    public void addConnectionClosedEventListener( ConnectionClosedEventListener ccListener )
    {
        if ( conCloseListeners == null )
        {
            conCloseListeners = new ArrayList<>();
        }

        conCloseListeners.add( ccListener );
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void inputClosed( IoSession session ) throws Exception 
    {
        session.closeNow();
    }


    /**
     * This method is called when a new session is created. We will store some
     * informations that the session will need to process incoming requests.
     * 
     * @param session the newly created session
     */
    @Override
    public void sessionCreated( IoSession session ) throws Exception
    {
        // Last, store the message container
        LdapMessageContainer<Message> ldapMessageContainer =
            new LdapMessageContainer<>(
                codec, config.getBinaryAttributeDetector() );

        session.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR, ldapMessageContainer );
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void sessionClosed( IoSession session ) throws Exception
    {
        authenticated.set( false );
        
        // Close all the Future for this session
        for ( ResponseFuture<? extends Response> responseFuture : futureMap.values() )
        {
            responseFuture.cancel();
        }

        // clear the mappings
        clearMaps();

        // Last, not least, reset the MessageId value
        messageId.set( 0 );

        connectorMutex.lock();

        try
        {
            if ( connector != null )
            {
                connector.dispose();
                connector = null;
            }
        }
        finally
        {
            connectorMutex.unlock();
        }

        if ( conCloseListeners != null )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04136_NOTIFYING_CLOSE_LISTENERS ) );
            }

            for ( ConnectionClosedEventListener listener : conCloseListeners )
            {
                listener.connectionClosed();
            }
        }
        
        connectionCloseFuture.complete( 0 );
    }


    /**
     * Sends the StartTLS extended request to server and adds a security layer
     * upon receiving a response with successful result. Note that we will use
     * the default LDAP connection.
     *
     * @throws LdapException If the StartTLS operation failed
     */
    public void startTls() throws LdapException
    {
        try
        {
            if ( config.isUseSsl() )
            {
                throw new LdapException( I18n.err( I18n.ERR_04157_CANNOT_USE_TLS_WITH_SSL_FLAG ) );
            }

            // try to connect, if we aren't already connected.
            connect();

            checkSession();
            
            if ( ioSession.isSecured() )
            {
                if ( LOG.isDebugEnabled() )
                { 
                    LOG.debug( I18n.msg( I18n.MSG_04121_LDAP_ALREADY_USING_START_TLS ) );
                }
                
                return;
            }

            ExtendedResponse resp = extended( new StartTlsRequestImpl() );
            LdapResult result = resp.getLdapResult();

            if ( result.getResultCode() == ResultCodeEnum.SUCCESS )
            {
                addSslFilter();
            }
            else
            {
                throw new LdapOperationException( result.getResultCode(), result.getDiagnosticMessage() );
            }
        }
        catch ( LdapException e )
        {
            throw e;
        }
        catch ( Exception e )
        {
            throw new LdapException( e );
        }
    }


    /**
     * Adds {@link SslFilter} to the IOConnector or IOSession's filter chain
     * 
     * @throws LdapException If the SSL filter addition failed
     */
    private void addSslFilter() throws LdapException
    {
        try
        {
            SSLContext sslContext = SSLContext.getInstance( config.getSslProtocol() );
            
            sslContext.init( config.getKeyManagers(), config.getTrustManagers(), config.getSecureRandom() );

            SslFilter sslFilter = new SslFilter( sslContext );
            sslFilter.setUseClientMode( true );

            // Configure the enabled cipher lists
            String[] enabledCipherSuite = config.getEnabledCipherSuites();

            if ( ( enabledCipherSuite != null ) && ( enabledCipherSuite.length != 0 ) )
            {
                sslFilter.setEnabledCipherSuites( enabledCipherSuite );
            }

            // Be sure we disable SSLV3
            String[] enabledProtocols = config.getEnabledProtocols();

            if ( ( enabledProtocols != null ) && ( enabledProtocols.length != 0 ) )
            {
                sslFilter.setEnabledProtocols( enabledProtocols );
            }
            else
            {
                // Default to TLS
                sslFilter.setEnabledProtocols( new String[]
                    { "TLSv1", "TLSv1.1", "TLSv1.2" } );
            }

            // for LDAPS/TLS
            handshakeFuture = new HandshakeFuture();
            
            if ( ( ioSession == null ) || !isConnected() )
            {
                connector.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
            }
            else
            // for StartTLS
            {
                ioSession.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
                
                boolean isSecured = handshakeFuture.get( timeout, TimeUnit.MILLISECONDS );
                
                if ( !isSecured )
                {
                    Throwable cause = ( Throwable ) ioSession.getAttribute( EXCEPTION_KEY );
                    throw new LdapTlsHandshakeException( I18n.err( I18n.ERR_04120_TLS_HANDSHAKE_ERROR ), cause );
                }
            }
        }
        catch ( Exception e )
        {
            if ( e instanceof LdapException )
            {
                throw ( LdapException ) e;
            }

            String msg = I18n.err( I18n.ERR_04122_SSL_CONTEXT_INIT_FAILURE );
            LOG.error( msg, e );
            throw new LdapException( msg, e );
        }
    }


    /**
     * Process the SASL Bind. It's a dialog with the server, we will send a first BindRequest, receive
     * a response and the, if this response is a challenge, continue by sending a new BindRequest with
     * the requested informations.
     *
     * @param saslRequest The SASL request object containing all the needed parameters
     * @return A {@link BindResponse} containing the result
     * @throws LdapException if some error occurred
     */
    public BindFuture bindSasl( SaslRequest saslRequest ) throws LdapException
    {
        // First switch to anonymous state
        authenticated.set( false );

        // try to connect, if we aren't already connected.
        connect();

        // If the session has not been establish, or is closed, we get out immediately
        checkSession();

        BindRequest bindRequest = createBindRequest( ( String ) null, null,
            saslRequest.getSaslMechanism(), saslRequest.getControls() );

        // Update the messageId
        int newId = messageId.incrementAndGet();
        bindRequest.setMessageId( newId );

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, bindRequest ) );
        }

        // Create a future for this Bind operation
        BindFuture bindFuture = new BindFuture( this, newId );

        // Store it in the future Map
        addToFutureMap( newId, bindFuture );

        try
        {
            BindResponse bindResponse;
            byte[] response;
            ResultCodeEnum result;

            // Creating a map for SASL properties
            Map<String, Object> properties = new HashMap<>();

            // Quality of Protection SASL property
            if ( saslRequest.getQualityOfProtection() != null )
            {
                properties.put( Sasl.QOP, saslRequest.getQualityOfProtection().getValue() );
            }

            // Security Strength SASL property
            if ( saslRequest.getSecurityStrength() != null )
            {
                properties.put( Sasl.STRENGTH, saslRequest.getSecurityStrength().getValue() );
            }

            // Mutual Authentication SASL property
            if ( saslRequest.isMutualAuthentication() )
            {
                properties.put( Sasl.SERVER_AUTH, "true" );
            }

            // Creating a SASL Client
            SaslClient sc = Sasl.createSaslClient(
                new String[]
                    { bindRequest.getSaslMechanism() },
                saslRequest.getAuthorizationId(),
                "ldap",
                config.getLdapHost(),
                properties,
                new SaslCallbackHandler( saslRequest ) );

            // If the SaslClient wasn't created, that means we can't create the SASL client
            // for the requested mechanism. We then produce an Exception
            if ( sc == null )
            {
                String message = I18n.err( I18n.ERR_04158_CANNOT_FIND_SASL_FACTORY_FOR_MECH, bindRequest.getSaslMechanism() );
                LOG.error( message );
                throw new LdapException( message );
            }

            // Corner case : the SASL mech might send an initial challenge, and we have to
            // deal with it immediately.
            if ( sc.hasInitialResponse() )
            {
                byte[] challengeResponse = sc.evaluateChallenge( Strings.EMPTY_BYTES );

                // Stores the challenge's response, and send it to the server
                bindRequest.setCredentials( challengeResponse );
                writeRequest( bindRequest );

                // Get the server's response, blocking
                bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

                if ( bindResponse == null )
                {
                    // We didn't received anything : this is an error
                    if ( LOG.isErrorEnabled() )
                    { 
                        LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                    }
                    
                    throw new LdapException( TIME_OUT_ERROR );
                }

                result = bindResponse.getLdapResult().getResultCode();
            }
            else
            {
                // Copy the bindRequest without setting the credentials
                BindRequest bindRequestCopy = new BindRequestImpl();
                bindRequestCopy.setMessageId( newId );

                bindRequestCopy.setName( bindRequest.getName() );
                bindRequestCopy.setSaslMechanism( bindRequest.getSaslMechanism() );
                bindRequestCopy.setSimple( bindRequest.isSimple() );
                bindRequestCopy.setVersion3( bindRequest.getVersion3() );
                bindRequestCopy.addAllControls( bindRequest.getControls().values().toArray( new Control[0] ) );

                writeRequest( bindRequestCopy );

                bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

                if ( bindResponse == null )
                {
                    // We didn't received anything : this is an error
                    if ( LOG.isErrorEnabled() )
                    {
                        LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                    }
                    
                    throw new LdapException( TIME_OUT_ERROR );
                }

                result = bindResponse.getLdapResult().getResultCode();
            }

            while ( !sc.isComplete()
                && ( ( result == ResultCodeEnum.SASL_BIND_IN_PROGRESS ) || ( result == ResultCodeEnum.SUCCESS ) ) )
            {
                response = sc.evaluateChallenge( bindResponse.getServerSaslCreds() );

                if ( result == ResultCodeEnum.SUCCESS )
                {
                    if ( response != null )
                    {
                        throw new LdapException( I18n.err( I18n.ERR_04159_PROTOCOL_ERROR ) );
                    }
                }
                else
                {
                    newId = messageId.incrementAndGet();
                    bindRequest.setMessageId( newId );
                    bindRequest.setCredentials( response );

                    addToFutureMap( newId, bindFuture );

                    writeRequest( bindRequest );

                    bindResponse = bindFuture.get( timeout, TimeUnit.MILLISECONDS );

                    if ( bindResponse == null )
                    {
                        // We didn't received anything : this is an error
                        if ( LOG.isErrorEnabled() )
                        {
                            LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
                        }
                        
                        throw new LdapException( TIME_OUT_ERROR );
                    }

                    result = bindResponse.getLdapResult().getResultCode();
                }
            }

            bindFuture.set( bindResponse );

            return bindFuture;
        }
        catch ( LdapException e )
        {
            throw e;
        }
        catch ( Exception e )
        {
            LOG.error( e.getMessage() );
            throw new LdapException( e );
        }
    }


    /**
     * A reusable code block to be used in various bind methods
     * 
     * @param request The request to send
     * @throws LdapException If the request was ot properly sent
     */
    private void writeRequest( Request request ) throws LdapException
    {
        // Send the request to the server
        WriteFuture writeFuture = ioSession.write( request );

        long localTimeout = timeout;

        while ( localTimeout > 0 )
        {
            // Wait only 100 ms
            boolean done = writeFuture.awaitUninterruptibly( 100 );

            if ( done )
            {
                return;
            }

            // Wait for the message to be sent to the server
            if ( !ioSession.isConnected() )
            {
                // We didn't received anything : this is an error
                if ( LOG.isErrorEnabled() )
                {
                    LOG.error( I18n.err( I18n.ERR_04118_SOMETHING_WRONG_HAPPENED ) );
                }

                Exception exception = ( Exception ) ioSession.removeAttribute( EXCEPTION_KEY );

                if ( exception instanceof LdapException )
                {
                    throw ( LdapException ) exception;
                }
                else if ( exception != null )
                {
                    throw new InvalidConnectionException( exception.getMessage(), exception );
                }

                throw new InvalidConnectionException( I18n.err( I18n.ERR_04160_SESSION_HAS_BEEN_CLOSED ) );
            }

            localTimeout -= 100;
        }

        if ( LOG.isErrorEnabled() )
        {
            LOG.error( I18n.err( I18n.ERR_04119_TIMEOUT ) );
        }
        
        throw new LdapException( TIME_OUT_ERROR );
    }


    /**
     * method to write the kerberos config in the standard MIT kerberos format
     *
     * This is required cause the JGSS api is not able to recognize the port value set
     * in the system property java.security.krb5.kdc this issue makes it impossible
     * to set a kdc running non standard ports (other than 88)
     *
     * e.g localhost:6088
     *
     * <pre>
     * [libdefaults]
     *     default_realm = EXAMPLE.COM
     *
     * [realms]
     *     EXAMPLE.COM = {
     *         kdc = localhost:6088
     *     }
     * </pre>
     *
     * @param realmName The realm name
     * @param kdcHost The Kerberos server host
     * @param kdcPort The Kerberos server port
     * @return the full path of the config file
     * @throws IOException If the config file cannot be created
     */
    private String createKrb5ConfFile( String realmName, String kdcHost, int kdcPort ) throws IOException
    {
        StringBuilder sb = new StringBuilder();

        sb.append( "[libdefaults]" )
            .append( "\n\t" );
        sb.append( "default_realm = " )
            .append( realmName )
            .append( "\n" );

        sb.append( "[realms]" )
            .append( "\n\t" );

        sb.append( realmName )
            .append( " = {" )
            .append( "\n\t\t" );
        sb.append( "kdc = " )
            .append( kdcHost )
            .append( ":" )
            .append( kdcPort )
            .append( "\n\t}\n" );

        File krb5Conf = Files.createTempFile( "client-api-krb5", ".conf" ).toFile();
        krb5Conf.deleteOnExit();

        try ( Writer writer = new OutputStreamWriter( Files.newOutputStream( Paths.get( krb5Conf.getPath() ) ), 
            Charset.defaultCharset() ) )
        {
            writer.write( sb.toString() );
        }

        String krb5ConfPath = krb5Conf.getAbsolutePath();

        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04135_KRB5_FILE_CREATED, krb5ConfPath ) );
        }

        return krb5ConfPath;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public BinaryAttributeDetector getBinaryAttributeDetector()
    {
        if ( config != null )
        {
            return config.getBinaryAttributeDetector();
        }
        else
        {
            return null;
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetector )
    {
        if ( config != null )
        {
            config.setBinaryAttributeDetector( binaryAttributeDetector );
        }
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setSchemaManager( SchemaManager schemaManager )
    {
        this.schemaManager = schemaManager;
    }


    /**
     * @return the socketSessionConfig
     */
    public SocketSessionConfig getSocketSessionConfig()
    {
        return socketSessionConfig;
    }


    /**
     * @param socketSessionConfig the socketSessionConfig to set
     */
    public void setSocketSessionConfig( SocketSessionConfig socketSessionConfig )
    {
        this.socketSessionConfig = socketSessionConfig;
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void event( IoSession session, FilterEvent event ) throws Exception 
    {
        // Check if it's a SSLevent 
        if ( ( event instanceof SslEvent ) && ( ( SslEvent ) event == SslEvent.SECURED ) )
        {
            handshakeFuture.secured();
        }
    }
}
