You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2019/07/31 01:25:37 UTC

[commons-dbcp] branch master updated (35863ae -> 5800833)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git.


    from 35863ae  [DBCP-553] org.apache.commons.dbcp2.PoolablePreparedStatement.passivate() should close ALL of its resources even when an exception occurs.
     new 1918a44  [DBCP-554] org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs.
     new e001b18  Format nit.
     new 5800833  Extract commons code into new private methods and sort methods. Remove trailing whitespace. Javadoc.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/changes/changes.xml                            |   3 +
 .../apache/commons/dbcp2/DelegatingConnection.java |   3 +-
 .../commons/dbcp2/PoolableCallableStatement.java   |  21 +-
 .../commons/dbcp2/PoolablePreparedStatement.java   |   2 +
 .../dbcp2/cpdsadapter/DriverAdapterCPDS.java       | 675 +++++++++++----------
 5 files changed, 367 insertions(+), 337 deletions(-)


[commons-dbcp] 01/03: [DBCP-554] org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git

commit 1918a4419cdb7a6776a8ec5121a070ea1f2277b9
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jul 30 21:12:03 2019 -0400

    [DBCP-554]
    org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should
    close ALL of its resources even when an exception occurs.
---
 src/changes/changes.xml                             |  3 +++
 .../commons/dbcp2/PoolableCallableStatement.java    | 21 ++++++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 99132a4..66eb615 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -133,6 +133,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action dev="ggregory" type="update" issue="DBCP-553" due-to="Gary Gregory">
         org.apache.commons.dbcp2.PoolablePreparedStatement.passivate() should close ALL of its resources even when an exception occurs.
       </action>
