001/*
002 *   Licensed to the Apache Software Foundation (ASF) under one
003 *   or more contributor license agreements.  See the NOTICE file
004 *   distributed with this work for additional information
005 *   regarding copyright ownership.  The ASF licenses this file
006 *   to you under the Apache License, Version 2.0 (the
007 *   "License"); you may not use this file except in compliance
008 *   with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *   Unless required by applicable law or agreed to in writing,
013 *   software distributed under the License is distributed on an
014 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *   KIND, either express or implied.  See the License for the
016 *   specific language governing permissions and limitations
017 *   under the License.
018 *
019 */
020
021package org.apache.directory.ldap.client.api;
022
023
024import java.io.IOException;
025
026import org.apache.commons.pool.PoolableObjectFactory;
027import org.apache.directory.api.ldap.codec.api.LdapApiService;
028import org.apache.directory.api.ldap.model.constants.SchemaConstants;
029import org.apache.directory.api.ldap.model.exception.LdapException;
030import org.apache.directory.api.ldap.model.name.Dn;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034
035/**
036 * A factory for creating LdapConnection objects managed by LdapConnectionPool.
037 * 
038 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
039 */
040public class PoolableLdapConnectionFactory implements PoolableObjectFactory<LdapConnection>
041{
042    private static final Logger LOG = LoggerFactory.getLogger( PoolableLdapConnectionFactory.class );
043
044    private LdapConnectionFactory connectionFactory;
045
046
047    /**
048     * Creates a new instance of PoolableLdapConnectionFactory.
049     *
050     * @param config the configuration for creating LdapConnections
051     */
052    public PoolableLdapConnectionFactory( LdapConnectionConfig config )
053    {
054        this( new DefaultLdapConnectionFactory( config ) );
055    }
056
057
058    /**
059     * Creates a new instance of PoolableLdapConnectionFactory.
060     *
061     * @param connectionFactory the connection factory for creating LdapConnections
062     */
063    public PoolableLdapConnectionFactory( LdapConnectionFactory connectionFactory )
064    {
065        this.connectionFactory = connectionFactory;
066    }
067
068
069    /**
070     * {@inheritDoc}
071     */
072    public void activateObject( LdapConnection connection )
073    {
074        LOG.debug( "Activating {}", connection );
075    }
076
077
078    /**
079     * {@inheritDoc}
080     */
081    public void destroyObject( LdapConnection connection ) 
082    {
083        LOG.debug( "Destroying {}", connection );
084        try {
085            connection.unBind();
086        }
087        catch ( LdapException e ) {
088            LOG.error( "unable to unbind connection: {}", e.getMessage() );
089            LOG.debug( "unable to unbind connection:", e );
090        }
091
092        try {
093            connection.close();
094        }
095        catch ( IOException e ) {
096            LOG.error( "unable to close connection: {}", e.getMessage() );
097            LOG.debug( "unable to close connection:", e );
098        }
099    }
100
101
102    /**
103     * Returns the LdapApiService instance used by this factory.
104     *
105     * @return The LdapApiService instance used by this factory
106     */
107    public LdapApiService getLdapApiService()
108    {
109        return connectionFactory.getLdapApiService();
110    }
111
112
113    /**
114     * {@inheritDoc}
115     * @throws LdapException If unable to connect.
116     */
117    public LdapConnection makeObject() throws LdapException
118    {
119        LOG.debug( "Creating a LDAP connection" );
120        return connectionFactory.newLdapConnection();
121    }
122
123
124    /**
125     * {@inheritDoc}
126     * @throws LdapException If unable to reconfigure and rebind.
127     */
128    public void passivateObject( LdapConnection connection ) throws LdapException
129    {
130        LOG.debug( "Passivating {}", connection );
131        
132        // in case connection configuration was modified, or rebound to a
133        // different identity, we reinitialize before returning to the pool.
134        connectionFactory.bindConnection( 
135            connectionFactory.configureConnection( connection ) );
136    }
137
138
139    /**
140     * {@inheritDoc}
141     */
142    public boolean validateObject( LdapConnection connection )
143    {
144        LOG.debug( "Validating {}", connection );
145
146        if ( connection.isConnected() )
147        {
148            try
149            {
150                return connection.lookup( Dn.ROOT_DSE, SchemaConstants.NO_ATTRIBUTE ) != null;
151            }
152            catch ( LdapException le )
153            {
154                return false;
155            }
156        }
157        else
158        {
159            return false;
160        }
161    }
162}