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

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.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.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 final LdapConnectionConfig config;
    
    /** The Socket configuration */
    private SocketSessionConfig socketSessionConfig;

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

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

    /** a map to hold the ResponseFutures for all operations */
    private final 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 final 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;

    // ~~~~~~~~~~~~~~~~~ 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 ( ldapSession != null ) && ldapSession.isConnected() && !ldapSession.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() && ldapSession.isSecured();
    }

    
    /**
     * 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 ( ldapSession == 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. 
     */
    private ConnectFuture tryConnect() throws LdapException
    {
        // Build the connection address
        SocketAddress address = new InetSocketAddress( config.getLdapHost(), config.getLdapPort() );
        long maxRetry = System.currentTimeMillis() + timeout;
        ConnectFuture connectionFuture = connector.connect( address );
        boolean result = false;

        while ( maxRetry > System.currentTimeMillis() )
        {
            // 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 );
            }
            finally
            {
                if ( result )
                {
                    boolean isConnected = connectionFuture.isConnected();
    
                    if ( !isConnected )
                    {
                        Throwable connectionException = connectionFuture.getException();
    
                        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_04143_CONNECTION_RETRYING ) );
                        }
    
                        // Wait 500 ms and retry
                        try
                        {
                            Thread.sleep( 500 );
                        }
                        catch ( InterruptedException e )
                        {
                            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 );
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        
        if ( connectionFuture == null )
        {
            connector.dispose();
            throw new InvalidConnectionException( I18n.err( I18n.ERR_04109_CANNOT_CONNECT ) );
        }

        return connectionFuture;
    }
    
    
    /**
     * Close the connection and generate the appropriate exception
     */
    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
     */
    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 );
                }

                // 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
     */
    private void setCloseListener( ConnectFuture connectionFuture )
    {
        // Get the close future for this session
        CloseFuture closeFuture = connectionFuture.getSession().getCloseFuture();
        
        closeFuture.addListener( future -> 
        {
            synchronized ( LdapNetworkConnection.this )
            {
                // DIRAPI-342: Skip processing if LDAP session changed, i.e. after re-connect.
                if ( future.getSession() != ldapSession )
                {
                    return;
                }

                // 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_04134_CLOSING, responseFuture ) );
                    }

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

            ldapSession.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;
        }

        // 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() )
        {
            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
        ldapSession = connectionFuture.getSession();

        // Store the container into the session if we don't have one
        setBinaryDetector();

        // Initialize the MessageId
        messageId.set( 0 );

        // And return
        return true;
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void close()
    {
        if ( !isConnected() )
        {
            return;
        }

        // Close the session
        ldapSession.closeNow().awaitUninterruptibly( timeout );
        ldapSession = null;

        clearMaps();

        // And close the connector if it has been created locally
        // Release the connector

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

        // Reset the messageId
        messageId.set( 0 );

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

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


    //------------------------ 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
        ldapSession.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 )
        {
            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 = ldapSession.write( unbindRequest );

        unbindFuture.awaitUninterruptibly( timeout );

        authenticated.set( false );

        // Close all the Future for this session
        for ( ResponseFuture<? extends Response> responseFuture : futureMap.values() )
        {
            responseFuture.cancel();
        }

        //  We now have to close the session
        close();

        // 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
    {
        String treeDeleteOid = "1.2.840.113556.1.4.805";

        if ( isControlSupported( treeDeleteOid ) )
        {
            DeleteRequest deleteRequest = new DeleteRequestImpl();
            deleteRequest.setName( dn );
            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 );
        }
    }


    /**
     * 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_USER_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
            ldapSession.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();
            }
            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 synchronized void sessionClosed( IoSession session ) throws Exception
    {
        // DIRAPI-342: Skip processing if LDAP session changed, i.e. after re-connect.
        if ( session != ldapSession )
        {
            return;
        }

        // no need to handle if this session was closed by the user
        if ( !isConnected() )
        {
            return;
        }

        close();
    }


    /**
     * 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 ( ldapSession.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() );
            
            TrustManager[] trustManagers = config.getTrustManagers();
            
            if ( ( trustManagers == null ) || ( trustManagers.length == 0 ) )
            {
                trustManagers = new TrustManager[] { new NoVerificationTrustManager() };
            }
            
            sslContext.init( config.getKeyManagers(), trustManagers, 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 ( !isConnected() )
            {
                connector.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
            }
            else
            // for StartTLS
            {
                ldapSession.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
                
                boolean isSecured = handshakeFuture.get( timeout, TimeUnit.MILLISECONDS );
                
                if ( !isSecured )
                {
                    Throwable cause = ( Throwable ) ldapSession.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 = ldapSession.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 ( !ldapSession.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 ) ldapSession.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 = File.createTempFile( "client-api-krb5", ".conf" );
        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();
        }
    }
}
