You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2018/06/19 10:30:31 UTC

svn commit: r1833804 [12/16] - in /tomcat/tc8.5.x/trunk: ./ java/org/apache/tomcat/dbcp/dbcp2/ java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ java/org/apache/tomcat/dbcp/dbcp2/datasources/ webapps/docs/

Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java?rev=1833804&r1=1833803&r2=1833804&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java Tue Jun 19 10:30:31 2018
@@ -37,7 +37,9 @@ import javax.naming.spi.ObjectFactory;
 import javax.sql.ConnectionPoolDataSource;
 import javax.sql.PooledConnection;
 
-import org.apache.tomcat.dbcp.dbcp2.PoolablePreparedStatement;
+import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
+import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
+import org.apache.tomcat.dbcp.dbcp2.Utils;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.impl.BaseObjectPoolConfig;
 import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool;
@@ -45,92 +47,79 @@ import org.apache.tomcat.dbcp.pool2.impl
 
 /**
  * <p>
- * An adapter for JDBC drivers that do not include an implementation
- * of {@link javax.sql.ConnectionPoolDataSource}, but still include a
- * {@link java.sql.DriverManager} implementation.
- * <code>ConnectionPoolDataSource</code>s are not used within general
- * applications.  They are used by <code>DataSource</code> implementations
- * that pool <code>Connection</code>s, such as
- * {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}.  A J2EE
- * container will normally provide some method of initializing the
- * <code>ConnectionPoolDataSource</code> whose attributes are presented
- * as bean getters/setters and then deploying it via JNDI.  It is then
- * available as a source of physical connections to the database, when
- * the pooling <code>DataSource</code> needs to create a new
- * physical connection.
+ * An adapter for JDBC drivers that do not include an implementation of {@link javax.sql.ConnectionPoolDataSource}, but
+ * still include a {@link java.sql.DriverManager} implementation. <code>ConnectionPoolDataSource</code>s are not used
+ * within general applications. They are used by <code>DataSource</code> implementations that pool
+ * <code>Connection</code>s, such as {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}. A J2EE container
+ * will normally provide some method of initializing the <code>ConnectionPoolDataSource</code> whose attributes are
+ * presented as bean getters/setters and then deploying it via JNDI. It is then available as a source of physical
+ * connections to the database, when the pooling <code>DataSource</code> needs to create a new physical connection.
  * </p>
- *
  * <p>
- * Although normally used within a JNDI environment, the DriverAdapterCPDS
- * can be instantiated and initialized as any bean and then attached
- * directly to a pooling <code>DataSource</code>.
- * <code>Jdbc2PoolDataSource</code> can use the
+ * Although normally used within a JNDI environment, the DriverAdapterCPDS can be instantiated and initialized as any
+ * bean and then attached directly to a pooling <code>DataSource</code>. <code>Jdbc2PoolDataSource</code> can use the
  * <code>ConnectionPoolDataSource</code> with or without the use of JNDI.
  * </p>
- *
  * <p>
- * The DriverAdapterCPDS also provides <code>PreparedStatement</code> pooling
- * which is not generally available in jdbc2
- * <code>ConnectionPoolDataSource</code> implementation, but is
- * addressed within the jdbc3 specification.  The <code>PreparedStatement</code>
- * pool in DriverAdapterCPDS has been in the dbcp package for some time, but
- * it has not undergone extensive testing in the configuration used here.
- * It should be considered experimental and can be toggled with the
- * poolPreparedStatements attribute.
+ * The DriverAdapterCPDS also provides <code>PreparedStatement</code> pooling which is not generally available in jdbc2
+ * <code>ConnectionPoolDataSource</code> implementation, but is addressed within the jdbc3 specification. The
+ * <code>PreparedStatement</code> pool in DriverAdapterCPDS has been in the dbcp package for some time, but it has not
+ * undergone extensive testing in the configuration used here. It should be considered experimental and can be toggled
+ * with the poolPreparedStatements attribute.
  * </p>
- *
  * <p>
- * The <a href="package-summary.html">package documentation</a> contains an
- * example using catalina and JNDI.  The <a
- * href="../datasources/package-summary.html">datasources package documentation</a>
- * shows how to use <code>DriverAdapterCPDS</code> as a source for
- * <code>Jdbc2PoolDataSource</code> without the use of JNDI.
+ * The <a href="package-summary.html">package documentation</a> contains an example using catalina and JNDI. The
+ * <a href="../datasources/package-summary.html">datasources package documentation</a> shows how to use
+ * <code>DriverAdapterCPDS</code> as a source for <code>Jdbc2PoolDataSource</code> without the use of JNDI.
  * </p>
  *
- * @author John D. McNally
  * @since 2.0
  */