+      <action dev="ggregory" type="update" issue="DBCP-554" due-to="Gary Gregory">
+        org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs.
+      </action>
     </release>
     <release version="2.6.0" date="2019-02-14" description="This is a minor release, including bug fixes and enhancements.">
       <action dev="chtompki" type="add" issue="DBCP-534" due-to="Peter Wicks">
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java b/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
index 717e7b2..8efcefd 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
@@ -21,6 +21,7 @@ import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.pool2.KeyedObjectPool;
@@ -119,13 +120,23 @@ public class PoolableCallableStatement extends DelegatingCallableStatement {
         // ResultSet's when it is closed.
         // FIXME The PreparedStatement we're wrapping should handle this for us.
         // See DBCP-10 for what could happen when ResultSets are closed twice.
-        final List<AbandonedTrace> resultSets = getTrace();
-        if (resultSets != null) {
-            final ResultSet[] set = resultSets.toArray(new ResultSet[resultSets.size()]);
-            for (final ResultSet element : set) {
-                element.close();
+        final List<AbandonedTrace> resultSetList = getTrace();
+        if (resultSetList != null) {
+            final List<Exception> thrown = new ArrayList<>();
+            final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]);
+            for (final ResultSet resultSet : resultSets) {
+                if (resultSet != null) {
+                    try {
+                        resultSet.close();
+                    } catch (Exception e) {
+                        thrown.add(e);
+                    }
+                }
             }
             clearTrace();
+            if (!thrown.isEmpty()) {
+                throw new SQLExceptionList(thrown);
+            }
         }
 
         super.passivate();


[commons-dbcp] 02/03: Format nit.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git

commit e001b18bae6a4278baae9e28333b510444d5ca9f
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jul 30 21:12:18 2019 -0400

    Format nit.
---
 src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java b/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
index 456f5ab..91386b0 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
@@ -30,6 +30,7 @@ import org.apache.commons.pool2.KeyedObjectPool;
  * {@link PreparedStatement}s.
  * <p>
  * My {@link #close} method returns me to my containing pool. (See {@link PoolingConnection}.)
+ * </p>
  *
  * @param <K>
  *            the key type
@@ -38,6 +39,7 @@ import org.apache.commons.pool2.KeyedObjectPool;
  * @since 2.0
  */
 public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
+    
     /**
      * The {@link KeyedObjectPool} from which I was obtained.
      */


[commons-dbcp] 03/03: Extract commons code into new private methods and sort methods. Remove trailing whitespace. Javadoc.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git

commit 580083315e87d7ba320640d14f58075f059496f5
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jul 30 21:25:31 2019 -0400

    Extract commons code into new private methods and sort methods.
    Remove trailing whitespace.
    Javadoc.
---
 .../apache/commons/dbcp2/DelegatingConnection.java |   3 +-
 .../commons/dbcp2/PoolablePreparedStatement.java   |   2 +-
 .../dbcp2/cpdsadapter/DriverAdapterCPDS.java       | 675 +++++++++++----------
 3 files changed, 347 insertions(+), 333 deletions(-)

diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
index 02b5ac1..a5518c3 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
@@ -253,7 +253,8 @@ public class DelegatingConnection<C extends Connection> extends AbandonedTrace i
     /**
      * Handles the given {@code SQLException}.
      *
-     * @param e       The SQLException
+     * @param <T> The throwable type.
+     * @param e   The SQLException
      * @return the given {@code SQLException}
      * @since 2.7.0
      */
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java b/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
index 91386b0..7dbbe49 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolablePreparedStatement.java
@@ -39,7 +39,7 @@ import org.apache.commons.pool2.KeyedObjectPool;
  * @since 2.0
  */
 public class PoolablePreparedStatement<K> extends DelegatingPreparedStatement {
-    
+
     /**
      * The {@link KeyedObjectPool} from which I was obtained.
      */
diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
index d039a49..bd3d297 100644
--- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
+++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
@@ -86,6 +86,11 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     private static final String GET_CONNECTION_CALLED = "A PooledConnection was already requested from this source, "
             + "further initialization is not allowed.";
 
+    static {
+        // Attempt to prevent deadlocks - see DBCP - 272
+        DriverManager.getDrivers();
+    }
+
     /** Description */
     private String description;
 
@@ -106,13 +111,13 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
 
     /** Log stream. NOT USED */
     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;
 
     /** Whether or not getConnection has been called */
@@ -121,11 +126,6 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     /** Connection properties passed to JDBC Driver */
     private Properties connectionProperties;
 
-    static {
-        // Attempt to prevent deadlocks - see DBCP - 272
-        DriverManager.getDrivers();
-    }
-
     /**
      * Controls access to the underlying connection
      */
@@ -138,6 +138,208 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     }
 
     /**
+     * Throws an IllegalStateException, if a PooledConnection has already been requested.
+     */
+    private void assertInitializationAllowed() throws IllegalStateException {
+        if (getConnectionCalled) {
+            throw new IllegalStateException(GET_CONNECTION_CALLED);
+        }
+    }
+
+    private boolean getBooleanContentString(RefAddr ra) {
+        return Boolean.valueOf(getStringContent(ra)).booleanValue();
+    }
+
+    /**
+     * Gets the connection properties passed to the JDBC driver.
+     *
+     * @return the JDBC connection properties used when creating connections.
+     */
+    public Properties getConnectionProperties() {
+        return connectionProperties;
+    }
+
+    /**
+     * 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)
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Gets the driver class name.
+     *
+     * @return value of driver.
+     */
+    public String getDriver() {
+        return driver;
+    }
+
+    private int getIntegerStringContent(final RefAddr ra) {
+        return Integer.parseInt(getStringContent(ra));
+    }
+
+    /**
+     * 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() {
+        return loginTimeout;
+    }
+
+    /**
+     * Gets the log writer for this data source. NOT USED.
+     */
+    @Override
+    public PrintWriter getLogWriter() {
+        return logWriter;
+    }
+
+    /**
+     * 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() {
+        return this.maxIdle;
+    }
+
+    /**
+     * Gets the maximum number of prepared statements.
+     *
+     * @return maxPrepartedStatements value
+     */
+    public int getMaxPreparedStatements() {
+        return maxPreparedStatements;
+    }
+
+    /**
+     * 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
+     * @see #setTimeBetweenEvictionRunsMillis
+     * @return the minimum amount of time a statement may sit idle in the pool.
+     */
+    public int getMinEvictableIdleTimeMillis() {
+        return minEvictableIdleTimeMillis;
+    }
+
+    /**
+     * Gets the number of statements to examine during each run of the idle object evictor thread (if any.)
+     *
+     * @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;
+    }
+
+    /**
+     * Implements {@link 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 {
+        // 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;
+            if (ref.getClassName().equals(getClass().getName())) {
+                RefAddr ra = ref.get("description");
+                if (isNotEmpty(ra)) {
+                    setDescription(getStringContent(ra));
+                }
+
+                ra = ref.get("driver");
+                if (isNotEmpty(ra)) {
+                    setDriver(getStringContent(ra));
+                }
+                ra = ref.get("url");
+                if (isNotEmpty(ra)) {
+                    setUrl(getStringContent(ra));
+                }
+                ra = ref.get(KEY_USER);
+                if (isNotEmpty(ra)) {
+                    setUser(getStringContent(ra));
+                }
+                ra = ref.get(KEY_PASSWORD);
+                if (isNotEmpty(ra)) {
+                    setPassword(getStringContent(ra));
+                }
+
+                ra = ref.get("poolPreparedStatements");
+                if (isNotEmpty(ra)) {
+                    setPoolPreparedStatements(getBooleanContentString(ra));
+                }
+                ra = ref.get("maxIdle");
+                if (isNotEmpty(ra)) {
+                    setMaxIdle(getIntegerStringContent(ra));
+                }
+
+                ra = ref.get("timeBetweenEvictionRunsMillis");
+                if (isNotEmpty(ra)) {
+                    setTimeBetweenEvictionRunsMillis(getIntegerStringContent(ra));
+                }
+
+                ra = ref.get("numTestsPerEvictionRun");
+                if (isNotEmpty(ra)) {
+                    setNumTestsPerEvictionRun(getIntegerStringContent(ra));
+                }
+
+                ra = ref.get("minEvictableIdleTimeMillis");
+                if (isNotEmpty(ra)) {
+                    setMinEvictableIdleTimeMillis(getIntegerStringContent(ra));
+                }
+                ra = ref.get("maxPreparedStatements");
+                if (isNotEmpty(ra)) {
+                    setMaxPreparedStatements(getIntegerStringContent(ra));
+                }
+
+                ra = ref.get("accessToUnderlyingConnectionAllowed");
+                if (isNotEmpty(ra)) {
+                    setAccessToUnderlyingConnectionAllowed(getBooleanContentString(ra));
+                }
+
+                cpds = this;
+            }
+        }
+        return cpds;
+    }
+
+    @Override
+    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+        throw new SQLFeatureNotSupportedException();
+    }
+
+    /**
+     * Gets the value of password for the default user.
+     *
+     * @return value of password.
+     */
+    public String getPassword() {
+        return Utils.toString(userPassword);
+    }
+
+    /**
+     * Gets the value of password for the default user.
+     *
+     * @return value of password.
+     * @since 2.4.0
+     */
+    public char[] getPasswordCharArray() {
+        return userPassword;
+    }
+
+    /**
      * Attempts to establish a database connection using the default user and password.
      */
     @Override
@@ -208,11 +410,6 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         return pooledConnection;
     }
 
-    @Override
-    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
-        throw new SQLFeatureNotSupportedException();
-    }
-
     /**
      * Implements {@link Referenceable}.
      */
