You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by jm...@apache.org on 2002/05/20 01:28:13 UTC

cvs commit: jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool KeyedCPDSConnectionFactory.java PoolKey.java UserPassKey.java Jdbc2PoolDataSource.java

jmcnally    02/05/19 16:28:13

  Modified:    jdbc2pool/src/java/org/apache/commons/jdbc2pool
                        Jdbc2PoolDataSource.java
  Added:       jdbc2pool/src/java/org/apache/commons/jdbc2pool
                        KeyedCPDSConnectionFactory.java PoolKey.java
                        UserPassKey.java
  Log:
  modified behavior so that if setPerUserMaxActive is not called on a specific
  username, the connections for that user are pooled in a KeyedObjectPool along
  with all the other users who do not have a their own pool defined.
  So defaultMaxActive defines the combined total connections for this default
  pool.
  
  Revision  Changes    Path
  1.6       +212 -75   jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/Jdbc2PoolDataSource.java
  
  Index: Jdbc2PoolDataSource.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/Jdbc2PoolDataSource.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Jdbc2PoolDataSource.java	3 Apr 2002 05:10:46 -0000	1.5
  +++ Jdbc2PoolDataSource.java	19 May 2002 23:28:13 -0000	1.6
  @@ -85,13 +85,16 @@
   import org.apache.commons.lang.Objects;
   import org.apache.commons.pool.ObjectPool;
   import org.apache.commons.pool.impl.GenericObjectPool;
  +import org.apache.commons.pool.KeyedObjectPool;
  +import org.apache.commons.pool.impl.GenericKeyedObjectPool;
  +import org.apache.commons.pool.impl.StackObjectPool;
   
   /**
    * DataSource that pools PooledConnection's from a 
    * ConnectionPoolDataSource.
    *
    * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
  - * @version $Id: Jdbc2PoolDataSource.java,v 1.5 2002/04/03 05:10:46 jmcnally Exp $
  + * @version $Id: Jdbc2PoolDataSource.java,v 1.6 2002/05/19 23:28:13 jmcnally Exp $
    */
   public class Jdbc2PoolDataSource
       implements DataSource, Referenceable, Serializable, ObjectFactory
  @@ -102,6 +105,12 @@
   
       public static Map dsInstanceMap = new HashMap();
   
  +    private static ObjectPool userPassKeyPool = 
  +        new StackObjectPool(new UserPassKey.Factory(), 256);
  +
  +    private static ObjectPool poolKeyPool = 
  +        new StackObjectPool(new PoolKey.Factory(), 256);
  +
       private boolean getConnectionCalled = false;
   
       private ConnectionPoolDataSource cpds;
  @@ -303,7 +312,8 @@
       /**
        * The maximum number of milliseconds that the pool will wait (when there
        * are no available connections) for a connection to be returned before
  -     * throwing an exception, or -1 to wait indefinitely.
  +     * throwing an exception, or -1 to wait indefinitely.  Will fail 
  +     * immediately if value is 0.
        * This value is used for any username which is not specified
        * in perUserMaxWait.  The default is -1.
        */
  @@ -314,7 +324,8 @@
       /**
        * The maximum number of milliseconds that the pool will wait (when there
        * are no available connections) for a connection to be returned before
  -     * throwing an exception, or -1 to wait indefinitely.
  +     * throwing an exception, or -1 to wait indefinitely.  Will fail 
  +     * immediately if value is 0.
        * This value is used for any username which is not specified
        * in perUserMaxWait.  The default is -1.
        */
  @@ -436,6 +447,10 @@
        */
       public PrintWriter getLogWriter() 
       {
  +        if (logWriter == null) 
  +        {
  +            logWriter = new PrintWriter(System.out);
  +        }        
           return logWriter;
       }
       
  @@ -546,7 +561,8 @@
       /**
        * The maximum number of milliseconds that the pool will wait (when there
        * are no available connections) for a connection to be returned before
  -     * throwing an exception, or -1 to wait indefinitely.
  +     * throwing an exception, or -1 to wait indefinitely.  Will fail 
  +     * immediately if value is 0.
        * The keys are usernames and the value is the maximum connections.  Any 
        * username specified here will override the value of defaultMaxWait.
        */
  @@ -563,7 +579,8 @@
       /**
        * The maximum number of milliseconds that the pool will wait (when there
        * are no available connections) for a connection to be returned before
  -     * throwing an exception, or -1 to wait indefinitely.
  +     * throwing an exception, or -1 to wait indefinitely.  Will fail 
  +     * immediately if value is 0.
        * The keys are usernames and the value is the maximum connections.  Any 
        * username specified here will override the value of defaultMaxWait.
        */
  @@ -803,7 +820,6 @@
           return getConnection(null, null);
       }
   
  -    private int connectioncalls=0;
       /**
        * Attempt to establish a database connection.
        */
  @@ -818,39 +834,64 @@
           }
           getConnectionCalled = true;
           Map pools = (Map)dsInstanceMap.get(instanceKey);
  -        String key = getKey(username);
  -        ObjectPool pool = (ObjectPool)pools.get(key);
  +        PoolKey key = getPoolKey(username);
  +        Object pool = pools.get(key);
           if ( pool == null ) 
           {
               try
               {
                   registerPool(username, password);
  -                pool = (ObjectPool)pools.get(key);
  +                pool = pools.get(key);
               }
               catch (Exception e)
               {
  +                e.printStackTrace();
                   throw new SQLException(e.getMessage());
               }
           }
  +        returnPoolKey(key);
   
           PooledConnection pc = null;
  -        try
  +        if (pool instanceof ObjectPool) 
           {
  -            pc = (PooledConnection)pool.borrowObject();
  +            try
  +            {
  +                pc = (PooledConnection)((ObjectPool)pool).borrowObject();
  +            }
  +            catch (Exception e)
  +            {
  +                if (e instanceof RuntimeException) 
  +                {
  +                    throw (RuntimeException)e;
  +                }
  +                else 
  +                {
  +                    throw new SQLException(e.getMessage());
  +                }
  +            }
           }
  -        catch (Exception e)
  -        {
  -            if (e instanceof RuntimeException) 
  +        else // assume KeyedObjectPool
  +        { 
  +            try
               {
  -                throw (RuntimeException)e;
  +                UserPassKey upkey = getPCKey(username, password);
  +                pc = (PooledConnection)
  +                    ((KeyedObjectPool)pool).borrowObject(upkey);
  +                returnPCKey(upkey);
               }
  -            else 
  +            catch (Exception e)
               {
  -                throw new SQLException(e.getMessage());
  +                if (e instanceof RuntimeException) 
  +                {
  +                    throw (RuntimeException)e;
  +                }
  +                else 
  +                {
  +                    throw new SQLException(e.getMessage());
  +                }
               }
           }
  -        Connection con = pc.getConnection();
  -
  +        
           boolean defaultAutoCommit = isDefaultAutoCommit();
           if ( username != null ) 
           {
  @@ -873,21 +914,84 @@
               }
           }    
   
  +        Connection con = pc.getConnection();        
           con.setAutoCommit(defaultAutoCommit);
           con.setReadOnly(defaultReadOnly);
           return con;
       }
   
  -    private String getKey(String suffix)
  +    private UserPassKey getPCKey(String username, String password)
       {
  -        String key = getDataSourceName();
  -        if ( suffix != null ) 
  +        UserPassKey upk = null;
  +        try
           {
  -            key += suffix;            
  +            upk = (UserPassKey)userPassKeyPool.borrowObject();
           }
  +        catch (Exception e)
  +        {
  +            getLogWriter().println("[WARN] Jdbc2PoolDataSource::getPCKey"
  +                + " could not get key from pool. Created a new instance. "
  +                + e.getMessage());
  +            upk = new UserPassKey();
  +        }
  +        upk.init(username, password);
  +        return upk;
  +    }
  +
  +    private void returnPCKey(UserPassKey key)
  +    {
  +        if (key.isReusable()) 
  +        {
  +            try
  +            {
  +                userPassKeyPool.returnObject(key);
  +            }
  +            catch (Exception e)
  +            {
  +                getLogWriter().println(
  +                    "[WARN] Jdbc2PoolDataSource::returnPCKey could not return"
  +                    + " key to pool. " + e.getMessage());
  +            }
  +        }
  +    }
  +
  +    private PoolKey getPoolKey(String username)
  +    {
  +        PoolKey key = null;
  +        try
  +        {
  +            key = (PoolKey)poolKeyPool.borrowObject();
  +        }
  +        catch (Exception e)
  +        {
  +            getLogWriter().println("[WARN] Jdbc2PoolDataSource::getPoolKey"
  +                + " could not get key from pool. Created a new instance. "
  +                + e.getMessage());
  +            key = new PoolKey();
  +        }
  +        if ( username != null && 
  +             (perUserMaxActive == null 
  +              || !perUserMaxActive.containsKey(username)) ) 
  +        {
  +            username = null;
  +        }
  +        key.init(getDataSourceName(), username);
           return key;
       }
   
  +    private void returnPoolKey(PoolKey key)
  +    {
  +        try
  +        {
  +            poolKeyPool.returnObject(key);
  +        }
  +        catch (Exception e)
  +        {
  +            getLogWriter().println(
  +                "[WARN] Jdbc2PoolDataSource::returnPoolKey could not return"
  +                + " key to pool. " + e.getMessage());
  +        }
  +    }
   
       synchronized private void registerInstance()
       {
  @@ -912,52 +1016,14 @@
            throws javax.naming.NamingException
       {
           Map pools = (Map)dsInstanceMap.get(instanceKey);
  -        String key = getKey(username);
  +        PoolKey key = getPoolKey(username);
           if ( !pools.containsKey(key) ) 
           {
               int maxActive = getDefaultMaxActive();
  -            if ( username != null ) 
  -            {
  -                Integer userMax = getPerUserMaxActive(username);
  -                if ( userMax != null ) 
  -                {
  -                    maxActive = userMax.intValue();
  -                }
  -            }    
  -
               int maxIdle = getDefaultMaxIdle();
  -            if ( username != null ) 
  -            {
  -                Integer userMax = getPerUserMaxIdle(username);
  -                if ( userMax != null ) 
  -                {
  -                    maxIdle = userMax.intValue();
  -                }
  -            }    
  -
               int maxWait = getDefaultMaxWait();
  -            if ( username != null ) 
  -            {
  -                Integer userMax = getPerUserMaxIdle(username);
  -                if ( userMax != null ) 
  -                {
  -                    maxWait = userMax.intValue();
  -                }
  -            }    
   
  -            // Create an object pool to contain our active connections
  -            GenericObjectPool pool = new GenericObjectPool(null);
  -            pool.setMaxActive(maxActive);
  -            pool.setMaxIdle(maxIdle);
  -            pool.setMaxWait(maxWait);
  -            pool.setTestOnBorrow(getTestOnBorrow());
  -            pool.setTestOnReturn(getTestOnReturn());
  -            pool.setTimeBetweenEvictionRunsMillis(
  -                getTimeBetweenEvictionRunsMillis());
  -            pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
  -            pool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
  -            pool.setTestWhileIdle(getTestWhileIdle());
  -                        
  +            // The source of physical db connections
               ConnectionPoolDataSource cpds = this.cpds;
               if ( cpds == null ) 
               {            
  @@ -973,17 +1039,92 @@
                   cpds = (ConnectionPoolDataSource)ctx.lookup(dataSourceName);
               }
   
  -            // Set up the factory we will use (passing the pool associates
  -            // the factory with the pool, so we do not have to do so
  -            // explicitly)
  -            new CPDSConnectionFactory(cpds, pool, validationQuery,
  -                                      username, password);
  +            Object whicheverPool = null;
  +            if (perUserMaxActive != null 
  +                && perUserMaxActive.containsKey(username)) 
  +            {                
  +                Integer userMax = getPerUserMaxActive(username);
  +                if ( userMax != null ) 
  +                {
  +                    maxActive = userMax.intValue();
  +                }
  +                userMax = getPerUserMaxIdle(username);
  +                if ( userMax != null ) 
  +                {
  +                    maxIdle = userMax.intValue();
  +                }
  +                userMax = getPerUserMaxWait(username);
  +                if ( userMax != null ) 
  +                {
  +                    maxWait = userMax.intValue();
  +                }
  +
  +                // Create an object pool to contain our PooledConnections
  +                GenericObjectPool pool = new GenericObjectPool(null);
  +                pool.setMaxActive(maxActive);
  +                pool.setMaxIdle(maxIdle);
  +                pool.setMaxWait(maxWait);
  +                pool.setWhenExhaustedAction(
  +                    getWhenExhausted(maxActive, maxWait));
  +                pool.setTestOnBorrow(getTestOnBorrow());
  +                pool.setTestOnReturn(getTestOnReturn());
  +                pool.setTimeBetweenEvictionRunsMillis(
  +                    getTimeBetweenEvictionRunsMillis());
  +                pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
  +                pool.setMinEvictableIdleTimeMillis(
  +                    getMinEvictableIdleTimeMillis());
  +                pool.setTestWhileIdle(getTestWhileIdle());
  +                
  +                // Set up the factory we will use (passing the pool associates
  +                // the factory with the pool, so we do not have to do so
  +                // explicitly)
  +                new CPDSConnectionFactory(cpds, pool, validationQuery,
  +                                          username, password);
  +                whicheverPool = pool;
  +            }
  +            else // use default pool
  +            {
  +                // Create an object pool to contain our PooledConnections
  +                GenericKeyedObjectPool pool = new GenericKeyedObjectPool(null);
  +                pool.setMaxActive(maxActive);
  +                pool.setMaxIdle(maxIdle);
  +                pool.setMaxWait(maxWait);
  +                pool.setWhenExhaustedAction(
  +                    getWhenExhausted(maxActive, maxWait));
  +                pool.setTestOnBorrow(getTestOnBorrow());
  +                pool.setTestOnReturn(getTestOnReturn());
  +                pool.setTimeBetweenEvictionRunsMillis(
  +                    getTimeBetweenEvictionRunsMillis());
  +                pool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
  +                pool.setMinEvictableIdleTimeMillis(
  +                    getMinEvictableIdleTimeMillis());
  +                pool.setTestWhileIdle(getTestWhileIdle());
  +                
  +                // Set up the factory we will use (passing the pool associates
  +                // the factory with the pool, so we do not have to do so
  +                // explicitly)
  +                new KeyedCPDSConnectionFactory(cpds, pool, validationQuery);
  +                whicheverPool = pool;
  +            }
               
               // pools is a FastHashMap set to put the pool in a thread-safe way
  -            pools.put(key, pool);
  +            pools.put(key, whicheverPool);
           }        
       }
  -    
  +
  +    private byte getWhenExhausted(int maxActive, int maxWait)
  +    {
  +        byte whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
  +        if (maxActive <= 0) 
  +        {
  +            whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_GROW;
  +        }
  +        else if (maxWait == 0) 
  +        {
  +            whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
  +        }
  +        return whenExhausted;
  +    }    
   
       // ----------------------------------------------------------------------
       // Referenceable implementation 
  @@ -1337,13 +1478,9 @@
                   }
   
                   ds = this;
  -            }
  -            
  +            }            
           }
           
           return ds;
       }
  -
  -
  -
   }
  
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/KeyedCPDSConnectionFactory.java
  
  Index: KeyedCPDSConnectionFactory.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/KeyedCPDSConnectionFactory.java,v 1.1 2002/05/19 23:28:13 jmcnally Exp $
   * $Revision: 1.1 $
   * $Date: 2002/05/19 23:28:13 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-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 acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Commons", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 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/>.
   *
   */
  
  package org.apache.commons.jdbc2pool;
  
  import java.util.Map;
  import java.util.HashMap;
  import java.util.WeakHashMap;
  import java.sql.*;
  import javax.sql.ConnectionPoolDataSource;
  import javax.sql.PooledConnection;
  import javax.sql.ConnectionEvent;
  import javax.sql.ConnectionEventListener;
  
  import org.apache.commons.pool.*;
  import org.apache.commons.dbcp.*;
  
  /**
   * A {*link PoolableObjectFactory} that creates
   * {*link PoolableConnection}s.
   *
   * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
   * @version $Id: KeyedCPDSConnectionFactory.java,v 1.1 2002/05/19 23:28:13 jmcnally Exp $
   */
  public class KeyedCPDSConnectionFactory 
      implements KeyedPoolableObjectFactory, ConnectionEventListener {
      /**
       * Create a new <tt>KeyedPoolableConnectionFactory</tt>.
       * @param cpds the ConnectionPoolDataSource from which to obtain PooledConnection's
       * @param pool the {*link ObjectPool} in which to pool those {*link Connection}s
       * @param validationQuery a query to use to {*link #validateObject validate} {*link Connection}s.  Should return at least one row. May be <tt>null</tt>
       */
      public KeyedCPDSConnectionFactory(ConnectionPoolDataSource cpds, 
                                        KeyedObjectPool pool, 
                                        String validationQuery) {
          _cpds = cpds;
          _pool = pool;
          _pool.setFactory(this);
          _validationQuery = validationQuery;
      }
  
      /**
       * Sets the {*link ConnectionFactory} from which to obtain base {*link Connection}s.
       * @param connFactory the {*link ConnectionFactory} from which to obtain base {*link Connection}s
       */
      synchronized public void setCPDS(ConnectionPoolDataSource cpds) {
          _cpds = cpds;
      }
  
      /**
       * Sets the query I use to {*link #validateObject validate} {*link Connection}s.
       * Should return at least one row.
       * May be <tt>null</tt>
       * @param validationQuery a query to use to {*link #validateObject validate} {*link Connection}s.
       */
      synchronized public void setValidationQuery(String validationQuery) {
          _validationQuery = validationQuery;
      }
  
      /**
       * Sets the {*link ObjectPool} in which to pool {*link Connection}s.
       * @param pool the {*link ObjectPool} in which to pool those {*link Connection}s
       */
      synchronized public void setPool(KeyedObjectPool pool) 
          throws SQLException
      {
          if(null != _pool && pool != _pool) {
              try
              {
                  _pool.close();
              }
              catch (Exception e)
              {
                  if (e instanceof RuntimeException) 
                  {
                      throw (RuntimeException)e;
                  }
                  else 
                  {
                      throw new SQLException(e.getMessage());
                  }
              }
          }
          _pool = pool;
      }
  
      public KeyedObjectPool getPool() {
          return _pool;
      }
  
      synchronized public Object makeObject(Object key) {
          UserPassKey upkey = (UserPassKey)key;
          // since we are using the key to make a new object, we will
          // declare the key invalid for reuse.
          upkey.setReusable(false);
          String username = upkey.getUsername();
          PooledConnection pc = null;
          try
          {
              if ( username == null ) 
              {
                  pc = _cpds.getPooledConnection();
              }
              else 
              {
                  pc = _cpds.getPooledConnection(username, upkey.getPassword());
              }
              // should we add this object as a listener or the pool.
              // consider the validateObject method in decision
              pc.addConnectionEventListener(this);
              pcKeyMap.put(pc, key);
          }
          catch (SQLException e)
          {
              throw new RuntimeException(e.getMessage());
          }
          return pc;
      }
  
      public void destroyObject(Object key, Object obj) {
          if(obj instanceof PooledConnection) {
              try {
                  ((PooledConnection)obj).close();
              } catch(RuntimeException e) {
                  throw e;
              } catch(SQLException e) {
                  ; // ignored
              }
          }
      }
  
      public boolean validateObject(Object key, Object obj) {
          boolean valid = false;
          if(obj instanceof PooledConnection) {
              PooledConnection pconn = (PooledConnection)obj;
              String query = _validationQuery;
              if(null != query) {
                  Connection conn = null;
                  Statement stmt = null;
                  ResultSet rset = null;
                  // logical Connection from the PooledConnection must be closed
                  // before another one can be requested and closing it will 
                  // generate an event. Keep track so we know not to return
                  // the PooledConnection 
                  validatingMap.put(pconn, null);
                  try {
                      conn = pconn.getConnection();
                      stmt = conn.createStatement();
                      rset = stmt.executeQuery(query);
                      if(rset.next()) {
                          valid = true;
                      } else {
                          valid = false;
                      }
                  } catch(Exception e) {
                      valid = false;
                  }
                  finally 
                  {
                      try {
                          rset.close();
                      } catch(Throwable t) {
                          // ignore
                      }
                      try {
                          stmt.close();
                      } catch(Throwable t) {
                          // ignore
                      }
                      try {
                          conn.close();
                      } catch(Throwable t) {
                          // ignore
                      }
                      validatingMap.remove(pconn);
                  }
              } else {
                  valid = true;
              }
          } else {
              valid = false;
          }
          return valid;
      }
  
      public void passivateObject(Object key, Object obj) {
      }
  
      public void activateObject(Object key, Object obj) {
      }
  
      // ***********************************************************************
      // 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) 
      {
          PooledConnection pc = (PooledConnection)event.getSource();
          // if this event occured becase we were validating, ignore it
          // otherwise return the connection to the pool.
          if (!validatingMap.containsKey(pc)) 
          {
              Object key = pcKeyMap.get(pc);
              if (key == null) 
              {
                  throw new IllegalStateException(NO_KEY_MESSAGE);
              }            
              try
              {
                  _pool.returnObject(key, pc);
              }
              catch (Exception e)
              {
                  destroyObject(key, pc);
                  System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + 
                                     "NOT BE RETURNED TO THE POOL");
              }
          }
      }
  
      /**
       * If a fatal error occurs, close the underlying physical connection so as
       * not to be returned in the future
       */
      public void connectionErrorOccurred(ConnectionEvent event) 
      {
          PooledConnection pc = (PooledConnection)event.getSource();
          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
              pc.removeConnectionEventListener(this);
          }
          catch (Exception ignore) 
          {
              // ignore
          }
  
          Object key = pcKeyMap.get(pc);
          if (key == null) 
          {
              throw new IllegalStateException(NO_KEY_MESSAGE);
          }            
          destroyObject(key, pc);
      }
  
      private static final String NO_KEY_MESSAGE = 
          "close() was called on a Connection, but " + 
          "I have no record of the underlying PooledConnection.";
  
      protected ConnectionPoolDataSource _cpds = null;
      protected String _validationQuery = null;
      protected KeyedObjectPool _pool = null;
      private Map validatingMap = new HashMap();
      private WeakHashMap pcKeyMap = new WeakHashMap();
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/PoolKey.java
  
  Index: PoolKey.java
  ===================================================================
  package org.apache.commons.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 apache@apache.org.
   *
   * 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.io.Serializable;
  import org.apache.commons.lang.Objects;
  import org.apache.commons.pool.BasePoolableObjectFactory;
  
  class PoolKey
      implements Serializable
  {
      private String datasourceName;
      private boolean reusable;
      private String username;
      
      PoolKey()
      {
      }
          
      /* *
       * Get the value of datasourceName.
       * @return value of datasourceName.
       * /
      public String getDatasourceName() 
      {
          return datasourceName;
      }
      
      /* *
       * Set the value of datasourceName.
       * @param v  Value to assign to datasourceName.
       * /
      public void setDatasourceName(String  v) 
      {
          this.datasourceName = v;
      }
      
      /* *
       * Get the value of username.
       * @return value of username.
       * /
      public String getUsername() 
      {
          return username;
      }
      
      /* *
       * Set the value of username.
       * @param v  Value to assign to username.
       * /
      public void setUsername(String  v) 
      {
          this.username = v;
      }
      */    
  
      /**
       * Initialize key for method with no arguments.
       *
       * @param instanceOrClass the Object on which the method is invoked.  if 
       * the method is static, a String representing the class name is used.
       * @param method the method name
       */
      void init(String username, String datasourceName) 
      {
          this.datasourceName = datasourceName;
          this.username = username;
      }
  
      public boolean equals(Object obj)
      {
          boolean equal = false;
          if ( obj instanceof PoolKey ) 
          {
              PoolKey pk = (PoolKey)obj;
              equal = Objects.equals(pk.datasourceName, datasourceName);
              equal &= Objects.equals(pk.username, username);
          }            
  
          return equal;
      }
  
      public int hashCode()
      {
          int h = 0;
          if (datasourceName != null) 
          {
              h += datasourceName.hashCode();
          }
          if (username != null) 
          {
              h += username.hashCode();
          }
          return h;
      }
  
      public String toString()
      {
          StringBuffer sb = new StringBuffer(50);
          sb.append("PoolKey(");
          sb.append(username).append(", ").append(datasourceName);
          sb.append(')');
          return sb.toString();
      }
  
      // ************* PoolableObjectFactory implementation *******************
  
      static class Factory 
          extends BasePoolableObjectFactory
      {
          /**
           * Creates an instance that can be returned by the pool.
           * @return an instance that can be returned by the pool.
           */
          public Object makeObject() 
              throws Exception
          {
              return new PoolKey();
          }
          
          /**
           * Uninitialize an instance to be returned to the pool.
           * @param obj the instance to be passivated
           */
          public void passivateObject(Object obj) 
              throws Exception
          {
              PoolKey key = (PoolKey)obj;
              key.datasourceName = null;
              key.username = null;
          }
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/jdbc2pool/src/java/org/apache/commons/jdbc2pool/UserPassKey.java
  
  Index: UserPassKey.java
  ===================================================================
  package org.apache.commons.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 apache@apache.org.
   *
   * 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.io.Serializable;
  import org.apache.commons.lang.Objects;
  import org.apache.commons.pool.BasePoolableObjectFactory;
  
  class UserPassKey
      implements Serializable
  {
      private String password;
      private boolean reusable;
      private String username;
      
      UserPassKey()
      {
      }
          
      /**
       * Get the value of password.
       * @return value of password.
       */
      public String getPassword() 
      {
          return password;
      }
      
      /**
       * Set the value of password.
       * @param v  Value to assign to password.
       */
      public void setPassword(String  v) 
      {
          this.password = v;
      }
      
      
      /**
       * Get the value of reusable.
       * @return value of reusable.
       */
      public boolean isReusable() 
      {
          return reusable;
      }
      
      /**
       * Set the value of reusable.
       * @param v  Value to assign to reusable.
       */
      public void setReusable(boolean  v) 
      {
          this.reusable = v;
      }
  
      
      /**
       * Get the value of username.
       * @return value of username.
       */
      public String getUsername() 
      {
          return username;
      }
      
      /**
       * Set the value of username.
       * @param v  Value to assign to username.
       */
      public void setUsername(String  v) 
      {
          this.username = v;
      }
      
      /**
       * Initialize key for method with no arguments.
       *
       * @param instanceOrClass the Object on which the method is invoked.  if 
       * the method is static, a String representing the class name is used.
       * @param method the method name
       */
      void init(String username, String password) 
      {
          this.reusable = true;
          this.username = username;
          this.password = password;
      }
  
      public boolean equals(Object obj)
      {
          boolean equal = false;
          if ( obj instanceof UserPassKey ) 
          {
              UserPassKey upk = (UserPassKey)obj;
              equal = Objects.equals(upk.username, username);
          }            
  
          return equal;
      }
  
      public int hashCode()
      {
          int h = 0;
          if (username != null) 
          {
              h = username.hashCode();
          }
          return h;
      }
  
      public String toString()
      {
          StringBuffer sb = new StringBuffer(50);
          sb.append("UserPassKey(");
          sb.append(username).append(", ").append(password)
              .append(", ").append(reusable);
          sb.append(')');
          return sb.toString();
      }
  
      // ************* PoolableObjectFactory implementation *******************
  
      static class Factory 
          extends BasePoolableObjectFactory
      {
          /**
           * Creates an instance that can be returned by the pool.
           * @return an instance that can be returned by the pool.
           */
          public Object makeObject() 
              throws Exception
          {
              return new UserPassKey();
          }
          
          /**
           * Uninitialize an instance to be returned to the pool.
           * @param obj the instance to be passivated
           */
          public void passivateObject(Object obj) 
              throws Exception
          {
              UserPassKey key = (UserPassKey)obj;
              key.username = null;
              key.password = null;
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>