-public class DriverAdapterCPDS
-    implements ConnectionPoolDataSource, Referenceable, Serializable,
-               ObjectFactory {
+public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceable, Serializable, ObjectFactory {
 
-    private static final long serialVersionUID = -4820523787212147844L;
+    private static final String KEY_USER = "user";
 
+    private static final String KEY_PASSWORD = "password";
 
-    private static final String GET_CONNECTION_CALLED
-            = "A PooledConnection was already requested from this source, "
+    private static final long serialVersionUID = -4820523787212147844L;
+
+    private static final String GET_CONNECTION_CALLED = "A PooledConnection was already requested from this source, "
             + "further initialization is not allowed.";
 
     /** Description */
     private String description;
-    /** Password */
-    private String password;
+
     /** Url name */
     private String url;
+
     /** User name */
-    private String user;
+    private String userName;
+
+    /** User password */
+    private char[] userPassword;
+
     /** Driver class name */
     private String driver;
 
     /** Login TimeOut in seconds */
     private int loginTimeout;
+
     /** Log stream. NOT USED */
-    private transient PrintWriter logWriter = null;
+    private transient PrintWriter logWriter;
 
     // PreparedStatement pool properties
     private boolean poolPreparedStatements;
     private int maxIdle = 10;
-    private long _timeBetweenEvictionRunsMillis =
-            BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
-    private int _numTestsPerEvictionRun = -1;
-    private int _minEvictableIdleTimeMillis = -1;
-    private int _maxPreparedStatements = -1;
+    private long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
+    private int numTestsPerEvictionRun = -1;
+    private int minEvictableIdleTimeMillis = -1;
+    private int maxPreparedStatements = -1;
 
     /** Whether or not getConnection has been called */
-    private volatile boolean getConnectionCalled = false;
+    private volatile boolean getConnectionCalled;
 
     /** Connection properties passed to JDBC Driver */
-    private Properties connectionProperties = null;
+    private Properties connectionProperties;
 
     static {
         // Attempt to prevent deadlocks - see DBCP - 272
@@ -140,7 +129,7 @@ public class DriverAdapterCPDS
     /**
      * Controls access to the underlying connection
      */
-    private boolean accessToUnderlyingConnectionAllowed = false;
+    private boolean accessToUnderlyingConnectionAllowed;
 
     /**
      * Default no-arg constructor for Serialization
@@ -149,8 +138,7 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Attempt to establish a database connection using the default
-     * user and password.
+     * Attempts to establish a database connection using the default user and password.
      */
     @Override
     public PooledConnection getPooledConnection() throws SQLException {
@@ -159,68 +147,65 @@ public class DriverAdapterCPDS
 
     /**
      * Attempt to establish a database connection.
-     * @param username name to be used for the connection
-     * @param pass password to be used fur the connection
+     *
+     * @param pooledUserName
+     *            name to be used for the connection
+     * @param pooledUserPassword
+     *            password to be used fur the connection
      */
     @Override
-    public PooledConnection getPooledConnection(final String username, final String pass)
+    public PooledConnection getPooledConnection(final String pooledUserName, final String pooledUserPassword)
             throws SQLException {
         getConnectionCalled = true;
-        PooledConnectionImpl pci = null;
-        // Workaround for buggy WebLogic 5.1 classloader - ignore the
-        // exception upon first invocation.
+        PooledConnectionImpl pooledConnection = null;
+        // Workaround for buggy WebLogic 5.1 classloader - ignore the exception upon first invocation.
         try {
             if (connectionProperties != null) {
-                connectionProperties.put("user", username);
-                connectionProperties.put("password", pass);
-                pci = new PooledConnectionImpl(DriverManager.getConnection(
-                        getUrl(), connectionProperties));
+                update(connectionProperties, KEY_USER, pooledUserName);
+                update(connectionProperties, KEY_PASSWORD, pooledUserPassword);
+                pooledConnection = new PooledConnectionImpl(
+                        DriverManager.getConnection(getUrl(), connectionProperties));
             } else {
-                pci = new PooledConnectionImpl(DriverManager.getConnection(
-                        getUrl(), username, pass));
+                pooledConnection = new PooledConnectionImpl(
+                        DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
             }
-            pci.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
-        }
-        catch (final ClassCircularityError e)
-        {
+            pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
+        } catch (final ClassCircularityError e) {
             if (connectionProperties != null) {
-                pci = new PooledConnectionImpl(DriverManager.getConnection(
-                        getUrl(), connectionProperties));
+                pooledConnection = new PooledConnectionImpl(
+                        DriverManager.getConnection(getUrl(), connectionProperties));
             } else {
-                pci = new PooledConnectionImpl(DriverManager.getConnection(
-                        getUrl(), username, pass));
+                pooledConnection = new PooledConnectionImpl(
+                        DriverManager.getConnection(getUrl(), pooledUserName, pooledUserPassword));
             }
-            pci.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
+            pooledConnection.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
         }
-        KeyedObjectPool<PStmtKeyCPDS, PoolablePreparedStatement<PStmtKeyCPDS>> stmtPool = null;
+        KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = null;
         if (isPoolPreparedStatements()) {
-            final GenericKeyedObjectPoolConfig<PoolablePreparedStatement<PStmtKeyCPDS>> config = new GenericKeyedObjectPoolConfig<>();
+            final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
             config.setMaxTotalPerKey(Integer.MAX_VALUE);
             config.setBlockWhenExhausted(false);
             config.setMaxWaitMillis(0);
             config.setMaxIdlePerKey(getMaxIdle());
-            if (getMaxPreparedStatements() <= 0)
-            {
-                // since there is no limit, create a prepared statement pool with an eviction thread
-                //  evictor settings are the same as the connection pool settings.
+            if (getMaxPreparedStatements() <= 0) {
+                // since there is no limit, create a prepared statement pool with an eviction thread;
+                // evictor settings are the same as the connection pool settings.
                 config.setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
                 config.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
                 config.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
-            }
-            else
-            {
-                // since there is limit, create a prepared statement pool without an eviction thread
-                //  pool has LRU functionality so when the limit is reached, 15% of the pool is cleared.
-                // see org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool.clearOldest method
+            } else {
+                // since there is a limit, create a prepared statement pool without an eviction thread;
+                // pool has LRU functionality so when the limit is reached, 15% of the pool is cleared.
+                // see org.apache.commons.pool2.impl.GenericKeyedObjectPool.clearOldest method
                 config.setMaxTotal(getMaxPreparedStatements());
                 config.setTimeBetweenEvictionRunsMillis(-1);
                 config.setNumTestsPerEvictionRun(0);
                 config.setMinEvictableIdleTimeMillis(0);
             }
-            stmtPool = new GenericKeyedObjectPool<>(pci, config);
-            pci.setStatementPool(stmtPool);
+            stmtPool = new GenericKeyedObjectPool<>(pooledConnection, config);
+            pooledConnection.setStatementPool(stmtPool);
         }
-        return pci;
+        return pooledConnection;
     }
 
     @Override
@@ -243,29 +228,21 @@ public class DriverAdapterCPDS
 
         ref.add(new StringRefAddr("description", getDescription()));
         ref.add(new StringRefAddr("driver", getDriver()));
-        ref.add(new StringRefAddr("loginTimeout",
-                                  String.valueOf(getLoginTimeout())));
-        ref.add(new StringRefAddr("password", getPassword()));
-        ref.add(new StringRefAddr("user", getUser()));
+        ref.add(new StringRefAddr("loginTimeout", String.valueOf(getLoginTimeout())));
+        ref.add(new StringRefAddr(KEY_PASSWORD, getPassword()));
+        ref.add(new StringRefAddr(KEY_USER, getUser()));
         ref.add(new StringRefAddr("url", getUrl()));
 
-        ref.add(new StringRefAddr("poolPreparedStatements",
-                                  String.valueOf(isPoolPreparedStatements())));
-        ref.add(new StringRefAddr("maxIdle",
-                                  String.valueOf(getMaxIdle())));
-        ref.add(new StringRefAddr("timeBetweenEvictionRunsMillis",
-            String.valueOf(getTimeBetweenEvictionRunsMillis())));
-        ref.add(new StringRefAddr("numTestsPerEvictionRun",
-            String.valueOf(getNumTestsPerEvictionRun())));
-        ref.add(new StringRefAddr("minEvictableIdleTimeMillis",
-            String.valueOf(getMinEvictableIdleTimeMillis())));
-        ref.add(new StringRefAddr("maxPreparedStatements",
-            String.valueOf(getMaxPreparedStatements())));
+        ref.add(new StringRefAddr("poolPreparedStatements", String.valueOf(isPoolPreparedStatements())));
+        ref.add(new StringRefAddr("maxIdle", String.valueOf(getMaxIdle())));
+        ref.add(new StringRefAddr("timeBetweenEvictionRunsMillis", String.valueOf(getTimeBetweenEvictionRunsMillis())));
+        ref.add(new StringRefAddr("numTestsPerEvictionRun", String.valueOf(getNumTestsPerEvictionRun())));
+        ref.add(new StringRefAddr("minEvictableIdleTimeMillis", String.valueOf(getMinEvictableIdleTimeMillis())));
+        ref.add(new StringRefAddr("maxPreparedStatements", String.valueOf(getMaxPreparedStatements())));
 
         return ref;
     }
 
-
     // ----------------------------------------------------------------------
     // ObjectFactory implementation
 
@@ -273,14 +250,13 @@ public class DriverAdapterCPDS
      * implements ObjectFactory to create an instance of this class
      */
     @Override
-    public Object getObjectInstance(final Object refObj, final Name name,
-                                    final Context context, final Hashtable<?,?> env)
-            throws Exception {
+    public Object getObjectInstance(final Object refObj, final Name name, final Context context,
+            final Hashtable<?, ?> env) throws Exception {
         // The spec says to return null if we can't create an instance
         // of the reference
         DriverAdapterCPDS cpds = null;
         if (refObj instanceof Reference) {
-            final Reference ref = (Reference)refObj;
+            final Reference ref = (Reference) refObj;
             if (ref.getClassName().equals(getClass().getName())) {
                 RefAddr ra = ref.get("description");
                 if (ra != null && ra.getContent() != null) {
@@ -295,19 +271,18 @@ public class DriverAdapterCPDS
                 if (ra != null && ra.getContent() != null) {
                     setUrl(ra.getContent().toString());
                 }
-                ra = ref.get("user");
+                ra = ref.get(KEY_USER);
                 if (ra != null && ra.getContent() != null) {
                     setUser(ra.getContent().toString());
                 }
-                ra = ref.get("password");
+                ra = ref.get(KEY_PASSWORD);
                 if (ra != null && ra.getContent() != null) {
                     setPassword(ra.getContent().toString());
                 }
 
                 ra = ref.get("poolPreparedStatements");
                 if (ra != null && ra.getContent() != null) {
-                    setPoolPreparedStatements(Boolean.valueOf(
-                        ra.getContent().toString()).booleanValue());
+                    setPoolPreparedStatements(Boolean.valueOf(ra.getContent().toString()).booleanValue());
                 }
                 ra = ref.get("maxIdle");
                 if (ra != null && ra.getContent() != null) {
@@ -316,31 +291,26 @@ public class DriverAdapterCPDS
 
                 ra = ref.get("timeBetweenEvictionRunsMillis");
                 if (ra != null && ra.getContent() != null) {
-                    setTimeBetweenEvictionRunsMillis(
-                        Integer.parseInt(ra.getContent().toString()));
+                    setTimeBetweenEvictionRunsMillis(Integer.parseInt(ra.getContent().toString()));
                 }
 
                 ra = ref.get("numTestsPerEvictionRun");
                 if (ra != null && ra.getContent() != null) {
-                    setNumTestsPerEvictionRun(
-                        Integer.parseInt(ra.getContent().toString()));
+                    setNumTestsPerEvictionRun(Integer.parseInt(ra.getContent().toString()));
                 }
 
                 ra = ref.get("minEvictableIdleTimeMillis");
                 if (ra != null && ra.getContent() != null) {
-                    setMinEvictableIdleTimeMillis(
-                        Integer.parseInt(ra.getContent().toString()));
+                    setMinEvictableIdleTimeMillis(Integer.parseInt(ra.getContent().toString()));
                 }
                 ra = ref.get("maxPreparedStatements");
                 if (ra != null && ra.getContent() != null) {
-                    setMaxPreparedStatements(
-                        Integer.parseInt(ra.getContent().toString()));
+                    setMaxPreparedStatements(Integer.parseInt(ra.getContent().toString()));
                 }
 
                 ra = ref.get("accessToUnderlyingConnectionAllowed");
                 if (ra != null && ra.getContent() != null) {
-                    setAccessToUnderlyingConnectionAllowed(
-                            Boolean.valueOf(ra.getContent().toString()).booleanValue());
+                    setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(ra.getContent().toString()).booleanValue());
                 }
 
                 cpds = this;
@@ -350,8 +320,7 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Throws an IllegalStateException, if a PooledConnection has already
-     * been requested.
+     * Throws an IllegalStateException, if a PooledConnection has already been requested.
      */
     private void assertInitializationAllowed() throws IllegalStateException {
         if (getConnectionCalled) {
@@ -372,35 +341,40 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * <p>Sets the connection properties passed to the JDBC driver.</p>
-     *
-     * <p>If <code>props</code> contains "user" and/or "password"
-     * properties, the corresponding instance properties are set. If these
-     * properties are not present, they are filled in using
-     * {@link #getUser()}, {@link #getPassword()} when {@link #getPooledConnection()}
-     * is called, or using the actual parameters to the method call when
-     * {@link #getPooledConnection(String, String)} is called. Calls to
-     * {@link #setUser(String)} or {@link #setPassword(String)} overwrite the values
-     * of these properties if <code>connectionProperties</code> is not null.</p>
+     * <p>
+     * Sets the connection properties passed to the JDBC driver.
+     * </p>
      *
-     * @param props Connection properties to use when creating new connections.
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * <p>
+     * If <code>props</code> contains "user" and/or "password" properties, the corresponding instance properties are
+     * set. If these properties are not present, they are filled in using {@link #getUser()}, {@link #getPassword()}
+     * when {@link #getPooledConnection()} is called, or using the actual parameters to the method call when
+     * {@link #getPooledConnection(String, String)} is called. Calls to {@link #setUser(String)} or
+     * {@link #setPassword(String)} overwrite the values of these properties if <code>connectionProperties</code> is not
+     * null.
+     * </p>
+     *
+     * @param props
+     *            Connection properties to use when creating new connections.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
     public void setConnectionProperties(final Properties props) {
         assertInitializationAllowed();
         connectionProperties = props;
-        if (connectionProperties.containsKey("user")) {
-            setUser(connectionProperties.getProperty("user"));
-        }
-        if (connectionProperties.containsKey("password")) {
-            setPassword(connectionProperties.getProperty("password"));
+        if (connectionProperties != null) {
+            if (connectionProperties.containsKey(KEY_USER)) {
+                setUser(connectionProperties.getProperty(KEY_USER));
+            }
+            if (connectionProperties.containsKey(KEY_PASSWORD)) {
+                setPassword(connectionProperties.getProperty(KEY_PASSWORD));
+            }
         }
     }
 
     /**
-     * Gets the value of description.  This property is here for use by
-     * the code which will deploy this datasource.  It is not used
-     * internally.
+     * Gets 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, may be null.
      * @see #setDescription(String)
@@ -410,39 +384,66 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Sets the value of description.  This property is here for use by
-     * the code which will deploy this datasource.  It is not used
-     * internally.
+     * Sets 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.
+     * @param v
+     *            Value to assign to description.
      */
-    public void setDescription(final String  v) {
+    public void setDescription(final String v) {
         this.description = v;
     }
 
     /**
      * Gets the value of password for the default user.
+     *
+     * @return value of password.
+     * @since 2.4.0
+     */
+    public char[] getPasswordCharArray() {
+        return userPassword;
+    }
+
+    /**
+     * Gets the value of password for the default user.
+     *
      * @return value of password.
      */
     public String getPassword() {
-        return password;
+        return Utils.toString(userPassword);
     }
 
     /**
      * Sets the value of password for the default user.
-     * @param v  Value to assign to password.
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     *
+     * @param userPassword
+     *            Value to assign to password.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public void setPassword(final String v) {
+    public void setPassword(final char[] userPassword) {
         assertInitializationAllowed();
-        this.password = v;
-        if (connectionProperties != null) {
-            connectionProperties.setProperty("password", v);
-        }
+        this.userPassword = userPassword;
+        update(connectionProperties, KEY_PASSWORD, Utils.toString(userPassword));
+    }
+
+    /**
+     * Sets the value of password for the default user.
+     *
+     * @param userPassword
+     *            Value to assign to password.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
+     */
+    public void setPassword(final String userPassword) {
+        assertInitializationAllowed();
+        this.userPassword = Utils.toCharArray(userPassword);
+        update(connectionProperties, KEY_PASSWORD, userPassword);
     }
 
     /**
      * Gets the value of url used to locate the database for this datasource.
+     *
      * @return value of url.
      */
     public String getUrl() {
@@ -451,37 +452,43 @@ public class DriverAdapterCPDS
 
     /**
      * Sets the value of URL string used to locate the database for this datasource.
-     * @param v  Value to assign to url.
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
-    */
+     *
+     * @param v
+     *            Value to assign to url.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
+     */
     public void setUrl(final String v) {
         assertInitializationAllowed();
         this.url = v;
     }
 
     /**
-     * Gets the value of default user (login or username).
+     * Gets the value of default user (login or user name).
+     *
      * @return value of user.
      */
     public String getUser() {
-        return user;
+        return userName;
     }
 
     /**
-     * Sets the value of default user (login or username).
-     * @param v  Value to assign to user.
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * Sets the value of default user (login or user name).
+     *
+     * @param v
+     *            Value to assign to user.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
     public void setUser(final String v) {
         assertInitializationAllowed();
-        this.user = v;
-        if (connectionProperties != null) {
-            connectionProperties.setProperty("user", v);
-        }
+        this.userName = v;
+        update(connectionProperties, KEY_USER, v);
     }
 
     /**
-     * Gets the driver classname.
+     * Gets the driver class name.
+     *
      * @return value of driver.
      */
     public String getDriver() {
@@ -489,11 +496,15 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Sets the driver classname.  Setting the driver classname cause the
-     * driver to be registered with the DriverManager.
-     * @param v  Value to assign to driver.
-     * @throws ClassNotFoundException Driver class was not found
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * Sets the driver class name. Setting the driver class name cause the driver to be registered with the
+     * DriverManager.
+     *
+     * @param v
+     *            Value to assign to driver.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
+     * @throws ClassNotFoundException
+     *             if the class cannot be located
      */
     public void setDriver(final String v) throws ClassNotFoundException {
         assertInitializationAllowed();
@@ -503,8 +514,8 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Gets the maximum time in seconds that this data source can wait
-     * while attempting to connect to a database. NOT USED.
+     * Gets the maximum time in seconds that this data source can wait while attempting to connect to a database. NOT
+     * USED.
      */
     @Override
     public int getLoginTimeout() {
@@ -520,8 +531,8 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Sets the maximum time in seconds that this data source will wait
-     * while attempting to connect to a database. NOT USED.
+     * Sets the maximum time in seconds that this data source will wait while attempting to connect to a database. NOT
+     * USED.
      */
     @Override
     public void setLoginTimeout(final int seconds) {
@@ -536,13 +547,12 @@ public class DriverAdapterCPDS
         logWriter = out;
     }
 
-
     // ------------------------------------------------------------------
     // PreparedStatement pool properties
 
-
     /**
      * Flag to toggle the pooling of <code>PreparedStatement</code>s
+     *
      * @return value of poolPreparedStatements.
      */
     public boolean isPoolPreparedStatements() {
@@ -551,17 +561,21 @@ public class DriverAdapterCPDS
 
     /**
      * Flag to toggle the pooling of <code>PreparedStatement</code>s
-     * @param v  true to pool statements.
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     *
+     * @param poolPreparedStatements
+     *            true to pool statements.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public void setPoolPreparedStatements(final boolean v) {
+    public void setPoolPreparedStatements(final boolean poolPreparedStatements) {
         assertInitializationAllowed();
-        this.poolPreparedStatements = v;
+        this.poolPreparedStatements = poolPreparedStatements;
     }
 
     /**
-     * Gets the maximum number of statements that can remain idle in the
-     * pool, without extra ones being released, or negative for no limit.
+     * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or
+     * negative for no limit.
+     *
      * @return the value of maxIdle
      */
     public int getMaxIdle() {
@@ -569,11 +583,13 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Gets the maximum number of statements that can remain idle in the
-     * pool, without extra ones being released, or negative for no limit.
+     * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or
+     * negative for no limit.
      *
-     * @param maxIdle The maximum number of statements that can remain idle
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * @param maxIdle
+     *            The maximum number of statements that can remain idle
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
     public void setMaxIdle(final int maxIdle) {
         assertInitializationAllowed();
@@ -581,107 +597,106 @@ public class DriverAdapterCPDS
     }
 
     /**
-     * Gets the number of milliseconds to sleep between runs of the
-     * idle object evictor thread.
-     * When non-positive, no idle object evictor thread will be
-     * run.
+     * Gets the number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no
+     * idle object evictor thread will be run.
+     *
      * @return the value of the evictor thread timer
      * @see #setTimeBetweenEvictionRunsMillis(long)
      */
     public long getTimeBetweenEvictionRunsMillis() {
-        return _timeBetweenEvictionRunsMillis;
+        return timeBetweenEvictionRunsMillis;
     }
 
     /**
-     * Sets the number of milliseconds to sleep between runs of the
-     * idle object evictor thread.
-     * When non-positive, no idle object evictor thread will be
-     * run.
-     * @param timeBetweenEvictionRunsMillis The time between runs
+     * Sets the number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no
+     * idle object evictor thread will be run.
+     *
+     * @param timeBetweenEvictionRunsMillis
+     *            The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive,
+     *            no idle object evictor thread will be run.
      * @see #getTimeBetweenEvictionRunsMillis()
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public void setTimeBetweenEvictionRunsMillis(
-            final long timeBetweenEvictionRunsMillis) {
+    public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
         assertInitializationAllowed();
-        _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
     }
 
     /**
-     * Gets the number of statements to examine during each run of the
-     * idle object evictor thread (if any).
+     * Gets the number of statements to examine during each run of the idle object evictor thread (if any.)
      *
-     * @see #setNumTestsPerEvictionRun(int)
-     * @see #setTimeBetweenEvictionRunsMillis(long)
-     * @return the number of statements
+     * @see #setNumTestsPerEvictionRun
+     * @see #setTimeBetweenEvictionRunsMillis
+     * @return the number of statements to examine during each run of the idle object evictor thread (if any.)
      */
     public int getNumTestsPerEvictionRun() {
-        return _numTestsPerEvictionRun;
+        return numTestsPerEvictionRun;
     }
 
     /**
-     * Sets the number of statements to examine during each run of the
-     * idle object evictor thread (if any).
+     * Sets the number of statements to examine during each run of the idle object evictor thread (if any).
      * <p>
-     * When a negative value is supplied, <tt>ceil({*link #numIdle})/abs({*link #getNumTestsPerEvictionRun})</tt>
-     * tests will be run.  I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
-     * idle objects will be tested per run.
+     * When a negative value is supplied, <tt>ceil({*link #numIdle})/abs({*link #getNumTestsPerEvictionRun})</tt> tests
+     * will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the idle objects will be tested per
+     * run.
+     * </p>
      *
-     * @param numTestsPerEvictionRun number of statements to examine per run
+     * @param numTestsPerEvictionRun
+     *            number of statements to examine per run
      * @see #getNumTestsPerEvictionRun()
      * @see #setTimeBetweenEvictionRunsMillis(long)
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
     public void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) {
         assertInitializationAllowed();
-        _numTestsPerEvictionRun = numTestsPerEvictionRun;
+        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
     }
 
     /**
-     * Gets the minimum amount of time a statement may sit idle in the pool
-     * before it is eligible for eviction by the idle object evictor
-     * (if any).
+     * Gets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the
+     * idle object evictor (if any).
      *
-     * @see #setMinEvictableIdleTimeMillis(int)
-     * @see #setTimeBetweenEvictionRunsMillis(long)
-     * @return the amount of time
+     * @see #setMinEvictableIdleTimeMillis
+     * @see #setTimeBetweenEvictionRunsMillis
+     * @return the minimum amount of time a statement may sit idle in the pool.
      */
     public int getMinEvictableIdleTimeMillis() {
-        return _minEvictableIdleTimeMillis;
+        return minEvictableIdleTimeMillis;
     }
 
     /**
-     * Sets the minimum amount of time a statement may sit idle in the pool
-     * before it is eligible for eviction by the idle object evictor
-     * (if any).
-     * When non-positive, no objects will be evicted from the pool
-     * due to idle time alone.
-     * @param minEvictableIdleTimeMillis minimum time to set (in ms)
+     * Sets the minimum amount of time a statement may sit idle in the pool before it is eligible for eviction by the
+     * idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle time alone.
+     *
+     * @param minEvictableIdleTimeMillis
+     *            minimum time to set (in ms)
      * @see #getMinEvictableIdleTimeMillis()
      * @see #setTimeBetweenEvictionRunsMillis(long)
-     * @throws IllegalStateException if {@link #getPooledConnection()} has been called
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
     public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) {
         assertInitializationAllowed();
-        _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
     }
 
     /**
      * Returns the value of the accessToUnderlyingConnectionAllowed property.
      *
-     * @return <code>true</code> if access to the underlying is allowed,
-     *  <code>false</code> otherwise.
+     * @return true if access to the underlying is allowed, false otherwise.
      */
     public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
         return this.accessToUnderlyingConnectionAllowed;
     }
 
     /**
-     * Sets the value of the accessToUnderlyingConnectionAllowed property.
-     * It controls if the PoolGuard allows access to the underlying connection.
-     * (Default: false)
+     * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
+     * the underlying connection. (Default: false)
      *
-     * @param allow Access to the underlying connection is granted when true.
+     * @param allow
+     *            Access to the underlying connection is granted when true.
      */
     public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
         this.accessToUnderlyingConnectionAllowed = allow;
@@ -692,18 +707,27 @@ public class DriverAdapterCPDS
      *
      * @return maxPrepartedStatements value
      */
-    public int getMaxPreparedStatements()
-    {
-        return _maxPreparedStatements;
+    public int getMaxPreparedStatements() {
+        return maxPreparedStatements;
     }
 
     /**
      * Sets the maximum number of prepared statements.
-     * @param maxPreparedStatements the new maximum number of prepared
-     * statements
+     *
+     * @param maxPreparedStatements
+     *            the new maximum number of prepared statements
      */
-    public void setMaxPreparedStatements(final int maxPreparedStatements)
-    {
-        _maxPreparedStatements = maxPreparedStatements;
+    public void setMaxPreparedStatements(final int maxPreparedStatements) {
+        this.maxPreparedStatements = maxPreparedStatements;
+    }
+
+    private void update(final Properties properties, final String key, final String value) {
+        if (properties != null) {
+            if (value == null) {
+                properties.remove(key);
+            } else {
+                properties.setProperty(key, value);
+            }
+        }
     }
 }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java?rev=1833804&r1=1833803&r2=1833804&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java Tue Jun 19 10:30:31 2018
@@ -16,122 +16,38 @@
  */
 package org.apache.tomcat.dbcp.dbcp2.cpdsadapter;
 
-import java.util.Arrays;
-
 import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
 
 /**
  * A key uniquely identifying a {@link java.sql.PreparedStatement PreparedStatement}.
+ *
  * @since 2.0
+ * @deprecated Use {@link PStmtKey}.
  */
+@Deprecated
 public class PStmtKeyCPDS extends PStmtKey {
-    private final Integer _resultSetHoldability;
-    private final int _columnIndexes[];
-    private final String _columnNames[];
-
     public PStmtKeyCPDS(final String sql) {
         super(sql);
-        _resultSetHoldability = null;
-        _columnIndexes = null;
-        _columnNames = null;
     }
 
     public PStmtKeyCPDS(final String sql, final int autoGeneratedKeys) {
         super(sql, null, autoGeneratedKeys);
-        _resultSetHoldability = null;
-        _columnIndexes = null;
-        _columnNames = null;
     }
 
     public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency) {
         super(sql, resultSetType, resultSetConcurrency);
-        _resultSetHoldability = null;
-        _columnIndexes = null;
-        _columnNames = null;
     }
 
     public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability) {
         super(sql, resultSetType, resultSetConcurrency);
-        _resultSetHoldability = Integer.valueOf(resultSetHoldability);
-        _columnIndexes = null;
-        _columnNames = null;
     }
 
     public PStmtKeyCPDS(final String sql, final int columnIndexes[]) {
-        super(sql);
-        _columnIndexes = Arrays.copyOf(columnIndexes, columnIndexes.length);
-        _resultSetHoldability = null;
-        _columnNames = null;
+        super(sql, null, columnIndexes);
     }
 
     public PStmtKeyCPDS(final String sql, final String columnNames[]) {
-        super(sql);
-        _columnNames = Arrays.copyOf(columnNames, columnNames.length);
-        _resultSetHoldability = null;
-        _columnIndexes = null;
-    }
-
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final PStmtKeyCPDS other = (PStmtKeyCPDS) obj;
-        if (!Arrays.equals(_columnIndexes, other._columnIndexes)) {
-            return false;
-        }
-        if (!Arrays.equals(_columnNames, other._columnNames)) {
-            return false;
-        }
-        if (_resultSetHoldability == null) {
-            if (other._resultSetHoldability != null) {
-                return false;
-            }
-        } else if (!_resultSetHoldability.equals(other._resultSetHoldability)) {
-            return false;
-        }
-        return true;
-    }
-
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(_columnIndexes);
-        result = prime * result + Arrays.hashCode(_columnNames);
-        result = prime * result + (_resultSetHoldability == null ? 0 : _resultSetHoldability.hashCode());
-        return result;
-    }
-
-
-    @Override
-    public String toString() {
-        final StringBuffer buf = new StringBuffer();
-        buf.append("PStmtKey: sql=");
-        buf.append(getSql());
-        buf.append(", catalog=");
-        buf.append(getCatalog());
-        buf.append(", resultSetType=");
-        buf.append(getResultSetType());
-        buf.append(", resultSetConcurrency=");
-        buf.append(getResultSetConcurrency());
-        buf.append(", statementType=");
-        buf.append(getStmtType());
-        buf.append(", resultSetHoldability=");
-        buf.append(_resultSetHoldability);
-        buf.append(", columnIndexes=");
-        buf.append(Arrays.toString(_columnIndexes));
-        buf.append(", columnNames=");
-        buf.append(Arrays.toString(_columnNames));
-        return buf.toString();
+        super(sql, null, columnNames);
     }
 }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java?rev=1833804&r1=1833803&r2=1833804&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java Tue Jun 19 10:30:31 2018
@@ -17,6 +17,7 @@
 
 package org.apache.tomcat.dbcp.dbcp2.cpdsadapter;
 
+import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
@@ -28,67 +29,69 @@ import javax.sql.PooledConnection;
 import javax.sql.StatementEventListener;
 
 import org.apache.tomcat.dbcp.dbcp2.DelegatingConnection;
+import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement;
+import org.apache.tomcat.dbcp.dbcp2.PStmtKey;
+import org.apache.tomcat.dbcp.dbcp2.PoolableCallableStatement;
 import org.apache.tomcat.dbcp.dbcp2.PoolablePreparedStatement;
+import org.apache.tomcat.dbcp.dbcp2.PoolingConnection.StatementType;
 import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
 import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory;
 import org.apache.tomcat.dbcp.pool2.PooledObject;
 import org.apache.tomcat.dbcp.pool2.impl.DefaultPooledObject;
 
 /**
- * Implementation of PooledConnection that is returned by
- * PooledConnectionDataSource.
+ * Implementation of PooledConnection that is returned by PooledConnectionDataSource.
  *
- * @author John D. McNally
  * @since 2.0
  */
 class PooledConnectionImpl
-        implements PooledConnection, KeyedPooledObjectFactory<PStmtKeyCPDS, PoolablePreparedStatement<PStmtKeyCPDS>> {
+        implements PooledConnection, KeyedPooledObjectFactory<PStmtKey, DelegatingPreparedStatement> {
 
-    private static final String CLOSED
-            = "Attempted to use PooledConnection after closed() was called.";
+    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;
+    private Connection connection;
 
     /**
-     * A DelegatingConnection used to create a PoolablePreparedStatementStub
+     * A DelegatingConnection used to create a PoolablePreparedStatementStub.
      */
     private final DelegatingConnection<?> delegatingConnection;
 
     /**
      * The JDBC database logical connection.
      */
-    private Connection logicalConnection = null;
+    private Connection logicalConnection;
 
     /**
-     * ConnectionEventListeners
+     * ConnectionEventListeners.
      */
     private final Vector<ConnectionEventListener> eventListeners;
 
     /**
-     * StatementEventListeners
+     * StatementEventListeners.
      */
-    private final Vector<StatementEventListener> statementEventListeners =
-            new Vector<>();
+    private final Vector<StatementEventListener> statementEventListeners = new Vector<>();
 
     /**
-     * flag set to true, once close() is called.
+     * Flag set to true, once {@link #close()} is called.
      */
-    private boolean isClosed;
+    private boolean closed;
 
     /** My pool of {@link PreparedStatement}s. */
-    private KeyedObjectPool<PStmtKeyCPDS, PoolablePreparedStatement<PStmtKeyCPDS>> pstmtPool = null;
+    private KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pStmtPool;
 
     /**
-     * Controls access to the underlying connection
+     * Controls access to the underlying connection.
      */
-    private boolean accessToUnderlyingConnectionAllowed = false;
+    private boolean accessToUnderlyingConnectionAllowed;
 
     /**
-     * Wrap the real connection.
-     * @param connection the connection to be wrapped
+     * Wraps the real connection.
+     *
+     * @param connection
+     *            the connection to be wrapped.
      */
     PooledConnectionImpl(final Connection connection) {
         this.connection = connection;
@@ -98,12 +101,21 @@ class PooledConnectionImpl
             this.delegatingConnection = new DelegatingConnection<>(connection);
         }
         eventListeners = new Vector<>();
-        isClosed = false;
+        closed = false;
     }
 
-    public void setStatementPool(
-            final KeyedObjectPool<PStmtKeyCPDS, PoolablePreparedStatement<PStmtKeyCPDS>> statementPool) {
-        pstmtPool = statementPool;
+    /**
+     * My {@link KeyedPooledObjectFactory} method for activating {@link PreparedStatement}s.
+     *
+     * @param key
+     *            Ignored.
+     * @param pooledObject
+     *            Ignored.
+     */
+    @Override
+    public void activateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
+            throws Exception {
+        pooledObject.getObject().activate();
     }
 
     /**
@@ -126,22 +138,31 @@ class PooledConnectionImpl
     /* JDBC_4_ANT_KEY_END */
 
     /**
-     * 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.
+     * Throws an SQLException, if isClosed is true
+     */
+    private void assertOpen() throws SQLException {
+        if (closed) {
+            throw new SQLException(CLOSED);
+        }
+    }
+
+    /**
+     * 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.
      *
-     * @throws SQLException if an error occurs or the connection is already closed
+     * @throws SQLException
+     *             Thrown when an error occurs or the connection is already closed.
      */
     @Override
     public void close() throws SQLException {
         assertOpen();
-        isClosed = true;
+        closed = true;
         try {
-            if (pstmtPool != null) {
+            if (pStmtPool != null) {
                 try {
-                    pstmtPool.close();
+                    pStmtPool.close();
                 } finally {
-                    pstmtPool = null;
+                    pStmtPool = null;
                 }
             }
         } catch (final RuntimeException e) {
@@ -158,11 +179,115 @@ class PooledConnectionImpl
     }
 
     /**
-     * Throws an SQLException, if isClosed is true
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
      */
-    private void assertOpen() throws SQLException {
-        if (isClosed) {
-            throw new SQLException(CLOSED);
+    protected PStmtKey createKey(final String sql) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull());
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), autoGeneratedKeys);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final int columnIndexes[]) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnIndexes);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
+                resultSetHoldability);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     *
+     * @since 2.4.0
+     */
+    protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability, final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
+                resultSetHoldability, statementType);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     *
+     * @since 2.4.0
+     */
+    protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
+            final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency, statementType);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), statementType);
+    }
+
+    /**
+     * Creates a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
+     */
+    protected PStmtKey createKey(final String sql, final String columnNames[]) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnNames);
+    }
+
+    /**
+     * My {@link KeyedPooledObjectFactory} method for destroying {@link PreparedStatement}s.
+     *
+     * @param key
+     *            ignored
+     * @param pooledObject
+     *            the wrapped {@link PreparedStatement} to be destroyed.
+     */
+    @Override
+    public void destroyObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
+            throws Exception {
+        pooledObject.getObject().getInnermostDelegate().close();
+    }
+
+    /**
+     * Closes the physical connection and checks that the logical connection was closed as well.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        // Closing the Connection ensures that if anyone tries to use it,
+        // an error will occur.
+        try {
+            connection.close();
+        } catch (final Exception ignored) {
+            // ignore
+        }
+
+        // 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.");
+        }
+    }
+
+    private String getCatalogOrNull() {
+        try {
+            return connection == null ? null : connection.getCatalog();
+        } catch (final SQLException e) {
+            return null;
         }
     }
 
@@ -170,7 +295,8 @@ class PooledConnectionImpl
      * Returns a JDBC connection.
      *
      * @return The database connection.
-     * @throws SQLException if the connection is not open or the previous logical connection is still open
+     * @throws SQLException
+     *             if the connection is not open or the previous logical connection is still open
      */
     @Override
     public Connection getConnection() throws SQLException {
@@ -179,54 +305,58 @@ class PooledConnectionImpl
         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.");
+            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, isAccessToUnderlyingConnectionAllowed());
+        logicalConnection = new ConnectionImpl(this, connection, isAccessToUnderlyingConnectionAllowed());
         return logicalConnection;
     }
 
     /**
-     * {@inheritDoc}
+     * Returns the value of the accessToUnderlyingConnectionAllowed property.
+     *
+     * @return true if access to the underlying is allowed, false otherwise.
      */
-    @Override
-    public void removeConnectionEventListener(
-            final ConnectionEventListener listener) {
-        eventListeners.remove(listener);
-    }
-
-    /* JDBC_4_ANT_KEY_BEGIN */
-    @Override
-    public void removeStatementEventListener(final StatementEventListener listener) {
-        statementEventListeners.remove(listener);
+    public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
+        return this.accessToUnderlyingConnectionAllowed;
     }
-    /* JDBC_4_ANT_KEY_END */
 
     /**
-     * Closes the physical connection and checks that the logical connection
-     * was closed as well.
+     * My {@link KeyedPooledObjectFactory} method for creating {@link PreparedStatement}s.
+     *
+     * @param key
+     *            The key for the {@link PreparedStatement} to be created.
      */
+    @SuppressWarnings("resource")
     @Override
-    protected void finalize() throws Throwable {
-        // Closing the Connection ensures that if anyone tries to use it,
-        // an error will occur.
-        try {
-            connection.close();
-        } catch (final Exception ignored) {
+    public PooledObject<DelegatingPreparedStatement> makeObject(final PStmtKey key) throws Exception {
+        if (null == key) {
+            throw new IllegalArgumentException("Prepared statement key is null or invalid.");
         }
-
-        // 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.");
+        if (key.getStmtType() == StatementType.PREPARED_STATEMENT) {
+            final PreparedStatement statement = (PreparedStatement) key.createStatement(connection);
+            @SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this
+            final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool,
+                    delegatingConnection);
+            return new DefaultPooledObject<DelegatingPreparedStatement>(pps);
         }
+        final CallableStatement statement = (CallableStatement) key.createStatement(connection);
+        @SuppressWarnings("unchecked")
+        final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool,
+                (DelegatingConnection<Connection>) delegatingConnection);
+        return new DefaultPooledObject<DelegatingPreparedStatement>(pcs);
     }
 
     /**
-     * sends a connectionClosed event.
+     * Normalizes the given SQL statement, producing a canonical form that is semantically equivalent to the original.
+     */
+    protected String normalizeSQL(final String sql) {
+        return sql.trim();
+    }
+
+    /**
+     * Sends a connectionClosed event.
      */
     void notifyListeners() {
         final ConnectionEvent event = new ConnectionEvent(this);
@@ -236,52 +366,132 @@ class PooledConnectionImpl
         }
     }
 
-    // -------------------------------------------------------------------
-    // The following code implements a PreparedStatement pool
+    /**
+     * My {@link KeyedPooledObjectFactory} method for passivating {@link PreparedStatement}s. Currently invokes
+     * {@link PreparedStatement#clearParameters}.
+     *
+     * @param key
+     *            ignored
+     * @param pooledObject
+     *            a wrapped {@link PreparedStatement}
+     */
+    @Override
+    public void passivateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject)
+            throws Exception {
+        @SuppressWarnings("resource")
+        final DelegatingPreparedStatement dps = pooledObject.getObject();
+        dps.clearParameters();
+        dps.passivate();
+    }
 
     /**
-     * Create or obtain a {@link PreparedStatement} from my pool.
-     * @param sql the SQL statement
-     * @return a {@link PoolablePreparedStatement}
+     * Creates or obtains a {@link CallableStatement} from my pool.
+     *
+     * @param sql
+     *            an SQL statement that may contain one or more '?' parameter placeholders. Typically this statement is
+     *            specified using JDBC call escape syntax.
+     * @return a default <code>CallableStatement</code> object containing the pre-compiled SQL statement.
+     * @exception SQLException
+     *                Thrown if a database access error occurs or this method is called on a closed connection.
+     * @since 2.4.0
+     */
+    CallableStatement prepareCall(final String sql) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareCall(sql);
+        }
+        try {
+            return (CallableStatement) pStmtPool.borrowObject(createKey(sql, StatementType.CALLABLE_STATEMENT));
+        } catch (final RuntimeException e) {
+            throw e;
+        } catch (final Exception e) {
+            throw new SQLException("Borrow prepareCall from pool failed", e);
+        }
+    }
+
+    /**
+     * Creates or obtains a {@link CallableStatement} from my pool.
+     *
+     * @param sql
+     *            a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+     *            more '?' parameters.
+     * @param resultSetType
+     *            a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @return a <code>CallableStatement</code> object containing the pre-compiled SQL statement that will produce
+     *         <code>ResultSet</code> objects with the given type and concurrency.
+     * @throws SQLException
+     *             Thrown if a database access error occurs, this method is called on a closed connection or the given
+     *             parameters are not <code>ResultSet</code> constants indicating type and concurrency.
+     * @since 2.4.0
      */
-    PreparedStatement prepareStatement(final String sql) throws SQLException {
-        if (pstmtPool == null) {
-            return connection.prepareStatement(sql);
+    CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency)
+            throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
         }
         try {
-            return pstmtPool.borrowObject(createKey(sql));
+            return (CallableStatement) pStmtPool.borrowObject(
+                    createKey(sql, resultSetType, resultSetConcurrency, StatementType.CALLABLE_STATEMENT));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
-            throw new SQLException("Borrow prepareStatement from pool failed", e);
+            throw new SQLException("Borrow prepareCall from pool failed", e);
         }
     }
 
     /**
-     * Create or obtain a {@link PreparedStatement} from my pool.
-     * @param sql a <code>String</code> object that is the SQL statement to
-     *            be sent to the database; may contain one or more '?' IN
-     *            parameters
-     * @param resultSetType a result set type; one of
-     *         <code>ResultSet.TYPE_FORWARD_ONLY</code>,
-     *         <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
-     *         <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
-     * @param resultSetConcurrency a concurrency type; one of
-     *         <code>ResultSet.CONCUR_READ_ONLY</code> or
-     *         <code>ResultSet.CONCUR_UPDATABLE</code>
+     * Creates or obtains a {@link CallableStatement} from my pool.
      *
+     * @param sql
+     *            a <code>String</code> object that is the SQL statement to be sent to the database; may contain on or
+     *            more '?' parameters.
+     * @param resultSetType
+     *            one of the following <code>ResultSet</code> constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            one of the following <code>ResultSet</code> constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @param resultSetHoldability
+     *            one of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
+     *            or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+     * @return a new <code>CallableStatement</code> object, containing the pre-compiled SQL statement, that will
+     *         generate <code>ResultSet</code> objects with the given type, concurrency, and holdability.
+     * @throws SQLException
+     *             Thrown if a database access error occurs, this method is called on a closed connection or the given
+     *             parameters are not <code>ResultSet</code> constants indicating type, concurrency, and holdability.
+     * @since 2.4.0
+     */
+    CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+        }
+        try {
+            return (CallableStatement) pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency,
+                    resultSetHoldability, StatementType.CALLABLE_STATEMENT));
+        } catch (final RuntimeException e) {
+            throw e;
+        } catch (final Exception e) {
+            throw new SQLException("Borrow prepareCall from pool failed", e);
+        }
+    }
+
+    /**
+     * Creates or obtains a {@link PreparedStatement} from my pool.
+     *
+     * @param sql
+     *            the SQL statement.
      * @return a {@link PoolablePreparedStatement}
-     * @see Connection#prepareStatement(String, int, int)
      */
-    PreparedStatement prepareStatement(final String sql, final int resultSetType,
-                                       final int resultSetConcurrency)
-            throws SQLException {
-        if (pstmtPool == null) {
-            return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
+    PreparedStatement prepareStatement(final String sql) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareStatement(sql);
         }
         try {
-            return pstmtPool.borrowObject(
-                    createKey(sql,resultSetType,resultSetConcurrency));
+            return pStmtPool.borrowObject(createKey(sql));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
@@ -290,23 +500,22 @@ class PooledConnectionImpl
     }
 
     /**
-     * Create or obtain a {@link PreparedStatement} from my pool.
-     * @param sql an SQL statement that may contain one or more '?' IN
-     *        parameter placeholders
-     * @param autoGeneratedKeys a flag indicating whether auto-generated keys
-     *        should be returned; one of
-     *        <code>Statement.RETURN_GENERATED_KEYS</code> or
-     *        <code>Statement.NO_GENERATED_KEYS</code>
+     * Creates or obtains a {@link PreparedStatement} from my pool.
+     *
+     * @param sql
+     *            an SQL statement that may contain one or more '?' IN parameter placeholders.
+     * @param autoGeneratedKeys
+     *            a flag indicating whether auto-generated keys should be returned; one of
+     *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
      * @return a {@link PoolablePreparedStatement}
      * @see Connection#prepareStatement(String, int)
      */
-    PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys)
-            throws SQLException {
-        if (pstmtPool == null) {
+    PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
+        if (pStmtPool == null) {
             return connection.prepareStatement(sql, autoGeneratedKeys);
         }
         try {
-            return pstmtPool.borrowObject(createKey(sql,autoGeneratedKeys));
+            return pStmtPool.borrowObject(createKey(sql, autoGeneratedKeys));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
@@ -314,16 +523,12 @@ class PooledConnectionImpl
         }
     }
 
-    PreparedStatement prepareStatement(final String sql, final int resultSetType,
-            final int resultSetConcurrency, final int resultSetHoldability)
-    throws SQLException {
-        if (pstmtPool == null) {
-            return connection.prepareStatement(sql, resultSetType,
-                    resultSetConcurrency, resultSetHoldability);
+    PreparedStatement prepareStatement(final String sql, final int columnIndexes[]) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareStatement(sql, columnIndexes);
         }
         try {
-            return pstmtPool.borrowObject(createKey(sql, resultSetType,
-                    resultSetConcurrency, resultSetHoldability));
+            return pStmtPool.borrowObject(createKey(sql, columnIndexes));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
@@ -331,13 +536,29 @@ class PooledConnectionImpl
         }
     }
 
-    PreparedStatement prepareStatement(final String sql, final int columnIndexes[])
-    throws SQLException {
-        if (pstmtPool == null) {
-            return connection.prepareStatement(sql, columnIndexes);
+    /**
+     * Creates or obtains a {@link PreparedStatement} from my pool.
+     *
+     * @param sql
+     *            a <code>String</code> object that is the SQL statement to be sent to the database; may contain one or
+     *            more '?' IN parameters.
+     * @param resultSetType
+     *            a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            a concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     *
+     * @return a {@link PoolablePreparedStatement}.
+     * @see Connection#prepareStatement(String, int, int)
+     */
+    PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency)
+            throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
         }
         try {
-            return pstmtPool.borrowObject(createKey(sql, columnIndexes));
+            return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
@@ -345,13 +566,13 @@ class PooledConnectionImpl
         }
     }
 
-    PreparedStatement prepareStatement(final String sql, final String columnNames[])
-    throws SQLException {
-        if (pstmtPool == null) {
-            return connection.prepareStatement(sql, columnNames);
+    PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
         }
         try {
-            return pstmtPool.borrowObject(createKey(sql, columnNames));
+            return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
         } catch (final RuntimeException e) {
             throw e;
         } catch (final Exception e) {
@@ -359,161 +580,60 @@ class PooledConnectionImpl
         }
     }
 
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql, final int autoGeneratedKeys) {
-        return new PStmtKeyCPDS(normalizeSQL(sql), autoGeneratedKeys);
-    }
-
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql, final int resultSetType,
-            final int resultSetConcurrency, final int resultSetHoldability) {
-        return new PStmtKeyCPDS(normalizeSQL(sql), resultSetType,
-                resultSetConcurrency, resultSetHoldability);
-    }
-
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql, final int columnIndexes[]) {
-        return new PStmtKeyCPDS(normalizeSQL(sql), columnIndexes);
-    }
-
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql, final String columnNames[]) {
-        return new PStmtKeyCPDS(normalizeSQL(sql), columnNames);
-    }
-
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql, final int resultSetType,
-                               final int resultSetConcurrency) {
-        return new PStmtKeyCPDS(normalizeSQL(sql), resultSetType,
-                            resultSetConcurrency);
-    }
-
-    /**
-     * Create a {@link PooledConnectionImpl.PStmtKey} for the given arguments.
-     */
-    protected PStmtKeyCPDS createKey(final String sql) {
-        return new PStmtKeyCPDS(normalizeSQL(sql));
-    }
-
-    /**
-     * Normalize the given SQL statement, producing a
-     * canonical form that is semantically equivalent to the original.
-     */
-    protected String normalizeSQL(final String sql) {
-        return sql.trim();
-    }
-
-    /**
-     * My {@link KeyedPooledObjectFactory} method for creating
-     * {@link PreparedStatement}s.
-     * @param key the key for the {@link PreparedStatement} to be created
-     */
-    @Override
-    public PooledObject<PoolablePreparedStatement<PStmtKeyCPDS>> makeObject(final PStmtKeyCPDS key) throws Exception {
-        if (null == key) {
-            throw new IllegalArgumentException();
+    PreparedStatement prepareStatement(final String sql, final String columnNames[]) throws SQLException {
+        if (pStmtPool == null) {
+            return connection.prepareStatement(sql, columnNames);
         }
-        // _openPstmts++;
-        if (null == key.getResultSetType()
-                && null == key.getResultSetConcurrency()) {
-            if (null == key.getAutoGeneratedKeys()) {
-                return new DefaultPooledObject<>(new PoolablePreparedStatement<>(
-                        connection.prepareStatement(key.getSql()),
-                        key, pstmtPool, delegatingConnection));
-            }
-            return new DefaultPooledObject<>(new PoolablePreparedStatement<>(
-                            connection.prepareStatement(key.getSql(),
-                                    key.getAutoGeneratedKeys().intValue()),
-                            key, pstmtPool, delegatingConnection));
+        try {
+            return pStmtPool.borrowObject(createKey(sql, columnNames));
+        } catch (final RuntimeException e) {
+            throw e;
+        } catch (final Exception e) {
+            throw new SQLException("Borrow prepareStatement from pool failed", e);
         }
-        return new DefaultPooledObject<>(new PoolablePreparedStatement<>(
-                connection.prepareStatement(key.getSql(),
-                        key.getResultSetType().intValue(),
-                        key.getResultSetConcurrency().intValue()),
-                        key, pstmtPool, delegatingConnection));
-    }
-
-    /**
-     * My {@link KeyedPooledObjectFactory} method for destroying
-     * {@link PreparedStatement}s.
-     * @param key ignored
-     * @param p the wrapped {@link PreparedStatement} to be destroyed.
-     */
-    @Override
-    public void destroyObject(final PStmtKeyCPDS key,
-            final PooledObject<PoolablePreparedStatement<PStmtKeyCPDS>> p)
-            throws Exception {
-        p.getObject().getInnermostDelegate().close();
     }
 
     /**
-     * My {@link KeyedPooledObjectFactory} method for validating
-     * {@link PreparedStatement}s.
-     * @param key ignored
-     * @param p ignored
-     * @return {@code true}
+     * {@inheritDoc}
      */
     @Override
-    public boolean validateObject(final PStmtKeyCPDS key,
-            final PooledObject<PoolablePreparedStatement<PStmtKeyCPDS>> p) {
-        return true;
+    public void removeConnectionEventListener(final ConnectionEventListener listener) {
+        eventListeners.remove(listener);
     }
 
-    /**
-     * My {@link KeyedPooledObjectFactory} method for activating
-     * {@link PreparedStatement}s.
-     * @param key ignored
-     * @param p ignored
-     */
+    /* JDBC_4_ANT_KEY_BEGIN */
     @Override
-    public void activateObject(final PStmtKeyCPDS key,
-            final PooledObject<PoolablePreparedStatement<PStmtKeyCPDS>> p)
-            throws Exception {
-        p.getObject().activate();
+    public void removeStatementEventListener(final StatementEventListener listener) {
+        statementEventListeners.remove(listener);
     }
+    /* JDBC_4_ANT_KEY_END */
 
     /**
-     * My {@link KeyedPooledObjectFactory} method for passivating
-     * {@link PreparedStatement}s.  Currently invokes {@link PreparedStatement#clearParameters}.
-     * @param key ignored
-     * @param p a wrapped {@link PreparedStatement}
+     * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
+     * the underlying connection. (Default: false.)
+     *
+     * @param allow
+     *            Access to the underlying connection is granted when true.
      */
-    @Override
-    public void passivateObject(final PStmtKeyCPDS key,
-            final PooledObject<PoolablePreparedStatement<PStmtKeyCPDS>> p)
-            throws Exception {
-        final PoolablePreparedStatement<PStmtKeyCPDS> ppss = p.getObject();
-        ppss.clearParameters();
-        ppss.passivate();
+    public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
+        this.accessToUnderlyingConnectionAllowed = allow;
     }
 
-    /**
-     * Returns the value of the accessToUnderlyingConnectionAllowed property.
-     *
-     * @return true if access to the underlying is allowed, false otherwise.
-     */
-    public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
-        return this.accessToUnderlyingConnectionAllowed;
+    public void setStatementPool(final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> statementPool) {
+        pStmtPool = statementPool;
     }
 
     /**
-     * Sets the value of the accessToUnderlyingConnectionAllowed property.
-     * It controls if the PoolGuard allows access to the underlying connection.
-     * (Default: false)
+     * My {@link KeyedPooledObjectFactory} method for validating {@link PreparedStatement}s.
      *
-     * @param allow Access to the underlying connection is granted when true.
+     * @param key
+     *            Ignored.
+     * @param pooledObject
+     *            Ignored.
+     * @return {@code true}
      */
-    public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
-        this.accessToUnderlyingConnectionAllowed = allow;
+    @Override
+    public boolean validateObject(final PStmtKey key, final PooledObject<DelegatingPreparedStatement> pooledObject) {
+        return true;
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org