@@ -240,250 +437,110 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         return ref;
     }
 
-    /**
-     * Implements {@link 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 {
-        // 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;
-            if (ref.getClassName().equals(getClass().getName())) {
-                RefAddr ra = ref.get("description");
-                if (ra != null && ra.getContent() != null) {
-                    setDescription(ra.getContent().toString());
-                }
-
-                ra = ref.get("driver");
-                if (ra != null && ra.getContent() != null) {
-                    setDriver(ra.getContent().toString());
-                }
-                ra = ref.get("url");
-                if (ra != null && ra.getContent() != null) {
-                    setUrl(ra.getContent().toString());
-                }
-                ra = ref.get(KEY_USER);
-                if (ra != null && ra.getContent() != null) {
-                    setUser(ra.getContent().toString());
-                }
-                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());
-                }
-                ra = ref.get("maxIdle");
-                if (ra != null && ra.getContent() != null) {
-                    setMaxIdle(Integer.parseInt(ra.getContent().toString()));
-                }
-
-                ra = ref.get("timeBetweenEvictionRunsMillis");
-                if (ra != null && ra.getContent() != null) {
-                    setTimeBetweenEvictionRunsMillis(Integer.parseInt(ra.getContent().toString()));
-                }
-
-                ra = ref.get("numTestsPerEvictionRun");
-                if (ra != null && ra.getContent() != null) {
-                    setNumTestsPerEvictionRun(Integer.parseInt(ra.getContent().toString()));
-                }
-
-                ra = ref.get("minEvictableIdleTimeMillis");
-                if (ra != null && ra.getContent() != null) {
-                    setMinEvictableIdleTimeMillis(Integer.parseInt(ra.getContent().toString()));
-                }
-                ra = ref.get("maxPreparedStatements");
-                if (ra != null && ra.getContent() != null) {
-                    setMaxPreparedStatements(Integer.parseInt(ra.getContent().toString()));
-                }
-
-                ra = ref.get("accessToUnderlyingConnectionAllowed");
-                if (ra != null && ra.getContent() != null) {
-                    setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(ra.getContent().toString()).booleanValue());
-                }
-
-                cpds = this;
-            }
-        }
-        return cpds;
+    private String getStringContent(RefAddr ra) {
+        return ra.getContent().toString();
     }
 
     /**
-     * Throws an IllegalStateException, if a PooledConnection has already been requested.
-     */
-    private void assertInitializationAllowed() throws IllegalStateException {
-        if (getConnectionCalled) {
-            throw new IllegalStateException(GET_CONNECTION_CALLED);
-        }
-    }
-
-    /**
-     * Gets the connection properties passed to the JDBC driver.
-     *
-     * @return the JDBC connection properties used when creating connections.
-     */
-    public Properties getConnectionProperties() {
-        return connectionProperties;
-    }
-
-    /**
-     * <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>
-     *
-     * @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 != 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.
-     *
-     * @return value of description, may be null.
-     * @see #setDescription(String)
-     */
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * 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.
-     */
-    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.
+     * 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 value of password.
+     * @return the value of the evictor thread timer
+     * @see #setTimeBetweenEvictionRunsMillis(long)
      */
-    public String getPassword() {
-        return Utils.toString(userPassword);
+    public long getTimeBetweenEvictionRunsMillis() {
+        return timeBetweenEvictionRunsMillis;
     }
 
     /**
-     * Sets the value of password for the default user.
+     * Gets the value of url used to locate the database for this datasource.
      *
-     * @param userPassword
-     *            Value to assign to password.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @return value of url.
      */
-    public void setPassword(final char[] userPassword) {
-        assertInitializationAllowed();
-        this.userPassword = Utils.clone(userPassword);
-        update(connectionProperties, KEY_PASSWORD, Utils.toString(this.userPassword));
+    public String getUrl() {
+        return url;
     }
 
     /**
-     * Sets the value of password for the default user.
+     * Gets the value of default user (login or user name).
      *
-     * @param userPassword
-     *            Value to assign to password.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @return value of user.
      */
-    public void setPassword(final String userPassword) {
-        assertInitializationAllowed();
-        this.userPassword = Utils.toCharArray(userPassword);
-        update(connectionProperties, KEY_PASSWORD, userPassword);
+    public String getUser() {
+        return userName;
     }
 
     /**
-     * Gets the value of url used to locate the database for this datasource.
+     * Returns the value of the accessToUnderlyingConnectionAllowed property.
      *
-     * @return value of url.
-     */
-    public String getUrl() {
-        return url;
+     * @return true if access to the underlying is allowed, false otherwise.
+     */
+    public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
+        return this.accessToUnderlyingConnectionAllowed;
+    }
+
+    private boolean isNotEmpty(RefAddr ra) {
+        return ra != null && ra.getContent() != null;
     }
 
     /**
-     * Sets the value of URL string used to locate the database for this datasource.
+     * Whether to toggle the pooling of <code>PreparedStatement</code>s
      *
-     * @param v
-     *            Value to assign to url.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
+     * @return value of poolPreparedStatements.
      */
-    public void setUrl(final String v) {
-        assertInitializationAllowed();
-        this.url = v;
+    public boolean isPoolPreparedStatements() {
+        return poolPreparedStatements;
     }
 
     /**
-     * Gets the value of default user (login or user name).
+     * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
+     * the underlying connection. (Default: false)
      *
-     * @return value of user.
+     * @param allow
+     *            Access to the underlying connection is granted when true.
      */
-    public String getUser() {
-        return userName;
+    public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
+        this.accessToUnderlyingConnectionAllowed = allow;
     }
 
     /**
-     * Sets the value of default user (login or user name).
+     * Sets the connection properties passed to the JDBC driver.
+     * <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 v
-     *            Value to assign to user.
+     * @param props
+     *            Connection properties to use when creating new connections.
      * @throws IllegalStateException
      *             if {@link #getPooledConnection()} has been called
      */
-    public void setUser(final String v) {
+    public void setConnectionProperties(final Properties props) {
         assertInitializationAllowed();
-        this.userName = v;
-        update(connectionProperties, KEY_USER, v);
+        connectionProperties = props;
+        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 driver class name.
+     * Sets 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 driver.
+     * @param v
+     *            Value to assign to description.
      */
-    public String getDriver() {
-        return driver;
+    public void setDescription(final String v) {
+        this.description = v;
     }
 
     /**
@@ -505,23 +562,6 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     }
 
     /**
-     * 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() {
-        return loginTimeout;
-    }
-
-    /**
-     * Gets the log writer for this data source. NOT USED.
-     */
-    @Override
-    public PrintWriter getLogWriter() {
-        return logWriter;
-    }
-
-    /**
      * Sets the maximum time in seconds that this data source will wait while attempting to connect to a database. NOT
      * USED.
      */
@@ -539,38 +579,6 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     }
 
     /**
-     * Whether to toggle the pooling of <code>PreparedStatement</code>s
-     *
-     * @return value of poolPreparedStatements.
-     */
-    public boolean isPoolPreparedStatements() {
-        return poolPreparedStatements;
-    }
-
-    /**
-     * Whether to toggle the pooling of <code>PreparedStatement</code>s
-     *
-     * @param poolPreparedStatements
-     *            true to pool statements.
-     * @throws IllegalStateException
-     *             if {@link #getPooledConnection()} has been called
-     */
-    public void setPoolPreparedStatements(final boolean poolPreparedStatements) {
-        assertInitializationAllowed();
-        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.
-     *
-     * @return the value of maxIdle
-     */
-    public int getMaxIdle() {
-        return this.maxIdle;
-    }
-
-    /**
      * Gets the maximum number of statements that can remain idle in the pool, without extra ones being released, or
      * negative for no limit.
      *
@@ -585,41 +593,29 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     }
 
     /**
-     * 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.
+     * Sets the maximum number of prepared statements.
      *
-     * @return the value of the evictor thread timer
-     * @see #setTimeBetweenEvictionRunsMillis(long)
+     * @param maxPreparedStatements
+     *            the new maximum number of prepared statements
      */
-    public long getTimeBetweenEvictionRunsMillis() {
-        return timeBetweenEvictionRunsMillis;
+    public void setMaxPreparedStatements(final int maxPreparedStatements) {
+        this.maxPreparedStatements = maxPreparedStatements;
     }
 
     /**
-     * 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.
+     * 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 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()
+     * @param minEvictableIdleTimeMillis
+     *            minimum time to set (in ms)
+     * @see #getMinEvictableIdleTimeMillis()
+     * @see #setTimeBetweenEvictionRunsMillis(long)
      * @throws IllegalStateException
      *             if {@link #getPooledConnection()} has been called
      */
-    public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
+    public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) {
         assertInitializationAllowed();
-        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
-    }
-
-    /**
-     * Gets the number of statements to examine during each run of the idle object evictor thread (if any.)
-     *
-     * @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;
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
     }
 
     /**
@@ -643,80 +639,87 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
     }
 
     /**
-     * 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).
+     * Sets the value of password for the default user.
      *
-     * @see #setMinEvictableIdleTimeMillis
-     * @see #setTimeBetweenEvictionRunsMillis
-     * @return the minimum amount of time a statement may sit idle in the pool.
+     * @param userPassword
+     *            Value to assign to password.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public int getMinEvictableIdleTimeMillis() {
-        return minEvictableIdleTimeMillis;
+    public void setPassword(final char[] userPassword) {
+        assertInitializationAllowed();
+        this.userPassword = Utils.clone(userPassword);
+        update(connectionProperties, KEY_PASSWORD, Utils.toString(this.userPassword));
     }
 
     /**
-     * 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.
+     * Sets the value of password for the default user.
      *
-     * @param minEvictableIdleTimeMillis
-     *            minimum time to set (in ms)
-     * @see #getMinEvictableIdleTimeMillis()
-     * @see #setTimeBetweenEvictionRunsMillis(long)
+     * @param userPassword
+     *            Value to assign to password.
      * @throws IllegalStateException
      *             if {@link #getPooledConnection()} has been called
      */
-    public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis) {
+    public void setPassword(final String userPassword) {
         assertInitializationAllowed();
-        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+        this.userPassword = Utils.toCharArray(userPassword);
+        update(connectionProperties, KEY_PASSWORD, userPassword);
     }
 
     /**
-     * Returns the value of the accessToUnderlyingConnectionAllowed property.
+     * Whether to toggle the pooling of <code>PreparedStatement</code>s
      *
-     * @return true if access to the underlying is allowed, false otherwise.
+     * @param poolPreparedStatements
+     *            true to pool statements.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
-        return this.accessToUnderlyingConnectionAllowed;
+    public void setPoolPreparedStatements(final boolean poolPreparedStatements) {
+        assertInitializationAllowed();
+        this.poolPreparedStatements = poolPreparedStatements;
     }
 
     /**
-     * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to
-     * the underlying connection. (Default: false)
+     * 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 allow
-     *            Access to the underlying connection is granted when true.
+     * @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
      */
-    public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) {
-        this.accessToUnderlyingConnectionAllowed = allow;
+    public void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) {
+        assertInitializationAllowed();
+        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
     }
 
     /**
-     * Gets the maximum number of prepared statements.
+     * Sets the value of URL string used to locate the database for this datasource.
      *
-     * @return maxPrepartedStatements value
+     * @param v
+     *            Value to assign to url.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public int getMaxPreparedStatements() {
-        return maxPreparedStatements;
+    public void setUrl(final String v) {
+        assertInitializationAllowed();
+        this.url = v;
     }
 
     /**
-     * Sets the maximum number of prepared statements.
+     * Sets the value of default user (login or user name).
      *
-     * @param maxPreparedStatements
-     *            the new maximum number of prepared statements
+     * @param v
+     *            Value to assign to user.
+     * @throws IllegalStateException
+     *             if {@link #getPooledConnection()} has been called
      */
-    public void setMaxPreparedStatements(final int maxPreparedStatements) {
-        this.maxPreparedStatements = maxPreparedStatements;
-    }
-
-    private void update(final Properties properties, final String key, final String value) {
-        if (properties != null && key != null) {
-            if (value == null) {
-                properties.remove(key);
-            } else {
-                properties.setProperty(key, value);
-            }
-        }
+    public void setUser(final String v) {
+        assertInitializationAllowed();
+        this.userName = v;
+        update(connectionProperties, KEY_USER, v);
     }
 
     /**
@@ -763,4 +766,14 @@ public class DriverAdapterCPDS implements ConnectionPoolDataSource, Referenceabl
         builder.append("]");
         return builder.toString();
     }
+
+    private void update(final Properties properties, final String key, final String value) {
+        if (properties != null && key != null) {
+            if (value == null) {
+                properties.remove(key);
+            } else {
+                properties.setProperty(key, value);
+            }
+        }
+    }
 }