All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.avalon.excalibur.datasource.JdbcConnectionFactory Maven / Gradle / Ivy

/* 
 * 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.avalon.excalibur.datasource;

import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;

import org.apache.avalon.excalibur.pool.ObjectFactory;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;

/**
 * The Factory implementation for JdbcConnections.
 *
 * @author Avalon Development Team
 * @version CVS $Revision: 1.4 $ $Date: 2004/02/28 11:47:14 $
 * @since 4.0
 */
public class JdbcConnectionFactory extends AbstractLogEnabled implements ObjectFactory
{
    private final String m_dburl;
    private final String m_username;
    private final String m_password;
    private final boolean m_autoCommit;
    private final String m_keepAlive;
    private final int m_keepAliveAge;
    private final String m_connectionClass;
    private Class m_class;
    private static final String DEFAULT_KEEPALIVE = "SELECT 1";
    private static final String ORACLE_KEEPALIVE = JdbcConnectionFactory.DEFAULT_KEEPALIVE + " FROM DUAL";
    private Connection m_firstConnection;

    /**
     * @deprecated  Use the new constructor with the keepalive and connectionClass
     *              specified.
     */
    public JdbcConnectionFactory( final String url,
                                  final String username,
                                  final String password,
                                  final boolean autoCommit,
                                  final boolean oradb )
    {
        this( url, username, password, autoCommit, oradb, null );
    }

    /**
     * @deprecated Use the new constructor with the keepalive and connectionClass
     *             specified.
     */
    public JdbcConnectionFactory( final String url,
                                  final String username,
                                  final String password,
                                  final boolean autoCommit,
                                  final boolean oradb,
                                  final String connectionClass )
    {
        this( url, username, password, autoCommit, ( oradb ) ? JdbcConnectionFactory.ORACLE_KEEPALIVE : JdbcConnectionFactory.DEFAULT_KEEPALIVE, connectionClass );
    }

    /**
     * Creates and configures a new JdbcConnectionFactory.
     *
     * @param url full JDBC database url.
     * @param username username to use when connecting to the database.
     * @param password password to use when connecting to the database.
     * @param autoCommit true if connections to the database should operate with auto commit
     *                   enabled.
     * @param keepAlive a query which will be used to check the statis of a connection after it
     *                  has been idle.  A null value will cause the keep alive feature to
     *                  be disabled.
     * @param connectionClass class of connections created by the factory.
     */
    public JdbcConnectionFactory( final String url,
                                  final String username,
                                  final String password,
                                  final boolean autoCommit,
                                  final String keepAlive,
                                  final String connectionClass )
    {
        this( url, username, password, autoCommit, keepAlive, 5000, connectionClass );
    }

    /**
     * Creates and configures a new JdbcConnectionFactory.
     *
     * @param url full JDBC database url.
     * @param username username to use when connecting to the database.
     * @param password password to use when connecting to the database.
     * @param autoCommit true if connections to the database should operate with auto commit
     *                   enabled.
     * @param keepAlive a query which will be used to check the statis of a connection after it
     *                  has been idle.  A null value will cause the keep alive feature to
     *                  be disabled.
     * @param keepAliveAge the maximum age in milliseconds since a connection was last
     *                     used before it must be pinged using the keepAlive query.  Ignored
     *                     if keepAlive is null.
     * @param connectionClass class of connections created by the factory.
     */
    public JdbcConnectionFactory( final String url,
                                  final String username,
                                  final String password,
                                  final boolean autoCommit,
                                  final String keepAlive,
                                  final int keepAliveAge,
                                  final String connectionClass )
    {
        this.m_dburl = url;
        this.m_username = username;
        this.m_password = password;
        this.m_autoCommit = autoCommit;
        this.m_keepAlive = keepAlive;
        this.m_keepAliveAge = keepAliveAge;
        this.m_connectionClass = connectionClass;

        try
        {
            if( null == m_username )
            {
                m_firstConnection = DriverManager.getConnection( m_dburl );
            }
            else
            {
                m_firstConnection = DriverManager.getConnection( m_dburl, m_username, m_password );
            }

            init();
        }
        catch( Exception e )
        {
            // ignore for now
            // No logger here, so we can't log this.  Really should output something here though
            //  as it can be a real pain to track down the cause when this happens.
            //System.out.println( "Unable to get specified connection class: " + e );
        }
    }

    private void init() throws Exception
    {
        String className = m_connectionClass;
        if( null == className )
        {
            m_class = AbstractJdbcConnection.class;
        }
        else
        {
            m_class = Thread.currentThread().getContextClassLoader().loadClass( className );
        }
    }

    public Object newInstance() throws Exception
    {
        Connection jdbcConnection = null;
        Connection connection = m_firstConnection;

        if( null == connection )
        {
            if( null == m_username )
            {
                connection = DriverManager.getConnection( m_dburl );
            }
            else
            {
                connection = DriverManager.getConnection( m_dburl, m_username, m_password );
            }
        }
        else
        {
            m_firstConnection = null;
        }

        if( null == this.m_class )
        {
            try
            {
                init();
            }
            catch( Exception e )
            {
                if( getLogger().isDebugEnabled() )
                {
                    getLogger().debug( "Exception in JdbcConnectionFactory.newInstance:", e );
                }
                throw new NoValidConnectionException( "No valid JdbcConnection class available" );
            }
        }

        try
        {
            jdbcConnection = getProxy( connection, this.m_keepAlive, this.m_keepAliveAge );
        }
        catch( Exception e )
        {
            if( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "Exception in JdbcConnectionFactory.newInstance:", e );
            }

            throw new NoValidConnectionException( e.getMessage() );
        }

        ContainerUtil.enableLogging( jdbcConnection, getLogger().getChildLogger( "conn" ) );

        // Not all drivers are friendly to explicitly setting autocommit
        if( jdbcConnection.getAutoCommit() != m_autoCommit )
        {
            jdbcConnection.setAutoCommit( m_autoCommit );
        }

        if( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "JdbcConnection object created" );
        }

        return jdbcConnection;
    }

    public Class getCreatedClass()
    {
        return m_class;
    }

    public void decommission( Object object ) throws Exception
    {
        if( object instanceof Disposable )
        {
            ( (Disposable)object ).dispose();

            if( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "JdbcConnection object disposed" );
            }
        }
    }

    private Connection getProxy( Connection conn, String keepAlive, int keepAliveAge )
    {
        ProxiedJdbcConnection handler = null;

        try
        {
            Constructor builder = m_class.getConstructor( new Class[]{Connection.class,
                                                                      String.class,
                                                                      Integer.TYPE } );
            handler = (ProxiedJdbcConnection)builder.newInstance(
                new Object[]{conn, keepAlive, new Integer( keepAliveAge ) } );
        }
        catch( Exception e )
        {
            final String msg = "Could not create the proper invocation handler, "
                    + "defaulting to AbstractJdbcConnection";
            getLogger().error( msg, e );
            handler = new AbstractJdbcConnection( conn, keepAlive, keepAliveAge );
        }

        final Connection connection = (Connection)Proxy.newProxyInstance(
                m_class.getClassLoader(),
                new Class[]{Connection.class,
                            LogEnabled.class,
                            PoolSettable.class,
                            Disposable.class},
                handler );

        handler.setProxiedConnection( connection );

        return connection;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy