jmcnally    02/01/14 18:50:45

  Added:       jdbc2pool LICENSE README.txt build.xml default.properties
               jdbc2pool/src/java/org/apache/commons/jdbc2pool
                        ConnectionPool.java
                        ConnectionWaitTimeoutException.java
                        Jdbc2PoolDataSource.java
               jdbc2pool/src/java/org/apache/commons/jdbc2pool/adapter
                        ConnectionImpl.java DriverAdapterCPDS.java
                        PooledConnectionImpl.java
  Log:
  A db connection pool meant to be used as the front end to a ConnectionPoolDataSource.
  Also an adapter for jdbc drivers that have not implemented the new interface.
  
  See the README.txt for info on relationship to DBCP and other projects.
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/jdbc2pool/LICENSE
  
  Index: LICENSE
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
  
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/README.txt
  
  Index: README.txt
  ===================================================================
  --------------------------------------------------------------------------
  J A K A R T A  C O M M O N S  J D B C 2 P O O L
  --------------------------------------------------------------------------
  
  o Building
  
  To build, you must have ant installed.  Just type 'ant' -- the default
  target will build the jar.
  
  There are also a few other targets like 'javadoc'.  Look in build.xml
  
  
  o Use in your application
  
  To use the Commons Jdbc2pool package, build a commons-jdbc2pool.jar file,
  import the desired classes from org.apache.commons.jdbc2pool and/or 
  org.apache.commons.jdbc2pool.adapter packages.
  
  There are two independent DataSource implementations within the jdbc2pool
  component.  Both attempt to conform to the letter of the jdbc2 specification,
  so standard usage should be possible.  Such as binding to and looking up from
  a jndi service provider.
  
  The first implementation is Jdbc2PoolDataSource which implements a pool of
  PooledConnection's.  The properties of the pool are set using bean-like 
  setters and the properties that are available are described in the javadoc.
  
  Also included is a ConnectionPoolDataSource (CPDS) implementation.  The 
  Jdbc2PoolDataSource expects a backend CPDS to supply PooledConnections.  A
  CPDS is generally supplied with a jdbc2 driver, however some popular db's
  only have jdbc 1.x drivers or the jdbc2 implementations are incomplete.
  DriverAdapterCPDS can be used in such cases.  It wraps usage of the 
  deprecated DriverManager api and provides a jdbc2 compliant CPDS facade 
  that can be deployed using jndi and used with any jdbc2 datasource.
  
  o Motivation
  
  Commons-Proper already contains a package known as DBCP which is also
  a database connection pool.  DBCP is not jdbc2 compliant in a few ways:
  
  1.  Should be deployable using standardized tools which will assume a no
  argument constructor and bean getter/setters (which can be introspected)
  for configuration.
  
  2.  Jdbc2 driver implementation will supply a CPDS that should be used when
  pooling connections.  DBCP does not use this interface instead it pools the
  older style Connection objects.
  
  3.  Some Jndi interfaces which should be implemented in a Jdbc2 product are
  left for the individual applications to complete.
  
  Torque, which is a Object-Relational Mapping project, jakarta-turbine-torque,
  contains a built in connection pool.  While the connection pool could be used
  outside of torque, it predates jdbc2 and had its own pecularities with respect
  to usage.  It would be beneficial for torque if it could use any jdbc2 pool,
  so that it could take advantage of any benefits that might come with using
  the pool supplied by an application server for example.
  
  Torque's connection pool was updated to be jdbc2 compliant and then separated
  into this package.  As DBCP already exists in Commons-Proper, if it is 
  altered so that it can be used by Torque, this package will likely be removed.
  Hopefully, it provides an example which can lead to DBCP becoming jdbc2
  compliant.  The DriverAdapterCPDS and related adapter classes should still be
  useful in this case.
  
  If DBCP is not updated to be compliant, this package can exist as an 
  alternative.
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/build.xml
  
  Index: build.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <project name="Jdbc2Pool" default="jar" basedir=".">
  
    <!-- Allow any user specific values to override the defaults -->
    <property file="${user.home}/build.properties" />
    <!-- Allow user defaults for this project -->
    <property file="build.properties" />
    <!-- Set default values for the build -->
    <property file="default.properties" />
  
    <!-- Construct compile classpath -->
    <path id="classpath">
      <pathelement location="${jdbc.jar}"/>
      <pathelement location="${log4j.jar}"/>
      <pathelement location="${commons-util.jar}"/>
      <pathelement location="${junit.jar}"/>
    </path>
  
    <!-- ================================================================== -->
    <!-- E N V I R O N M E N T                                             -->
    <!-- ================================================================== -->
  
    <target name="env">
      <echo message="java.home = ${java.home}"/>
      <echo message="user.home = ${user.home}"/>
      <echo message="lib.repo = ${lib.repo}"/>
      <echo message="log4j.jar = ${log4j.jar}"/>
      <echo message="jdbc.jar = ${jdbc.jar}"/>
      <echo message="junit.jar = ${junit.jar}"/>
      <echo message="commons-util.jar = ${commons-util.jar}"/>
    </target>
  
    <!-- ================================================================== -->
    <!-- U S A G E                                                          -->
    <!-- ================================================================== -->
  
    <target
      name="usage">
  
      <echo message="use -projecthelp to see the available targets"/>
    </target>
  
  
    <!-- ================================================================== -->
    <!-- I N I T                                                            -->
    <!-- ================================================================== -->
  
    <target
      name="init">
  
      <available
        classname="org.apache.log4j.Category"
        property="log4j.present"
        classpathref="classpath"
      />
  
      <available
        classname="org.apache.commons.util.exception.NestableException"
        property="commons-util.present"
        classpathref="classpath"
      />
  
      <available
        classname="javax.sql.ConnectionPoolDataSource"
        property="jdbc.present"
        classpathref="classpath"
      />
  
      <available
        classname="junit.framework.TestCase"
        property="junit.present"
        classpathref="classpath"
      />
    </target>
  
    <!-- ================================================================== -->
    <!-- P R O P E R T Y  C H E C K S  A N D  W A R N I N G S               -->
    <!-- ================================================================== -->
  
    <target
      name="check.log4j"
      unless="log4j.present">
  
      <antcall target="property-warning">
        <param name="name" value="log4j.jar"/>
        <param name="value" value="${log4j.jar}"/>
      </antcall>
    </target>
  
    <target
      name="check.commons-util"
      unless="commons-util.present">
  
      <antcall target="property-warning">
        <param name="name" value="commons-util.jar"/>
        <param name="value" value="${commons-util.jar}"/>
      </antcall>
    </target>
  
    <target
      name="check.jdbc"
      unless="jdbc.present">
  
      <antcall target="property-warning">
        <param name="name" value="jdbc.jar"/>
        <param name="value" value="${jdbc.jar}"/>
      </antcall>
    </target>
  
    <target name="property-warning">
      <echo>
        +----------------------------------------------------------------+
        + F A I L E D  R E Q U I R E M E N T                             |
        +----------------------------------------------------------------+
        | You must define the following property in order                |
        | to build Jdbc2pool:                                               |
        |                                                                |
        | ${name} (currently "${value}")
        |                                                                |
        | You can set this property in the provided build.properties     |
        | file, or you may set this property in your                     |
        | ${user.home}/build.properties file.
        +----------------------------------------------------------------+
      </echo>
      <fail message="Failed Requirement"/>
    </target>
  
    <!-- ================================================================== -->
    <!-- P R E P A R E                                                      -->
    <!-- ================================================================== -->
  
    <target
      name="prepare"
      depends="init,check.log4j,check.commons-util,
               check.jdbc,env">
  
      <mkdir dir="${build.dir}"/>
      <mkdir dir="${build.dest}"/>
  
    </target>
  
    <!-- ================================================================== -->
    <!-- C O M P I L E                                                      -->
    <!-- ================================================================== -->
  
    <target
      name="compile"
      depends="prepare"
      description="==> compiles the source code">
  
      <javac srcdir="${src.dir}/java"
        destdir="${build.dest}"
        debug="${debug}"
        deprecation="${deprecation}"
        optimize="${optimize}">
        <classpath refid="classpath"/>
      </javac>
    </target>
  
    <!-- ================================================================== -->
    <!-- C O M P I L E  T E S T S                                           -->
    <!-- ================================================================== -->
  
    <target
      name="compile-test"
      depends="compile"
      if="junit.present"
      description="==> compiles the test source code">
  
      <javac srcdir="${test.dir}"
        destdir="${build.dest}"
        excludes="**/package.html"
        debug="${debug}"
        deprecation="${deprecation}"
        optimize="${optimize}">
        <classpath refid="classpath"/>
        <classpath>
          <pathelement path="${build.dest}"/>
        </classpath>
      </javac>
    </target>
  
    <!-- ================================================================== -->
    <!-- T E S T                                                            -->
    <!-- ================================================================== -->
    <target
      name="run-test"
      depends="prepare,compile-test"
      if="junit.present"
      description="==> runs the test source code">
  
      <taskdef
        name="junit"
        classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask">
        <classpath refid="classpath"/>
      </taskdef>
  
      <junit printsummary="no" haltonfailure="yes">
        <classpath>
          <pathelement location="${build.dest}"/>
          <pathelement location="${build.test}"/>
          <path refid="classpath"/>
        </classpath>
  
        <formatter type="plain" usefile="false"/>
  
        <batchtest>
          <fileset dir="${test.dir}">
            <exclude name="**/BaseTestCase.java"/>
            <exclude name="**/PoolTest.java"/>
            <include name="**/*Test.java"/>
          </fileset>
        </batchtest>
      </junit>
  
    </target>
  
    <!-- ================================================================== -->
    <!-- J A R                                                              -->
    <!-- ================================================================== -->
  
    <target
      name="jar"
      depends="compile"
      description="==> generates the jdbc2pool.jar">
  
      <jar jarfile="${build.dir}/${final.name}.jar">
        <fileset dir="${build.dest}">
          <exclude name="**/package.html"/>
        </fileset>
      </jar>
    </target>
  
    <!-- ================================================================== -->
    <!-- J A V A D O C S                                                    -->
    <!-- ================================================================== -->
  
    <target
      name="javadocs"
      depends="prepare"
      description="==> generates the API documentation">
  
      <mkdir dir="${docs.dest}/api"/>
  
      <javadoc
        sourcepath="${src.dir}/java"
        packagenames="${package}.*"
        destdir="${javadoc.destdir}"
        author="true"
        private="true"
        version="true"
        use="true"
        windowtitle="${name} ${version} API"
        doctitle="${name} ${version} API"
        bottom="Copyright &amp;copy; ${year} Apache Software Foundation. All Rights 
Reserved.">
        <classpath refid="classpath"/>
        <classpath path="${ant.home}/lib/ant.jar"/>
      </javadoc>
    </target>
  
    <!-- ================================================================== -->
    <!-- C L E A N                                                          -->
    <!-- ================================================================== -->
  
    <target
      name="clean"
      description="==> cleans up the build directory">
  
      <delete dir="${build.dir}"/>
    </target>
  
    <!-- ================================================================== -->
    <!-- I N S T A L L  J A R                                               -->
    <!-- ================================================================== -->
  
    <target
      name="install-jar"
      depends="jar"
      description="==> Installs .jar file in ${lib.repo}">
  
      <copy todir="${lib.repo}" filtering="no">
        <fileset dir="${build.dir}">
          <include name="${final.name}.jar"/>
        </fileset>
      </copy>
    </target>
  
  </project>
  
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/default.properties
  
  Index: default.properties
  ===================================================================
  # -------------------------------------------------------------------
  # B U I L D  P R O P E R T I E S
  # -------------------------------------------------------------------
  # These properties are used by the Jdbc2Pool build, you may override
  # any of these default values by placing property values in
  # your ${user.home}/build.properties file.
  # -------------------------------------------------------------------
  
  name = Jdbc2Pool
  project = jdbc2pool
  version = 1.0-dev
  package = org.apache.${project}
  final.name = ${project}-${version}
  jdbc2pool.jar = ${final.name}.jar
  
  build.dir = ./bin
  build.dest = ${build.dir}/classes
  build.test = ${build.dir}/test
  src.dir = ./src
  test.dir = ${src.dir}/test
  test.libDir = ${build.test}/lib
  javadoc.destdir = ./docs/api
  
  year = 1999-2001
  debug = on
  optimize = off
  deprecation = on
  
  # You must set values for the JAR file properties listed here, or in
  # your ${user.home}/build.properties or local build.properties file in
  # order to build Jdbc2pool:
  
  log4j.jar = ${lib.repo}/log4j-1.1.3.jar
  commons-util.jar = ${lib.repo}/commons-util-0.1-dev.jar
  jdbc.jar = ${lib.repo}/jdbc2_0-stdext.jar
  junit.jar = ${lib.repo}/junit-3.7.jar
  
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/ConnectionPool.java
  
  Index: ConnectionPool.java
  ===================================================================
  package org.apache.torque.jdbc2pool;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
  
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Date;
  import java.io.PrintWriter;
  import java.sql.Connection;
  import java.sql.SQLException;
  import java.util.Stack;
  import java.util.Vector;
  import javax.sql.ConnectionPoolDataSource;
  import javax.sql.PooledConnection;
  import javax.sql.ConnectionEvent;
  import javax.sql.ConnectionEventListener;
  
  import org.apache.log4j.Category;
  import org.apache.torque.jdbc2pool.ConnectionWaitTimeoutException;
  
  /**
   * This class implements a simple connection pooling scheme.  Multiple
   * pools are available through use of the <code>PoolBrokerService</code>.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Costas Stergiou</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Frank Y. Kim</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Brett McLaughlin</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Greg Ritter</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Daniel L. Rall</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Paul O'Leary</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Magn�s ��r Torfason</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jon S. Stevens</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>John McNally</a>
   * @version $Id: ConnectionPool.java,v 1.1 2002/01/15 02:50:44 jmcnally Exp $
   */
  class ConnectionPool
      implements ConnectionEventListener
  {
      /**
       * Pool containing database connections.
       */
      private Stack pool;
  
      /**
       * The driver type for this pool.
       */
      private String driver;
  
      /**
       * The url for this pool.
       */
      private String url;
  
      /**
       * The user name for this pool.
       */
      private String username;
  
      /**
       * The password for this pool.
       */
      private String password;
  
      /**
       * The current number of database connections that have been
       * created.
       */
      private int totalConnections;
  
      /**
       * The maximum number of database connections that can be
       * created.
       */
      private int maxConnections;
  
      /**
       * The amount of time in milliseconds that a connection will be
       * pooled.
       */
      private int expiryTime; // 1 hour
  
      /**
       * Thread sleep time between checks for database connectivity
       * problems.
       */
      //private int dbCheckFrequency;
  
  
      int logInterval;
      Monitor monitor;
  
      /**
       * Amount of time a thread asking the pool for a cached connection will
       * wait before timing out and throwing an error.
       */
      private long connectionWaitTimeout;
  
      /** The ConnectionPoolDataSource  */
      private ConnectionPoolDataSource cpds;
  
      /**
       * Keep track of when connections were created.  Keyed by a 
       * PooledConnection and value is a java.util.Date
       */
      private Map timeStamps;
  
      private PrintWriter logWriter;
      private Category category;
  
      /**
       * Creates a <code>ConnectionPool</code> with the default
       * attributes.
       *
       * @param driver   The driver type for this pool.
       * @param url      The url for this pool.
       * @param username  The user name for this pool.
       * @param password The password for this pool.
       */
      ConnectionPool(ConnectionPoolDataSource cpds, String username,
                     String password, int maxConnections, int expiryTime,
                     int connectionWaitTimeout, int logInterval,
                     PrintWriter logWriter)
      {
          totalConnections = 0;
          pool = new Stack();
          timeStamps = new HashMap();
          
          this.cpds = cpds;
          this.username = username;
          this.password = password;
          if ( maxConnections > 0 ) 
          {
              this.maxConnections = maxConnections;
          }
          else 
          {
              this.maxConnections = 1;            
          }
          if ( expiryTime > 0 ) 
          {
              this.expiryTime = expiryTime * 1000;            
          }
          else 
          {
              this.expiryTime = 3600 * 1000; // one hour
          }
          if ( connectionWaitTimeout > 0 ) 
          {
              this.connectionWaitTimeout = connectionWaitTimeout * 1000;    
          }
          else
          {
              this.connectionWaitTimeout = 10 * 1000; // ten seconds
          }
          this.logInterval = logInterval * 1000;    
          this.logWriter = logWriter;        
          this.category = Category.exists(getClass().getName());
   
          // Create monitor thread
          monitor = new Monitor();
          // Indicate that this is a system thread. JVM will quit only when there
          // are no more active user threads. Settings threads spawned internally
          // by Turbine as daemons allows commandline applications using Turbine
          // to terminate in an orderly manner.
          monitor.setDaemon(true);
          monitor.start();
      }
  
      /**
       * Returns a connection that maintains a link to the pool it came from.
       *
       * @param driver   The fully-qualified name of the JDBC driver to use.
       * @param url      The URL of the database from which the connection is
       *                 desired.
       * @param username The name of the database user.
       * @param password The password of the database user.
       * @return         A database connection.
       *
       * @exception Exception
       */
      synchronized final PooledConnection 
          getConnection(String username, String password)
          throws SQLException
      {
          if ( username != this.username || password != this.password ) 
          {
              throw new SQLException("Username and password are invalid.");
          }
          
          PooledConnection pcon = null;
          if ( pool.empty() && totalConnections < maxConnections )
          {
              pcon = getNewConnection();
          }
          else
          {
              try
              {
                  pcon = getInternalPooledConnection();
              }
              catch (Exception e)
              {
                  // ignore for now, should wrap in SQLException 
              }
          }
          return pcon;
      }
  
      /**
       * Returns a fresh connection to the database.  The database type
       * is specified by <code>driver</code>, and its connection
       * information by <code>url</code>, <code>username</code>, and
       * <code>password</code>.
       *
       * @return A database connection.
       * @exception Exception
       */
      private PooledConnection getNewConnection()
          throws SQLException
      {
          PooledConnection pc = null;
          if ( username == null ) 
          {
              pc = cpds.getPooledConnection();
          }
          else 
          {
              pc = cpds.getPooledConnection(username, password);
          }
          pc.addConnectionEventListener(this);
          // Age some connections so that there will not be a run on the db,
          // when connections start expiring
          long currentTime = System.currentTimeMillis();
          double ratio = (1.0 * totalConnections)/maxConnections;
          currentTime -= expiryTime*0.25*(1.0-ratio);
          timeStamps.put(pc, new Long(currentTime));
          totalConnections++;
          return pc;
      }
  
      /**
       * Gets a pooled database connection.
       *
       * @return A database connection.
       * @exception ConnectionWaitTimeoutException Wait time exceeded.
       * @exception Exception No pooled connections.
       */
      private synchronized PooledConnection getInternalPooledConnection()
          throws ConnectionWaitTimeoutException, Exception
      {
          PooledConnection pcon = null;
  
          if ( pool.empty() )
          {
              // The connection pool is empty and we cannot allocate any new
              // connections.  Wait the prescribed amount of time and see if
              // a connection is returned.
              try
              {
                  wait( connectionWaitTimeout );
              }
              catch (InterruptedException ignored)
              {
                  // Don't care how we come out of the wait state.
              }
  
              // Check for a returned connection.
              if ( pool.empty() )
              {
                  // If the pool is still empty here, we were not awoken by
                  // someone returning a connection.
                  throw new ConnectionWaitTimeoutException(url);
              }
              pcon = popConnection();
          }
          else
          {
              pcon = popConnection();
          }
  
          return pcon;
      }
      /**
       * Helper function that attempts to pop a connection off the pool's stack,
       * handling the case where the popped connection has become invalid by
       * creating a new connection.
       *
       * @return An existing or new database connection.
       * @exception Exception
       */
      private PooledConnection popConnection()
          throws Exception
      {
          while ( !pool.empty() )
          {
              PooledConnection con = (PooledConnection) pool.pop();
  
              // It's really not safe to assume this connection is
              // valid even though it's checked before being pooled.
              if ( isValid(con) )
              {
                  return con;
              }
              else
              {
                  // Close invalid connection.
                  con.close();
                  totalConnections--;
  
                  // If the pool is now empty, create a new connection.  We're
                  // guaranteed not to exceed the connection limit since we
                  // just killed off one or more invalid connections, and no
                  // one else can be accessing this cache right now.
                  if ( pool.empty() )
                  {
                      return getNewConnection();
                  }
              }
          }
  
          // The connection pool was empty to start with--don't call this
          // routine if there's no connection to pop!
          // TODO: Propose general Turbine assertion failure exception? -PGO
          throw new Exception("Assertaion failure: Attempted to pop " +
                              "connection from empty pool!");
      }
  
  
      /**
       * Helper method which determines whether a connection has expired.
       *
       * @param connection The connection to test.
       * @return True if the connection is expired, false otherwise.
       * @exception Exception
       */
      private boolean isExpired( PooledConnection connection )
      {
          // Test the age of the connection (defined as current time
          // minus connection birthday) against the connection pool
          // expiration time.
          return ( expiryTime < (System.currentTimeMillis() -
                   ((Long)timeStamps.get(connection)).longValue()) );
      }
  
      /**
       * Determines if a connection is still valid.
       *
       * @param connection The connection to test.
       * @return True if the connection is valid, false otherwise.
       * @exception Exception
       */
      private boolean isValid( PooledConnection connection )
      {
          try
          {
              // This will throw an exception if:
              //     The connection is null
              //     The connection is closed
              // Therefore, it would be false.
              connection.getConnection();
              // Check for expiration
              return !isExpired(connection);
          }
          catch (SQLException e)
          {
              return false;
          }
      }
  
  
      /**
       * Close any open connections when this object is garbage collected.
       *
       * @exception Throwable Anything might happen...
       */
      protected void finalize()
          throws Throwable
      {
          shutdown();
      }
  
      /**
       * Close all connections to the database,
       */
      void shutdown()
      {
          if ( pool != null )
          {
              while ( !pool.isEmpty() )
              {
                  try
                  {
                      ((PooledConnection)pool.pop()).close();
                  }
                  catch (SQLException ignore)
                  {
                  }
                  finally
                  {
                      totalConnections--;
                  }
              }
          }
          monitor.shutdown();
      }
  
      /**
       * Re
       turns the Total connections in the pool
       */
      int getTotalCount()
      {
          return totalConnections;
      }
  
      /**
       * Returns the available connections in the pool
       */
      int getNbrAvailable()
      {
          return pool.size();
      }
  
      /**
       * Returns the checked out connections in the pool
       */
      int getNbrCheckedOut()
      {
          return (totalConnections - pool.size());
      }
  
      /**
       * Decreases the count of connections in the pool
       * and also calls <code>notify()</code>.
       */
      void decrementConnections()
      {
          totalConnections--;
          notify();
      }
  
      String getPoolName()
      {
          return toString();
      }
  
      // ***********************************************************************
      // java.sql.ConnectionEventListener implementation
      // ***********************************************************************
  
      /**
       * This will be called if the Connection returned by the getConnection
       * method came from a PooledConnection, and the user calls the close()
       * method of this connection object. What we need to do here is to
       * release this PooledConnection from our pool...
       */
      public void connectionClosed(ConnectionEvent event) 
      {
          System.out.println("connectionClosed event caught");
          releaseConnection( (PooledConnection)event.getSource());
      }
  
      /**
       * If a fatal error occurs, close the underlying physical connection so as
       * not to be returned in the future
       */
      public void connectionErrorOccurred(ConnectionEvent event) 
      {
          try 
          {
              System.err
                  .println("CLOSING DOWN CONNECTION DUE TO INTERNAL ERROR");
              //remove this from the listener list because we are no more 
              //interested in errors since we are about to close this connection
              ( (PooledConnection) event.getSource() )
                  .removeConnectionEventListener(this);
          }
          catch (Exception ignore) 
          {
              //just ignore
          }
  
          try 
          {
              closePooledConnection( (PooledConnection)event.getSource() );
          }
          catch (Exception ignore) 
          {
              //just ignore
          }
      }
  
      /**
       * This method returns a connection to the pool, and <b>must</b>
       * be called by the requestor when finished with the connection.
       *
       * @param connection The database connection to release.
       * @exception Exception Trouble releasing the connection.
       */
      private synchronized void releaseConnection(PooledConnection pcon)
      {
          if ( isValid(pcon) )
          {
              pool.push(pcon);
              notify();
          }
          else
          {
              closePooledConnection(pcon);
          }
      }
  
      private void closePooledConnection(PooledConnection pcon)
      {
          try
          {
              pcon.close();
              timeStamps.remove(pcon);
          }
          catch (Exception ignored)
          {
              // ignored, should log this !FIXME!
          }
          finally
          {
              decrementConnections();
          }
      }
  
      private void log(String s)
      {
          if ( logWriter != null ) 
          {
              logWriter.println(s);
          }
          else if ( category != null ) 
          {
              category.info(s);
          }
          else 
          {
              System.out.println(s);
          }
      }
  
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * This inner class monitors the <code>PoolBrokerService</code>.
       *
       * This class is capable of logging the number of connections available in
       * the pool periodically. This can prove useful if you application
       * frozes after certain amount of time/requests and you suspect
       * that you have connection leakage problem.
       *
       * Set the <code>database.logInterval</code> property to the number of
       * milliseconds you want to elapse between loging the number of
       * connections.
       */
      protected class Monitor extends Thread
      {
          private boolean isRun = true;
  
          public void run()
          {
              StringBuffer buf = new StringBuffer();
              while (logInterval > 0 && isRun)
              {
                  buf.setLength(0);
                  buf.append(getPoolName()).append(" (in + out = total): ")
                     .append(getNbrAvailable()).append(" + ")
                     .append(getNbrCheckedOut()).append(" = ")
                     .append(getTotalCount());
                  log(buf.toString());
              }
  
              // Wait for a bit.
              try
              {
                  Thread.sleep(logInterval);
              }
              catch (InterruptedException ignored)
              {
                  // Don't care.
              }
          }
  
          public void shutdown()
          {
              isRun = false;
          }
      }
  }
  
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/ConnectionWaitTimeoutException.java
  
  Index: ConnectionWaitTimeoutException.java
  ===================================================================
  package org.apache.torque.jdbc2pool;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
  
  import java.sql.SQLException;
  
  /**
   * Thrown to indicate that
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Daniel Rall</a>
   * @version $Id: ConnectionWaitTimeoutException.java,v 1.1 2002/01/15 02:50:44 
jmcnally Exp $
   */
  public class ConnectionWaitTimeoutException extends Exception
  {
      /**
       * Creates an wait time out exception for the specified database URL.
       *
       * @param url The URL whose connection we were waiting for.
       */
      public ConnectionWaitTimeoutException( String url )
      {
          super("Timed out waiting for pooled connection from '" + url + '\'');
      }
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/Jdbc2PoolDataSource.java
  
  Index: Jdbc2PoolDataSource.java
  ===================================================================
  package org.apache.torque.jdbc2pool;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
   
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Properties;
  
  import java.util.Hashtable;
  import java.io.PrintWriter;
  import java.io.Serializable;
  import java.io.ByteArrayOutputStream;
  import java.io.ObjectOutputStream;
  import java.io.IOException;
  import java.sql.Connection;
  import java.sql.SQLException;
  import javax.sql.DataSource;
  import javax.sql.ConnectionPoolDataSource;
  import javax.naming.Name;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.Referenceable;
  import javax.naming.Reference;
  import javax.naming.RefAddr;
  import javax.naming.BinaryRefAddr;
  import javax.naming.StringRefAddr;
  import javax.naming.NamingException;
  import javax.naming.spi.ObjectFactory;
  
  import org.apache.commons.util.ObjectUtils;
  
  /**
   * Torque's default connection pool DataSource
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>John D. McNally</a>
   * @version $Id: Jdbc2PoolDataSource.java,v 1.1 2002/01/15 02:50:44 jmcnally Exp $
   */
  public class Jdbc2PoolDataSource
      implements DataSource, Referenceable, Serializable, ObjectFactory
  {
      /** Pools keyed by username. */
      private static Map pools = new HashMap(); 
  
      /** DataSource Name used to find the ConnectionPoolDataSource */
      private String dataSourceName;
      /** Description */
      private String description;
  
      /** Login TimeOut in seconds */
      private int loginTimeout;
  
      private ConnectionPoolDataSource cpds;
  
      /** Log stream */
      private PrintWriter logWriter;
  
      /** Environment that may be used to set up a jndi initial context. */
      private Properties jndiEnvironment;
  
      private int defaultMaxConnections;
      private Properties perUserMaxConnections;
      private int maxExpiryTime;
      private int connectionWaitTimeout;
      private int logInterval;
      private boolean defaultAutoCommit;
      private boolean defaultReadOnly;
  
      /**
       * Default no-arg constructor for Serialization
       */
      public Jdbc2PoolDataSource() 
      {
          defaultAutoCommit = true;
      }
  
      // Properties
          
      /**
       * Get the number of database connections to cache per user.
       * This value is used for any username which is not specified
       * in perUserMaxConnections.  The default is 1.
       *
       * @return value of maxConnections.
       */
      public int getDefaultMaxConnections() 
      {
          return defaultMaxConnections;
      }
      
      /**
       * Set the number of database connections to cache per user.
       * This value is used for any username which is not specified
       * in perUserMaxConnections.  The default is 1.
       *
       * @param v  Value to assign to maxConnections.
       */
      public void setDefaultMaxConnections(int  v) 
      {
          this.defaultMaxConnections = v;
      }
      
      
      /**
       * Get the number of database connections to cache per user.  The keys
       * are usernames and the value is the maximum connections.  Any username
       * specified here will override the value of defaultMaxConnections.
       *
       * @return value of perUserMaxConnections.
       */
      public Properties getPerUserMaxConnections() 
      {
          return perUserMaxConnections;
      }
      
      /**
       * Set the number of database connections to cache per user.  The keys
       * are usernames and the value is the maximum connections.  Any username
       * specified here will override the value of defaultMaxConnections.
       * 
       * @param v  Value to assign to perUserMaxConnections.
       */
      public void setPerUserMaxConnections(Properties  v) 
      {
          this.perUserMaxConnections = v;
      }
      
      
      /**
       * Get the amount of time (in seconds) that database connections 
       * will be cached.  The default is 3600 (1 hour).
       * 
       * @return value of expiryTime.
       */
      public int getMaxExpiryTime() 
      {
          return maxExpiryTime;
      }
      
      /**
       * Set the amount of time (in seconds) that database connections 
       * will be cached.  The default is 3600 (1 hour).
       *
       * @param v  Value to assign to expiryTime.
       */
      public void setMaxExpiryTime(int  v) 
      {
          this.maxExpiryTime = v;
      }
      
      
      /**
       * Get the amount of time (in seconds) a connection request will  
       * have to wait before a time out occurs and an error is thrown.
       * The default is 10 seconds.
       *
       * @return value of connectionWaitTimeout.
       */
      public int getConnectionWaitTimeout() 
      {
          return connectionWaitTimeout;
      }
      
      /**
       * Eet the amount of time (in seconds) a connection request will
       * have to wait before a time out occurs and an error is thrown.
       * The default is 10 seconds.
       *
       * @param v  Value to assign to connectionWaitTimeout.
       */
      public void setConnectionWaitTimeout(int  v) 
      {
          this.connectionWaitTimeout = v;
      }
      
      
      /**
       * Get the interval (in seconds) between which the ConnectionPool logs 
       * the status of it's Connections. Default is 0 which indicates no 
       * logging.
       *
       * @return value of logInterval.
       */
      public int getLogInterval() 
      {
          return logInterval;
      }
      
      /**
       * Set the interval (in seconds) between which the ConnectionPool logs 
       * the status of it's Connections. Default is 0 which indicates no 
       * logging.
       *
       * @param v  Value to assign to logInterval.
       */
      public void setLogInterval(int  v) 
      {
          this.logInterval = v;
      }
      
      /** 
       * Get the value of defaultAutoCommit, which defines the state of 
       * connections handed out from this pool.  The value can be changed
       * on the Connection using Connection.setAutoCommit(boolean).
       * The default is true.
       *
       * @return value of defaultAutoCommit.
       */
      public boolean isDefaultAutoCommit() 
      {
          return defaultAutoCommit;
      }
      
      /**
       * Set the value of defaultAutoCommit, which defines the state of 
       * connections handed out from this pool.  The value can be changed
       * on the Connection using Connection.setAutoCommit(boolean).
       * The default is true.
       *
       * @param v  Value to assign to defaultAutoCommit.
       */
      public void setDefaultAutoCommit(boolean  v) 
      {
          this.defaultAutoCommit = v;
      }
          
      /**
       * Get the value of defaultReadOnly, which defines the state of 
       * connections handed out from this pool.  The value can be changed
       * on the Connection using Connection.setReadOnly(boolean).
       * The default is false.
       *
       * @return value of defaultReadOnly.
       */
      public boolean isDefaultReadOnly() 
      {
          return defaultReadOnly;
      }
      
      /**
       * Set the value of defaultReadOnly, which defines the state of 
       * connections handed out from this pool.  The value can be changed
       * on the Connection using Connection.setReadOnly(boolean).
       * The default is false.
       *
       * @param v  Value to assign to defaultReadOnly.
       */
      public void setDefaultReadOnly(boolean  v) 
      {
          this.defaultReadOnly = v;
      }
      
      /**
       * Get the name of the ConnectionPoolDataSource which backs this pool.
       * This name is used to look up the datasource from a jndi service 
       * provider.
       *
       * @return value of dataSourceName.
       */
      public String getDataSourceName() 
      {
          return dataSourceName;
      }
      
      /**
       * Set the name of the ConnectionPoolDataSource which backs this pool.
       * This name is used to look up the datasource from a jndi service 
       * provider.
       *
       * @param v  Value to assign to dataSourceName.
       */
      public void setDataSourceName(String  v) 
      {
          this.dataSourceName = v;
      }
      
      
      /**
       * Get the description.  This property is defined by jdbc as for use with
       * GUI (or other) tools that might deploy the datasource.  It serves no
       * internal purpose.
       *
       * @return value of description.
       */
      public String getDescription() 
      {
          return description;
      }
      
      /**
       * Set the description.  This property is defined by jdbc as for use with
       * GUI (or other) tools that might deploy the datasource.  It serves no
       * internal purpose.
       * 
       * @param v  Value to assign to description.
       */
      public void setDescription(String  v) 
      {
          this.description = v;
      }
          
      /**
       * Get the value of jndiEnvironment which is used when instantiating
       * a jndi InitialContext.  This InitialContext is used to locate the
       * backend ConnectionPoolDataSource.
       *
       * @return value of jndiEnvironment.
       */
      public Properties getJndiEnvironment() 
      {
          return jndiEnvironment;
      }
      
      /**
       * Set the value of jndiEnvironment which is used when instantiating
       * a jndi InitialContext.  This InitialContext is used to locate the
       * backend ConnectionPoolDataSource.
       *
       * @param v  Value to assign to jndiEnvironment.
       */
      public void setJndiEnvironment(Properties  v) 
      {
          this.jndiEnvironment = v;
      }
      
      /**
       * Get the value of connectionPoolDataSource.  This method will return
       * null, if the backing datasource is being accessed via jndi.
       *
       * @return value of connectionPoolDataSource.
       */
      public ConnectionPoolDataSource getConnectionPoolDataSource() 
      {
          return cpds;
      }
      
      /**
       * Set the backend ConnectionPoolDataSource.  This property should not be
       * set if using jndi to access the datasource.
       *
       * @param v  Value to assign to connectionPoolDataSource.
       */
      public void setConnectionPoolDataSource(ConnectionPoolDataSource  v) 
      {
          this.cpds = v;
      }
      
  
      /**
       * Attempt to establish a database connection.
       */
      public Connection getConnection() 
          throws SQLException
      {
          return getConnection(null, null);
      }
                       
      /**
       * Attempt to establish a database connection.
       */
      synchronized public Connection getConnection(String username, 
                                                   String password)
          throws SQLException
      {
          String key = getKey(username);
          ConnectionPool pool = (ConnectionPool)pools.get(key);
          if ( pool == null ) 
          {
              try
              {
                  registerPool(username, password);
                  pool = (ConnectionPool)pools.get(key);
              }
              catch (Exception e)
              {
                  throw new SQLException(e.getMessage());
              }
          }
  
          Connection con = 
              pool.getConnection(username, password).getConnection();
          con.setAutoCommit(defaultAutoCommit);
          con.setReadOnly(defaultReadOnly);
          return con;
      }
  
      private String getKey(String suffix)
      {
          String key = getDataSourceName();
          if ( suffix != null ) 
          {
              key += suffix;            
          }
          return key;
      }
  
      synchronized private void registerPool(String username, String password)
           throws javax.naming.NamingException
      {
          String key = getKey(username);
          if ( !pools.containsKey(key) ) 
          {
              ConnectionPoolDataSource cpds = this.cpds;
              if ( cpds == null ) 
              {            
                  Context ctx = null;
                  if ( jndiEnvironment == null ) 
                  {
                      ctx = new InitialContext();                
                  }
                  else 
                  {
                      ctx = new InitialContext(jndiEnvironment);
                  }
                  cpds = (ConnectionPoolDataSource)ctx.lookup(dataSourceName);
              }
  
              int maxConnections = getDefaultMaxConnections();
              if ( username != null ) 
              {
                  String userMaxCon = 
                      (String)getPerUserMaxConnections().get(username);
                  if ( userMaxCon != null ) 
                  {
                      maxConnections = Integer.parseInt(userMaxCon);
                  }
              }    
          
              ConnectionPool pool = new ConnectionPool(cpds, username, password,
                  maxConnections, maxExpiryTime, connectionWaitTimeout, 
                  logInterval, logWriter);
  
              // avoid ConcurrentModificationException
              Map newPools = new HashMap(pools);
              newPools.put(key, pool);
              pools = newPools;   
          }        
      }
      
      /**
       * Gets the maximum time in seconds that this data source can wait 
       * while attempting to connect to a database.
       */
      public int getLoginTimeout() 
      {
          return loginTimeout;
      }
                             
      /**
       * Get the log writer for this data source.
       */
      public PrintWriter getLogWriter() 
      {
          return logWriter;
      }
                             
      /**
       * Sets the maximum time in seconds that this data source will wait 
       * while attempting to connect to a database. NOT USED.
       */
      public void setLoginTimeout(int seconds)
      {
          loginTimeout = seconds;
      } 
                             
      /**
       * Set the log writer for this data source. NOT USED.
       */
      public void setLogWriter(java.io.PrintWriter out)
      {
          logWriter = out;
      } 
  
      /**
       * <CODE>Referenceable</CODE> implementation.
       */
      public Reference getReference() 
          throws NamingException
      {
          String factory = getClass().getName();
          
          Reference ref = new Reference(getClass().getName(), factory, null);
  
          ref.add(new StringRefAddr("defaultMaxConnections", 
                                    String.valueOf(getDefaultMaxConnections())));
          ref.add(new StringRefAddr("maxExpiryTime", 
                                    String.valueOf(getMaxExpiryTime())));
          ref.add(new StringRefAddr("connectionWaitTimeout", 
                                    String.valueOf(getConnectionWaitTimeout())));
          ref.add(new StringRefAddr("logInterval", 
                                    String.valueOf(getLogInterval())));
          ref.add(new StringRefAddr("dataSourceName", getDataSourceName()));
          ref.add(new StringRefAddr("description", getDescription()));
  
          byte[] serJndiEnv = null;
          // BinaryRefAddr does not allow null byte[].
          if ( getJndiEnvironment() != null ) 
          {
              try
              {
                  serJndiEnv = serialize(getJndiEnvironment());
                  ref.add(new BinaryRefAddr("jndiEnvironment", serJndiEnv));
              }
              catch (IOException ioe)
              {
                  throw new NamingException("An IOException prevented " + 
                     "serializing the jndiEnvironment properties.");
              }
          }
  
          byte[] serPUMC = null;
          // BinaryRefAddr does not allow null byte[].
          if ( getPerUserMaxConnections() != null ) 
          {
              try
              {
                  serPUMC = serialize(getPerUserMaxConnections());
                  ref.add(new BinaryRefAddr("perUserMaxConnections", serPUMC));
              }
              catch (IOException ioe)
              {
                  throw new NamingException("An IOException prevented " + 
                     "serializing the perUserMaxConnections properties.");
              }
          }
          
          return ref;
      }
  
  
      /**
       * implements ObjectFactory to create an instance of this class
       */ 
      public Object getObjectInstance(Object refObj, Name name, 
                                      Context context, Hashtable env) 
          throws Exception 
      {
          Reference ref = (Reference)refObj;
        
          if (ref.getClassName().equals(getClass().getName())) 
          {   
              setDefaultMaxConnections(Integer.parseInt(
                  (String)ref.get("defaultMaxConnections").getContent()));
              setMaxExpiryTime(Integer.parseInt(
                  (String)ref.get("maxExpiryTime").getContent()));
              setConnectionWaitTimeout(Integer.parseInt(
                  (String)ref.get("connectionWaitTimeout").getContent()));
              setLogInterval(Integer.parseInt(
                  (String)ref.get("logInterval").getContent()));
              setDataSourceName((String)ref.get("dataSourceName").getContent());
              setDescription((String)ref.get("description").getContent());
  
              RefAddr refAddr = ref.get("jndiEnvironment");
              if ( refAddr != null ) 
              {
                  byte[] serialized = (byte[])refAddr.getContent();
                  setJndiEnvironment( 
                      (Properties)ObjectUtils.deserialize(serialized) );
              }
  
              refAddr = ref.get("perUserMaxConnections");
              if ( refAddr != null ) 
              {
                  byte[] serialized = (byte[])refAddr.getContent();
                  setPerUserMaxConnections( 
                      (Properties)ObjectUtils.deserialize(serialized) );
              }
              
              return this;
          }
          else 
          { 
              // We can't create an instance of the reference
              return null;
          }
      }
  
      /**
       * Converts a object to a byte array for storage/serialization.
       * FIXME! this method should be moved to commons.util.ObjectUtils
       *
       * @param hash The Hashtable to convert.
       * @return A byte[] with the converted Hashtable.
       * @exception Exception, a generic exception.
       */
      private static byte[] serialize(Serializable obj)
          throws IOException
      {
          byte[] byteArray = null;
          ByteArrayOutputStream baos = null;
          ObjectOutputStream out = null;
          try
          {
              // These objects are closed in the finally.
              baos = new ByteArrayOutputStream();
              out = new ObjectOutputStream(baos);
  
              out.writeObject(obj);
              byteArray = baos.toByteArray();
          }
          finally
          {
              if (out != null) 
              {
                  out.close();
              }
          }
          return byteArray;
      }
  
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/adapter/ConnectionImpl.java
  
  Index: ConnectionImpl.java
  ===================================================================
  package org.apache.torque.jdbc2pool.adapter;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
  
  import java.util.Map;
  import java.io.PrintStream;
  import java.sql.Connection;
  import java.sql.DatabaseMetaData;
  import java.sql.PreparedStatement;
  import java.sql.CallableStatement;
  import java.sql.Statement;
  import java.sql.SQLWarning;
  import java.sql.SQLException;
  import java.util.EventObject;
  import java.util.Vector;
  import javax.sql.ConnectionEvent;
  import javax.sql.ConnectionEventListener;
  import javax.sql.PooledConnection;
  
  /**
   * This class is used as the <code>Connection</code> that will be returned
   * from <code>PooledConnectionImpl.getConnection()</code>.  It expects a
   * <code>Connection</code> that is created by a jdbc 1.x driver or datasource
   * as well as the PooleConnectionImpl that instantiated this object as 
   * arguments to the constructor.  All methods except for close() and isClosed()
   * are wrappers around the jdbc 1.x <code>Connection</code>.  close() will
   * result in the isClosed() method returning true as well as notifying the
   * listeners registered with the PooledConnectionImpl of the connectionClosed
   * event.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>John D. McNally</a>
   * @version $Id: ConnectionImpl.java,v 1.1 2002/01/15 02:50:44 jmcnally Exp $
   */
  public class ConnectionImpl 
      implements Connection
  {
      private static final String CLOSED = 
          "Attempted to use Connection after closed() was called.";
  
      /**
       * The JDBC database connection.
       */
      private Connection connection;
  
      /**
       * The object that instantiated this object
       */
       private PooledConnectionImpl pooledConnection;
  
      /**
       * Marks whether is Connection is still usable.
       */
      boolean isClosed;
  
      /**
       * Creates a <code>ConnectionImpl</code>.
       *
       * @param pooledConnection The PooledConnection that is calling the ctor.
       * @param connection The JDBC connection to wrap.
       */
      ConnectionImpl(PooledConnectionImpl pooledConnection, 
                     Connection connection)
      {
          this.pooledConnection = pooledConnection;
          this.connection = connection;
          isClosed = false;
      }
  
  
      /**
       * The finalizer helps prevent <code>ConnectionPool</code> leakage.
       */
      protected void finalize()
          throws Throwable
      {
          if (!isClosed)
          {
              // If this DBConnection object is finalized while linked
              // to a ConnectionPool, it means that it was taken from a pool
              // and not returned.  We log this fact, close the underlying
              // Connection, and return it to the ConnectionPool.
              throw new SQLException("A ConnectionImpl was finalized "
                        + "without being closed which will cause leakage of "
                        + " PooledConnections from the ConnectionPool." );
          }
      }
  
      /**
       * Throws an SQLException, if isClosed() is true
       */
      private void assertOpen()
          throws SQLException 
      {
          if ( isClosed ) 
          {
              throw new SQLException(CLOSED);
          }
      }
  
      // ***********************************************************************
      // java.sql.Connection implementation using wrapped Connection
      // ***********************************************************************
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void clearWarnings() 
          throws SQLException 
      {
          assertOpen();
          connection.clearWarnings();
      }
  
      /**
       * Marks the Connection as closed, and notifies the pool that the
       * pooled connection is available.
       *
       * @exception SQLException The database connection couldn't be closed.
       */
      public void close()
          throws SQLException
      {
          isClosed = true;
          pooledConnection.notifyListeners();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void commit()
          throws SQLException
      {
          assertOpen();
          connection.commit();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public Statement createStatement()
          throws SQLException 
      {
          assertOpen();
          return connection.createStatement();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public Statement createStatement(int resultSetType, 
                                       int resultSetConcurrency) 
          throws SQLException 
      {
          assertOpen();
          return connection
                  .createStatement(resultSetType, resultSetConcurrency);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public boolean getAutoCommit() 
          throws SQLException 
      {
          assertOpen();
          return connection.getAutoCommit();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public String getCatalog() 
          throws SQLException 
      {
          assertOpen();
          return connection.getCatalog();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public DatabaseMetaData getMetaData() 
          throws SQLException 
      {
          assertOpen();
          return connection.getMetaData();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public int getTransactionIsolation() 
          throws SQLException 
      {
          assertOpen();
          return connection.getTransactionIsolation();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public Map getTypeMap() 
          throws SQLException 
      {
          assertOpen();
          return connection.getTypeMap();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public SQLWarning getWarnings() 
          throws SQLException 
      {
          assertOpen();
          return connection.getWarnings();
      }
  
      /**
       * Returns true after close() is called, and false prior to that.
       *
       * @return a <code>boolean</code> value
       */
      public boolean isClosed() 
      {
          return isClosed;
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public boolean isReadOnly() 
          throws SQLException 
      {
          assertOpen();
          return connection.isReadOnly();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public String nativeSQL(String sql) 
          throws SQLException 
      {
          assertOpen();
          return connection.nativeSQL(sql);
      }    
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public CallableStatement prepareCall(String sql) 
          throws SQLException 
      {
          assertOpen();
          return connection.prepareCall(sql);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public CallableStatement prepareCall(String sql, int resultSetType, 
                                           int resultSetConcurrency) 
          throws SQLException 
      {
          assertOpen();
          return connection
              .prepareCall(sql, resultSetType, resultSetConcurrency);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public PreparedStatement prepareStatement(String sql)
          throws SQLException
      {
          assertOpen();
          return connection.prepareStatement(sql);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public PreparedStatement prepareStatement(String sql, int resultSetType, 
                                                int resultSetConcurrency) 
          throws SQLException 
      {
          assertOpen();
          return connection
              .prepareStatement(sql, resultSetType, resultSetConcurrency);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void rollback()
          throws SQLException
      {
          assertOpen();
          connection.rollback();
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void setAutoCommit(boolean b)
          throws SQLException
      {
          assertOpen();
          connection.setAutoCommit(b);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void setCatalog(String catalog) 
          throws SQLException 
      {
          assertOpen();
          connection.setCatalog(catalog);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void setReadOnly(boolean readOnly) 
          throws SQLException 
      {
          assertOpen();
          connection.setReadOnly(readOnly);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void setTransactionIsolation(int level) 
          throws SQLException 
      {
          assertOpen();
          connection.setTransactionIsolation(level);
      }
  
      /**
       * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
       *
       * @exception SQLException if this connection is closed or an error occurs
       * in the wrapped connection.
       */
      public void setTypeMap(Map map) 
          throws SQLException 
      {
          assertOpen();
          connection.setTypeMap(map);
      }
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/adapter/DriverAdapterCPDS.java
  
  Index: DriverAdapterCPDS.java
  ===================================================================
  package org.apache.torque.jdbc2pool.adapter;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
   
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  import java.util.Hashtable;
  import  java.io.PrintWriter;
  import  java.io.Serializable;
  import java.sql.DriverManager;
  import java.sql.SQLException;
  import javax.sql.PooledConnection;
  import javax.sql.ConnectionPoolDataSource;
  import javax.naming.Name;
  import javax.naming.Context;
  import javax.naming.Referenceable;
  import javax.naming.spi.ObjectFactory;
  import javax.naming.Reference;
  import javax.naming.StringRefAddr;
  import javax.naming.NamingException;
  
  /**
   * An adapter for jdbc drivers that do not include an implementation
   * of ConnectionPoolDataSource.  This DataSource uses the old 
   * DriverManager implementation
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>John D. McNally</a>
   * @version $Id: DriverAdapterCPDS.java,v 1.1 2002/01/15 02:50:44 jmcnally Exp $
   */
  public class DriverAdapterCPDS
      implements ConnectionPoolDataSource, Referenceable, Serializable, 
                 ObjectFactory
  {
      /** Description */
      private String description;
      /** Password */
      private String password;
      /** Url name */
      private String url;
      /** User name */
      private String user;
      /** Driver class name */
      private String driver;
  
      /** Login TimeOut in seconds */
      private int loginTimeout;
      /** Log stream */
      private PrintWriter logWriter = null;
  
      /**
       * Default no-arg constructor for Serialization
       */
      public DriverAdapterCPDS() 
      {
      }
  
      // Properties
      
      /**
       * Get the value of description.  This property is here for use by
       * the code which will deploy this datasource.  It is not used
       * internally.
       *
       * @return value of description.
       */
      public String getDescription() 
      {
          return description;
      }
      
      /**
       * Set the value of description.  This property is here for use by
       * the code which will deploy this datasource.  It is not used
       * internally.
       *
       * @param v  Value to assign to description.
       */
      public void setDescription(String  v) 
      {
          this.description = v;
      }
  
      /**
       * Get the value of password for the default user.
       * @return value of password.
       */
      public String getPassword() 
      {
          return password;
      }
      
      /**
       * Set the value of password for the default user.
       * @param v  Value to assign to password.
       */
      public void setPassword(String  v) 
      {
          this.password = v;
      }
  
      /**
       * Get the value of url used to locate the database for this datasource.
       * @return value of url.
       */
      public String getUrl() 
      {
          return url;
      }
      
      /**
       * Set the value of url used to locate the database for this datasource.
       * @param v  Value to assign to url.
       */
      public void setUrl(String  v) 
      {
          this.url = v;
      }
  
      /**
       * Get the value of default user (login or username).
       * @return value of user.
       */
      public String getUser() 
      {
          return user;
      }
      
      /**
       * Set the value of default user (login or username).
       * @param v  Value to assign to user.
       */
      public void setUser(String  v) 
      {
          this.user = v;
      }
  
      /**
       * Get the driver classname.
       * @return value of driver.
       */
      public String getDriver() 
      {
          return driver;
      }
      
      /**
       * Set the driver classname.  Setting the driver classname cause the 
       * driver to be registered with the DriverManager.
       * @param v  Value to assign to driver.
       */
      public void setDriver(String  v)
          throws ClassNotFoundException
      {
          this.driver = v;
          // make sure driver is registered
          Class.forName(v);
      }
      
      /**
       * Attempt to establish a database connection using the default
       * user and password.
       */
      public PooledConnection getPooledConnection() 
          throws SQLException
      {
          return getPooledConnection(getUser(), getPassword());
      }
                       
      /**
       * Attempt to establish a database connection.
       */
      public PooledConnection getPooledConnection(String username, 
                                                  String password)
          throws SQLException
      {
          // Workaround for buggy WebLogic 5.1 classloader - ignore the
          // exception upon first invocation.
          try
          {
              return new PooledConnectionImpl(
                  DriverManager.getConnection( getUrl(),
                                               getUser(),
                                               getPassword() ) );
          }
          catch( ClassCircularityError e )
          {
              return new PooledConnectionImpl(
                  DriverManager.getConnection( getUrl(),
                                               getUser(),
                                               getPassword() ) );
          }
      }
  
      /**
       * Gets the maximum time in seconds that this data source can wait 
       * while attempting to connect to a database. NOT USED.
       */
      public int getLoginTimeout() 
      {
          return loginTimeout;
      }
                             
      /**
       * Get the log writer for this data source. NOT USED.
       */
      public PrintWriter getLogWriter() 
      {
          return logWriter;
      }
                             
      /**
       * Sets the maximum time in seconds that this data source will wait 
       * while attempting to connect to a database. NOT USED.
       */
      public void setLoginTimeout(int seconds)
      {
          loginTimeout = seconds;
      } 
                             
      /**
       * Set the log writer for this data source. NOT USED.
       */
      public void setLogWriter(java.io.PrintWriter out)
      {
          logWriter = out;
      } 
  
      /**
       * <CODE>Referenceable</CODE> implementation.
       */
      public Reference getReference() 
          throws NamingException 
      {
          String factory = getClass().getName();
          
          Reference ref = new Reference(getClass().getName(), factory, null);
  
          ref.add(new StringRefAddr("description", getDescription()));
          ref.add(new StringRefAddr("password", getPassword()));
          ref.add(new StringRefAddr("user", getUser()));
          ref.add(new StringRefAddr("url", getUrl()));
  
          return ref;
      }
  
  
      /**
       * implements ObjectFactory to create an instance of this class
       */ 
      public Object getObjectInstance(Object refObj, Name name, 
                                      Context context, Hashtable env) 
          throws Exception 
      {
          Reference ref = (Reference)refObj;
        
          if (ref.getClassName().equals(getClass().getName())) 
          {   
              setDescription((String)ref.get("description").getContent());
              setUrl((String)ref.get("url").getContent());
              setUser((String)ref.get("user").getContent());
              setPassword((String)ref.get("password").getContent());
              return this;
          }
          else 
          { 
              // We can't create an instance of the reference
              return null;
          }
      }
  
  }
  
  
  
  1.1                  
jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/adapter/PooledConnectionImpl.java
  
  Index: PooledConnectionImpl.java
  ===================================================================
  package org.apache.torque.jdbc2pool.adapter;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 "Apache" and "Apache Software Foundation" and 
   *    "Apache Turbine" must not be used to endorse or promote products 
   *    derived from this software without prior written permission. For 
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", 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 (INCLUDING, 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/>.
   */
  
  import java.util.Map;
  import java.util.Iterator;
  import java.util.EventObject;
  import java.util.Vector;
  import java.sql.Connection;
  import java.sql.DatabaseMetaData;
  import java.sql.PreparedStatement;
  import java.sql.CallableStatement;
  import java.sql.Statement;
  import java.sql.SQLWarning;
  import java.sql.SQLException;
  import javax.sql.ConnectionEvent;
  import javax.sql.ConnectionEventListener;
  import javax.sql.PooledConnection;
  
  /**
   * Implementation of PooledConnection that is returned by
   * PooledConnectionDataSource.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>John D. McNally</a>
   * @version $Id: PooledConnectionImpl.java,v 1.1 2002/01/15 02:50:44 jmcnally Exp $
   */
  public class PooledConnectionImpl 
      implements PooledConnection
  {
      private static final String CLOSED = 
          "Attempted to use PooledConnection after closed() was called.";
  
      /**
       * The JDBC database connection that represents the physical db connection.
       */
      private Connection connection = null;
  
      /**
       * The JDBC database logical connection.
       */
      private Connection logicalConnection = null;
  
      /**
       * ConnectionEventListeners
       */
      private Vector eventListeners;
  
      /**
       * flag set to true, once close() is called.
       */
      boolean isClosed;
  
      /**
       * Wrap the real connection.
       */
      PooledConnectionImpl(Connection connection)
      {
          this.connection = connection;
          eventListeners = new Vector();
          isClosed = false;
      }
  
      /**
       * Add an event listener.
       */
      public void addConnectionEventListener(ConnectionEventListener listener)
      {
          if ( !eventListeners.contains(listener) )
          {
              eventListeners.add(listener);
          }
      }
  
      /**
       * Closes the physical connection and marks this 
       * <code>PooledConnection</code> so that it may not be used 
       * to generate any more logical <code>Connection</code>s.
       *
       * @exception SQLException if an error occurs
       */
      public void close()
          throws SQLException
      {        
          isClosed = true;
          connection.close();
      }
  
      /**
       * Throws an SQLException, if isClosed() is true
       */
      private void assertOpen()
          throws SQLException 
      {
          if ( isClosed ) 
          {
              throw new SQLException(CLOSED);
          }
      }
  
      /**
       * Returns a JDBC connection.
       *
       * @return The database connection.
       */
      public Connection getConnection()
          throws SQLException
      {
          assertOpen();
          // make sure the last connection is marked as closed
          if ( logicalConnection != null && !logicalConnection.isClosed() ) 
          {
              // should notify pool of error so the pooled connection can
              // be removed !FIXME!
              throw new SQLException("PooledConnection was reused, without" +
                                     "its previous Connection being closed.");
          }
  
          // the spec requires that this return a new Connection instance.
          logicalConnection = new ConnectionImpl(this, connection);
          return logicalConnection;
      }
  
      /**
       * Remove an event listener.
       */
      public void removeConnectionEventListener(ConnectionEventListener listener)
      {
          eventListeners.remove(listener);
      }
  
      /**
       * Closes the physical connection and checks that the logical connection
       * was closed as well.
       */
      protected void finalize()
          throws Throwable
      {
          // Closing the Connection ensures that if anyone tries to use it,
          // an error will occur.
          try
          {
              connection.close();
          }
          catch (Exception ignored)
          {
          }
  
          // make sure the last connection is marked as closed
          if ( logicalConnection != null && !logicalConnection.isClosed() ) 
          {
              throw new SQLException("PooledConnection was gc'ed, without" +
                                     "its last Connection being closed.");
          }        
      }
  
      /**
       * sends a connectionClosed event.
       */
      void notifyListeners()
      {
          ConnectionEvent event = new ConnectionEvent(this);
          Iterator i = eventListeners.iterator();
          while ( i.hasNext() ) 
          {
              ((ConnectionEventListener)i.next()).connectionClosed(event);
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to