You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by pr...@apache.org on 2003/04/08 20:34:34 UTC

cvs commit: avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource ProxiedJdbcConnection.java AbstractJdbcConnection.java JdbcConnectionFactory.java

proyal      2003/04/08 11:34:34

  Modified:    datasource/src/java/org/apache/avalon/excalibur/datasource
                        AbstractJdbcConnection.java
                        JdbcConnectionFactory.java
  Added:       datasource/src/java/org/apache/avalon/excalibur/datasource
                        ProxiedJdbcConnection.java
  Log:
  Fix proxy-based datasource
   * AbstractJdbcConnection cannot return 'this' to the pool, as that
     is not its proxied self.
   * Added ProxiedJdbcConnection interface to allow invocation handler
     to get proxied version of self as well as to allow retrieval
     of underlying connection
   * Disable lastUsed-based expiration of connections, since it was
     borked anyways
   * Implement equals() on AbstractJdbcConnection so that put()'s to the
     pool work correctly.
   * Remove unused parameter from JdbcConnectionFactory.init()
   * Dispose any Disposable in JdbcConnectionFactory
   * The InvocationHandler created in JdbcConnectionFactory must implement
     ProxiedJdbcConnection so that it can receive a handle to its proxied
     self.
  
  Revision  Changes    Path
  1.27      +76 -43    avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/AbstractJdbcConnection.java
  
  Index: AbstractJdbcConnection.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/AbstractJdbcConnection.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- AbstractJdbcConnection.java	6 Mar 2003 19:47:47 -0000	1.26
  +++ AbstractJdbcConnection.java	8 Apr 2003 18:34:33 -0000	1.27
  @@ -3,34 +3,34 @@
    ============================================================================
                      The Apache Software License, Version 1.1
    ============================================================================
  - 
  +
    Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  - 
  +
    Redistribution and use in source and binary forms, with or without modifica-
    tion, are permitted provided that the following conditions are met:
  - 
  +
    1. Redistributions of  source code must  retain the above copyright  notice,
       this list of conditions and the following disclaimer.
  - 
  +
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
  - 
  +
    3. The end-user documentation included with the redistribution, if any, must
       include  the following  acknowledgment:  "This product includes  software
       developed  by the  Apache Software Foundation  (http://www.apache.org/)."
       Alternately, this  acknowledgment may  appear in the software itself,  if
       and wherever such third-party acknowledgments normally appear.
  - 
  - 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"  
  -    must not be used to endorse or promote products derived from this  software 
  -    without  prior written permission. For written permission, please contact 
  +
  + 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
  +    must not be used to endorse or promote products derived from this  software
  +    without  prior written permission. For written permission, please contact
       apache@apache.org.
  - 
  +
    5. Products  derived from this software may not  be called "Apache", nor may
       "Apache" appear  in their name,  without prior written permission  of the
       Apache Software Foundation.
  - 
  +
    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  @@ -41,16 +41,17 @@
    ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
    (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  - 
  +
    This software  consists of voluntary contributions made  by many individuals
  - on  behalf of the Apache Software  Foundation. For more  information on the 
  + on  behalf of the Apache Software  Foundation. For more  information on the
    Apache Software Foundation, please see <http://www.apache.org/>.
  - 
  +
   */
   package org.apache.avalon.excalibur.datasource;
   
  -import java.lang.reflect.InvocationHandler;
   import java.lang.reflect.Method;
  +import java.lang.reflect.Proxy;
  +import java.lang.reflect.InvocationHandler;
   import java.sql.Connection;
   import java.sql.PreparedStatement;
   import java.sql.ResultSet;
  @@ -63,6 +64,7 @@
   import java.util.Map;
   
   import org.apache.avalon.excalibur.pool.Pool;
  +import org.apache.avalon.excalibur.pool.Poolable;
   import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.logger.AbstractLogEnabled;
   import org.apache.avalon.framework.logger.Logger;
  @@ -72,30 +74,33 @@
    * object.
    *
    * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  + * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
    * @version CVS $Revision$ $Date$
    * @since 4.1
    */
   public class AbstractJdbcConnection
  -    extends AbstractLogEnabled
  -    implements PoolSettable, Disposable,  InvocationHandler
  +        extends AbstractLogEnabled
  +        implements PoolSettable, Disposable, ProxiedJdbcConnection
   {
       protected Connection m_connection;
  +    private Object m_proxy;
       protected Pool m_pool;
       protected PreparedStatement m_testStatement;
       protected SQLException m_testException;
       protected long m_lastUsed = System.currentTimeMillis();
       private static final Map m_methods;
  -    
  -    static {
  +
  +    static
  +    {
           m_methods = new HashMap();
           Method[] methods = AbstractJdbcConnection.class.getDeclaredMethods();
  -        
  -        for ( int i = 0; i < methods.length; i++ )
  +
  +        for( int i = 0; i < methods.length; i++ )
           {
  -            m_methods.put(methods[i].getName(), methods[i]);
  +            m_methods.put( methods[i].getName(), methods[i] );
           }
       }
  -    
  +
       /**
        * Contains Statements created on the original jdbc connection
        * between a {@link JdbcDataSource#getConnection} and {@link
  @@ -189,8 +194,18 @@
           }
       }
   
  +    public void setProxiedConnection( Object proxy )
  +    {
  +        m_proxy = proxy;
  +    }
  +
  +    public Connection getConnection()
  +    {
  +        return m_connection;
  +    }
  +
       public boolean isClosed()
  -        throws SQLException
  +            throws SQLException
       {
           if( m_connection.isClosed() )
           {
  @@ -198,11 +213,14 @@
           }
   
           long age = System.currentTimeMillis() - m_lastUsed;
  -        if( age > 1000 * 60 * 60 ) // over an hour?
  -        {
  -            this.dispose();
  -            return true;
  -        }
  +// Commenting out the hour check since it was to check an hour since last use, but since the
  +// last-use time is not being updated anywhere, it has turned into "all connections expire after
  +// an hour"
  +//        if( age > 1000 * 60 * 60 ) // over an hour?
  +//        {
  +//            this.dispose();
  +//            return true;
  +//        }
   
           if( m_testStatement != null && age > ( 5 * 1000 ) ) // over 5 seconds ago
           {
  @@ -228,15 +246,15 @@
       }
   
       public void close()
  -        throws SQLException
  +            throws SQLException
       {
           try
           {
               clearAllocatedStatements();
               m_connection.clearWarnings();
  -            m_pool.put( this );
  +            m_pool.put( (Poolable)m_proxy );
           }
  -        catch ( SQLException se )
  +        catch( SQLException se )
           {
               // gets rid of connections that throw SQLException during
               // clean up
  @@ -267,7 +285,7 @@
                   final Iterator iterator = m_allocatedStatements.iterator();
                   while( iterator.hasNext() )
                   {
  -                    Statement stmt = (Statement) iterator.next();
  +                    Statement stmt = (Statement)iterator.next();
                       stmt.close();
                   }
               }
  @@ -305,22 +323,37 @@
               }
           }
       }
  -    
  -    public Object invoke(Object proxy, Method method, Object[] args)
  -              throws Throwable
  +
  +    public boolean equals( Object obj )
  +    {
  +        if( Proxy.isProxyClass( obj.getClass() ) )
  +        {
  +            final InvocationHandler handler = Proxy.getInvocationHandler(obj );
  +
  +            if( handler instanceof ProxiedJdbcConnection )
  +            {
  +                return m_connection.equals( ( (ProxiedJdbcConnection)handler ).getConnection() );
  +            }
  +        }
  +
  +        return false;
  +    }
  +
  +    public Object invoke( Object proxy, Method method, Object[] args )
  +            throws Throwable
       {
           Object retVal = null;
  -        Method executeMethod = (Method)m_methods.get(method.getName());
  -        
  -        if ( null == executeMethod )
  +        Method executeMethod = (Method)m_methods.get( method.getName() );
  +
  +        if( null == executeMethod )
           {
  -            retVal = method.invoke(m_connection, args);
  +            retVal = method.invoke( m_connection, args );
           }
           else
           {
  -            retVal = executeMethod.invoke(this, args);
  +            retVal = executeMethod.invoke( this, args );
           }
  -        
  +
           return retVal;
       }
   }
  
  
  
  1.19      +287 -276  avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/JdbcConnectionFactory.java
  
  Index: JdbcConnectionFactory.java
  ===================================================================
  RCS file: /home/cvs/avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/JdbcConnectionFactory.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- JdbcConnectionFactory.java	5 Mar 2003 18:59:01 -0000	1.18
  +++ JdbcConnectionFactory.java	8 Apr 2003 18:34:34 -0000	1.19
  @@ -1,276 +1,287 @@
  -/*
  -
  - ============================================================================
  -                   The Apache Software License, Version 1.1
  - ============================================================================
  - 
  - Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  - 
  - Redistribution and use in source and binary forms, with or without modifica-
  - tion, are permitted provided that the following conditions are met:
  - 
  - 1. Redistributions of  source code must  retain the above copyright  notice,
  -    this list of conditions and the following disclaimer.
  - 
  - 2. Redistributions in binary form must reproduce the above copyright notice,
  -    this list of conditions and the following disclaimer in the documentation
  -    and/or other materials provided with the distribution.
  - 
  - 3. The end-user documentation included with the redistribution, if any, must
  -    include  the following  acknowledgment:  "This product includes  software
  -    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  -    Alternately, this  acknowledgment may  appear in the software itself,  if
  -    and wherever such third-party acknowledgments normally appear.
  - 
  - 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"  
  -    must not be used to endorse or promote products derived from this  software 
  -    without  prior written permission. For written permission, please contact 
  -    apache@apache.org.
  - 
  - 5. Products  derived from this software may not  be called "Apache", nor may
  -    "Apache" appear  in their name,  without prior written permission  of the
  -    Apache Software Foundation.
  - 
  - THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  - FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  - APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  - INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  - DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  - OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  - ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  - (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  - 
  - This software  consists of voluntary contributions made  by many individuals
  - on  behalf of the Apache Software  Foundation. For more  information on the 
  - Apache Software Foundation, please see <http://www.apache.org/>.
  - 
  -*/
  -package org.apache.avalon.excalibur.datasource;
  -
  -import java.lang.reflect.Constructor;
  -import java.lang.reflect.InvocationHandler;
  -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 <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  - * @version CVS $Revision$ $Date$
  - * @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 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.m_dburl = url;
  -        this.m_username = username;
  -        this.m_password = password;
  -        this.m_autoCommit = autoCommit;
  -        this.m_keepAlive = keepAlive;
  -        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( m_firstConnection );
  -        }
  -        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( Connection connection ) 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( connection );
  -            }
  -            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);
  -        }
  -        catch( Exception e )
  -        {
  -            if( getLogger().isDebugEnabled() )
  -            {
  -                getLogger().debug( "Exception in JdbcConnectionFactory.newInstance:", e );
  -            }
  -
  -            throw new NoValidConnectionException( e.getMessage() );
  -        }
  -
  -        ContainerUtil.enableLogging(jdbcConnection, getLogger());
  -
  -        // 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 AbstractJdbcConnection )
  -        {
  -            ( (AbstractJdbcConnection)object ).dispose();
  -        }
  -    }
  -    
  -    private Connection getProxy(Connection conn, String keepAlive)
  -    {
  -        InvocationHandler handler = null;
  -        
  -        try
  -        {
  -            Constructor builder = m_class.getConstructor(new Class[]{Connection.class, String.class});
  -            handler = (InvocationHandler)builder.newInstance(new Object[]{conn, keepAlive});
  -        }
  -        catch (Exception e)
  -        {
  -            getLogger().error("Could not create the proper invocation handler, defaulting to AbstractJdbcConnection", e);
  -            handler = new AbstractJdbcConnection(conn, keepAlive);
  -        }
  -        
  -        return (Connection) Proxy.newProxyInstance(
  -                m_class.getClassLoader(),
  -                new Class[]{Connection.class,
  -                            LogEnabled.class,
  -                            PoolSettable.class,
  -                            Disposable.class},
  -                handler);
  -    }
  -}
  +/*
  +
  + ============================================================================
  +                   The Apache Software License, Version 1.1
  + ============================================================================
  +
  + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  +
  + Redistribution and use in source and binary forms, with or without modifica-
  + tion, are permitted provided that the following conditions are met:
  +
  + 1. Redistributions of  source code must  retain the above copyright  notice,
  +    this list of conditions and the following disclaimer.
  +
  + 2. Redistributions in binary form must reproduce the above copyright notice,
  +    this list of conditions and the following disclaimer in the documentation
  +    and/or other materials provided with the distribution.
  +
  + 3. The end-user documentation included with the redistribution, if any, must
  +    include  the following  acknowledgment:  "This product includes  software
  +    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  +    Alternately, this  acknowledgment may  appear in the software itself,  if
  +    and wherever such third-party acknowledgments normally appear.
  +
  + 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
  +    must not be used to endorse or promote products derived from this  software
  +    without  prior written permission. For written permission, please contact
  +    apache@apache.org.
  +
  + 5. Products  derived from this software may not  be called "Apache", nor may
  +    "Apache" appear  in their name,  without prior written permission  of the
  +    Apache Software Foundation.
  +
  + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  + FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  + APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  + INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  + DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  + OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  + ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  + (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  +
  + This software  consists of voluntary contributions made  by many individuals
  + on  behalf of the Apache Software  Foundation. For more  information on the
  + Apache Software Foundation, please see <http://www.apache.org/>.
  +
  +*/
  +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 <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  + * @version CVS $Revision$ $Date$
  + * @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 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.m_dburl = url;
  +        this.m_username = username;
  +        this.m_password = password;
  +        this.m_autoCommit = autoCommit;
  +        this.m_keepAlive = keepAlive;
  +        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 );
  +        }
  +        catch( Exception e )
  +        {
  +            if( getLogger().isDebugEnabled() )
  +            {
  +                getLogger().debug( "Exception in JdbcConnectionFactory.newInstance:", e );
  +            }
  +
  +            throw new NoValidConnectionException( e.getMessage() );
  +        }
  +
  +        ContainerUtil.enableLogging( jdbcConnection, getLogger() );
  +
  +        // 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 )
  +    {
  +        ProxiedJdbcConnection handler = null;
  +
  +        try
  +        {
  +            Constructor builder = m_class.getConstructor( new Class[]{Connection.class,
  +                                                                      String.class} );
  +            handler = (ProxiedJdbcConnection)builder.newInstance( new Object[]{conn, keepAlive} );
  +        }
  +        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 );
  +        }
  +
  +        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;
  +    }
  +}
  
  
  
  1.1                  avalon-excalibur/datasource/src/java/org/apache/avalon/excalibur/datasource/ProxiedJdbcConnection.java
  
  Index: ProxiedJdbcConnection.java
  ===================================================================
  package org.apache.avalon.excalibur.datasource;
  
  import java.lang.reflect.InvocationHandler;
  import java.sql.Connection;
  
  /**
   * A JDBC connection that has a proxy around it in order to dynamicly implement JDBC2/3 needs
   * to get a handle to its proxied self so that the proxied version can be returned to the pool.
   *
   * @author <a href="proyal@apache.org">peter royal</a>
   */
  public interface ProxiedJdbcConnection extends InvocationHandler
  {
      void setProxiedConnection( Object proxy );
  
      Connection getConnection();
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org