/*
 *   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 java.lang.reflect.Constructor;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An abstract class implementing the PoolableObjectFactory, for LdapConnections.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public abstract class AbstractPoolableLdapConnectionFactory implements PooledObjectFactory<LdapConnection>
{
    /** This class logger */
    private static final Logger LOG = LoggerFactory.getLogger( AbstractPoolableLdapConnectionFactory.class );

    /** The factory to use to create a new connection */
    protected LdapConnectionFactory connectionFactory;

    /** The validator to use */
    protected LdapConnectionValidator validator = new LookupLdapConnectionValidator();

    /**
     * {@inheritDoc}
     * 
     * There is nothing to do to activate a connection.
     */
    @Override
    public void activateObject( PooledObject<LdapConnection> connection ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04146_ACTIVATING, connection ) );
        }
        
        if ( !connection.getObject().isConnected() || !connection.getObject().isAuthenticated() )
        {
            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04147_REBIND_CONNECTION_DROPPED, connection ) );
            }
            
            connectionFactory.bindConnection( connection.getObject() );
        }
    }


    /**
     * {@inheritDoc}
     * 
     * Destroying a connection will unbind it which will result on a shutdown
     * of teh underlying protocol.
     */
    @Override
    public void destroyObject( PooledObject<LdapConnection> connection ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04148_DESTROYING, connection ) );
        }

        try
        {
            // https://tools.ietf.org/html/rfc2251#section-4.3
            // unbind closes the connection so no need to close
            connection.getObject().unBind();
        }
        catch ( LdapException e )
        {
            LOG.error( I18n.err( I18n.ERR_04100_UNABLE_TO_UNBIND, e.getMessage() ) );

            if ( LOG.isDebugEnabled() )
            {
                LOG.debug( I18n.msg( I18n.MSG_04149_UNABLE_TO_UNBIND, e.getMessage() ) );
            }
        }
    }


    /**
     * Returns the LdapApiService instance used by this factory.
     *
     * @return The LdapApiService instance used by this factory
     */
    public LdapApiService getLdapApiService()
    {
        return connectionFactory.getLdapApiService();
    }


    /**
     * {@inheritDoc}
     * Specifically, we are creating a new connection based on the LdapConnection Factory
     * we used to create this pool of connections. The default is to create bound connections.
     * 
     * @throws LdapException If unable to connect.
     */
    @Override
    public PooledObject<LdapConnection> makeObject() throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04150_CREATING_LDAP_CONNECTION ) );
        }
        
        return new DefaultPooledObject<>( connectionFactory.newLdapConnection() );
    }


    protected static LdapConnectionFactory newLdapConnectionFactory(
        LdapConnectionConfig config,
        Class<? extends LdapConnectionFactory> connectionFactoryClass )
    {
        try
        {
            Constructor<? extends LdapConnectionFactory> constructor =
                connectionFactoryClass.getConstructor( LdapConnectionConfig.class );
            return constructor.newInstance( config );
        }
        catch ( Exception e )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_04101_CANNOT_CREATE_LDAP_CONNECTION_FACTORY, e.getMessage(), e ) );
        }
    }


    /**
     * {@inheritDoc}
     * 
     * We don't do anything with the connection. It remains in the state it was before
     * being used.
     * 
     * @throws LdapException If unable to reconfigure and rebind.
     */
    @Override
    public void passivateObject( PooledObject<LdapConnection> connection ) throws LdapException
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04151_PASSIVATING, connection ) );
        }
    }
  
    
    /**
     * Sets the validator to use when validation occurs.  Note that validation
     * will only occur if the connection pool was configured to validate.  This
     * means one of:
     * <ul>
     * <li>{@link org.apache.commons.pool2.impl.GenericObjectPool#setTestOnBorrow setTestOnBorrow}</li>
     * <li>{@link org.apache.commons.pool2.impl.GenericObjectPool#setTestWhileIdle setTestWhileIdle}</li>
     * <li>{@link org.apache.commons.pool2.impl.GenericObjectPool#setTestOnReturn setTestOnReturn}</li>
     * </ul>
     * must have been set to true on the pool.  The default validator is 
     * {@link LookupLdapConnectionValidator}.
     *
     * @param validator The validator
     */
    public void setValidator( LdapConnectionValidator validator ) 
    {
        this.validator = validator;
    }


    /**
     * {@inheritDoc}
     * 
     * Validating a connection is done by checking the connection status.
     */
    @Override
    public boolean validateObject( PooledObject<LdapConnection> connection )
    {
        if ( LOG.isDebugEnabled() )
        {
            LOG.debug( I18n.msg( I18n.MSG_04152_VALIDATING, connection ) );
        }
        
        return validator.validate( connection.getObject() );
    }
}
