You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2009/10/05 22:33:45 UTC
svn commit: r821997 - in /commons/proper/dbcp/trunk/src:
java/org/apache/commons/dbcp/cpdsadapter/
test/org/apache/commons/dbcp/datasources/
Author: markt
Date: Mon Oct 5 20:33:44 2009
New Revision: 821997
URL: http://svn.apache.org/viewvc?rev=821997&view=rev
Log:
Fix DBCP-160
Based on a patch by Mark Riley
This patch:
- Changes to ConnectionImpl so it extends DelegatingConnection
- Adds statement pooling support (with test cases) to all prepareStatement() methods
It differs from Mark's original patch in that:
- It doesn't change DelegatingConnection
- It adds test cases and fixes for statement pooling
- Most of the implementation in ConnectionImpl is left to the super class
Modified:
commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/ConnectionImpl.java
commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java
commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/PooledConnectionImpl.java
commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestPerUserPoolDataSource.java
commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java
Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/ConnectionImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/ConnectionImpl.java?rev=821997&r1=821996&r2=821997&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/ConnectionImpl.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/ConnectionImpl.java Mon Oct 5 20:33:44 2009
@@ -17,57 +17,35 @@
package org.apache.commons.dbcp.cpdsadapter;
-import java.util.Map;
import java.sql.Connection;
-import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
-import java.sql.CallableStatement;
-import java.sql.Statement;
-import java.sql.SQLWarning;
import java.sql.SQLException;
-/* JDBC_4_ANT_KEY_BEGIN */
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.ClientInfoStatus;
-import java.sql.Clob;
-import java.sql.NClob;
-import java.sql.SQLClientInfoException;
-import java.sql.SQLXML;
-import java.sql.Struct;
-import java.util.Collections;
-import java.util.Properties;
-/* JDBC_4_ANT_KEY_END */
+
+import org.apache.commons.dbcp.DelegatingConnection;
+import org.apache.commons.dbcp.DelegatingPreparedStatement;
/**
* This class is the <code>Connection</code> that will be returned
* from <code>PooledConnectionImpl.getConnection()</code>.
* Most methods are wrappers around the jdbc 1.x <code>Connection</code>.
- * A few exceptions include preparedStatement, close and isClosed.
+ * A few exceptions include preparedStatement and close.
* In accordance with the jdbc specification this Connection cannot
* be used after closed() is called. Any further usage will result in an
* SQLException.
+ *
+ * ConnectionImpl extends DelegatingConnection to enable access to the
+ * underlying connection.
*
* @author John D. McNally
* @version $Revision$ $Date$
*/
-class ConnectionImpl implements Connection {
- private static final String CLOSED
- = "Attempted to use Connection after closed() was called.";
-
-/* JDBC_4_ANT_KEY_BEGIN */
- private static final Map<String, ClientInfoStatus> EMPTY_FAILED_PROPERTIES =
- Collections.<String, ClientInfoStatus>emptyMap();
-/* JDBC_4_ANT_KEY_END */
+class ConnectionImpl extends DelegatingConnection {
- /** The JDBC database connection. */
- private final Connection connection;
+ private final boolean accessToUnderlyingConnectionAllowed;
/** The object that instantiated this object */
private final PooledConnectionImpl pooledConnection;
- /** Marks whether is Connection is still usable. */
- boolean isClosed;
-
/**
* Creates a <code>ConnectionImpl</code>.
*
@@ -75,49 +53,12 @@
* @param connection The JDBC 1.x Connection to wrap.
*/
ConnectionImpl(PooledConnectionImpl pooledConnection,
- Connection connection) {
+ Connection connection,
+ boolean accessToUnderlyingConnectionAllowed) {
+ super(connection);
this.pooledConnection = pooledConnection;
- this.connection = connection;
- isClosed = false;
- }
-
- /**
- * The finalizer helps prevent <code>ConnectionPool</code> leakage.
- */
- protected void finalize() throws Throwable {
- if (!isClosed) {
- // If this DBConnection object is finalized while linked
- // to a ConnectionPool, it means that it was taken from a pool
- // and not returned. We log this fact, close the underlying
- // Connection, and return it to the ConnectionPool.
- throw new SQLException("A ConnectionImpl was finalized "
- + "without being closed which will cause leakage of "
- + " PooledConnections from the ConnectionPool.");
- }
- }
-
- /**
- * Throws an SQLException, if isClosed() is true
- */
- private void assertOpen() throws SQLException {
- if (isClosed) {
- throw new SQLException(CLOSED);
- }
- }
-
- // ***********************************************************************
- // java.sql.Connection implementation using wrapped Connection
- // ***********************************************************************
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void clearWarnings() throws SQLException {
- assertOpen();
- connection.clearWarnings();
+ this.accessToUnderlyingConnectionAllowed =
+ accessToUnderlyingConnectionAllowed;
}
/**
@@ -130,170 +71,14 @@
* @exception SQLException The database connection couldn't be closed.
*/
public void close() throws SQLException {
- if (!isClosed) {
- isClosed = true;
+ if (!_closed) {
+ _closed = true;
+ passivate();
pooledConnection.notifyListeners();
}
}
/**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void commit() throws SQLException {
- assertOpen();
- connection.commit();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public Statement createStatement() throws SQLException {
- assertOpen();
- return connection.createStatement();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public Statement createStatement(int resultSetType,
- int resultSetConcurrency)
- throws SQLException {
- assertOpen();
- return connection
- .createStatement(resultSetType, resultSetConcurrency);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public boolean getAutoCommit() throws SQLException {
- assertOpen();
- return connection.getAutoCommit();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public String getCatalog() throws SQLException {
- assertOpen();
- return connection.getCatalog();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public DatabaseMetaData getMetaData() throws SQLException {
- assertOpen();
- return connection.getMetaData();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public int getTransactionIsolation() throws SQLException {
- assertOpen();
- return connection.getTransactionIsolation();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public Map getTypeMap() throws SQLException {
- assertOpen();
- return connection.getTypeMap();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public SQLWarning getWarnings() throws SQLException {
- assertOpen();
- return connection.getWarnings();
- }
-
- /**
- * Returns true after close() is called, and false prior to that.
- *
- * @return a <code>boolean</code> value
- */
- public boolean isClosed() {
- return isClosed;
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public boolean isReadOnly() throws SQLException {
- assertOpen();
- return connection.isReadOnly();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public String nativeSQL(String sql) throws SQLException {
- assertOpen();
- return connection.nativeSQL(sql);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public CallableStatement prepareCall(String sql) throws SQLException {
- assertOpen();
- return connection.prepareCall(sql);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public CallableStatement prepareCall(String sql, int resultSetType,
- int resultSetConcurrency)
- throws SQLException {
- assertOpen();
- return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
- }
-
- /**
* If pooling of <code>PreparedStatement</code>s is turned on in the
* {@link DriverAdapterCPDS}, a pooled object may be returned, otherwise
* delegate to the wrapped jdbc 1.x {@link java.sql.Connection}.
@@ -302,8 +87,15 @@
* in the wrapped connection.
*/
public PreparedStatement prepareStatement(String sql) throws SQLException {
- assertOpen();
- return pooledConnection.prepareStatement(sql);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement
+ (this, pooledConnection.prepareStatement(sql));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
+ }
}
/**
@@ -317,246 +109,101 @@
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency)
throws SQLException {
- assertOpen();
- return pooledConnection
- .prepareStatement(sql, resultSetType, resultSetConcurrency);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void rollback() throws SQLException {
- assertOpen();
- connection.rollback();
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void setAutoCommit(boolean b) throws SQLException {
- assertOpen();
- connection.setAutoCommit(b);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void setCatalog(String catalog) throws SQLException {
- assertOpen();
- connection.setCatalog(catalog);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void setReadOnly(boolean readOnly) throws SQLException {
- assertOpen();
- connection.setReadOnly(readOnly);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void setTransactionIsolation(int level) throws SQLException {
- assertOpen();
- connection.setTransactionIsolation(level);
- }
-
- /**
- * Pass thru method to the wrapped jdbc 1.x {@link java.sql.Connection}.
- *
- * @exception SQLException if this connection is closed or an error occurs
- * in the wrapped connection.
- */
- public void setTypeMap(Map map) throws SQLException {
- assertOpen();
- connection.setTypeMap(map);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement
+ (this, pooledConnection.prepareStatement
+ (sql,resultSetType,resultSetConcurrency));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
+ }
}
- // ------------------- JDBC 3.0 -----------------------------------------
- // Will be commented by the build process on a JDBC 2.0 system
-
/* JDBC_3_ANT_KEY_BEGIN */
-
- public int getHoldability() throws SQLException {
- assertOpen();
- return connection.getHoldability();
- }
-
- public void setHoldability(int holdability) throws SQLException {
- assertOpen();
- connection.setHoldability(holdability);
- }
-
- public java.sql.Savepoint setSavepoint() throws SQLException {
- assertOpen();
- return connection.setSavepoint();
- }
-
- public java.sql.Savepoint setSavepoint(String name) throws SQLException {
- assertOpen();
- return connection.setSavepoint(name);
- }
-
- public void rollback(java.sql.Savepoint savepoint) throws SQLException {
- assertOpen();
- connection.rollback(savepoint);
- }
-
- public void releaseSavepoint(java.sql.Savepoint savepoint)
- throws SQLException {
- assertOpen();
- connection.releaseSavepoint(savepoint);
- }
-
- public Statement createStatement(int resultSetType,
- int resultSetConcurrency,
- int resultSetHoldability)
- throws SQLException {
- assertOpen();
- return connection.createStatement(resultSetType, resultSetConcurrency,
- resultSetHoldability);
- }
-
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency,
int resultSetHoldability)
throws SQLException {
- assertOpen();
- return connection.prepareStatement(sql, resultSetType,
- resultSetConcurrency,
- resultSetHoldability);
- }
-
- public CallableStatement prepareCall(String sql, int resultSetType,
- int resultSetConcurrency,
- int resultSetHoldability)
- throws SQLException {
- assertOpen();
- return connection.prepareCall(sql, resultSetType,
- resultSetConcurrency,
- resultSetHoldability);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement(this,
+ pooledConnection.prepareStatement(sql, resultSetType,
+ resultSetConcurrency, resultSetHoldability));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
+ }
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
- assertOpen();
- return connection.prepareStatement(sql, autoGeneratedKeys);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement(this,
+ pooledConnection.prepareStatement(sql, autoGeneratedKeys));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
+ }
}
public PreparedStatement prepareStatement(String sql, int columnIndexes[])
throws SQLException {
- assertOpen();
- return connection.prepareStatement(sql, columnIndexes);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement(this,
+ pooledConnection.prepareStatement(sql, columnIndexes));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
+ }
}
public PreparedStatement prepareStatement(String sql, String columnNames[])
throws SQLException {
- assertOpen();
- return connection.prepareStatement(sql, columnNames);
- }
-/* JDBC_3_ANT_KEY_END */
-/* JDBC_4_ANT_KEY_BEGIN */
-
- public boolean isWrapperFor(Class<?> iface) throws SQLException {
- return iface.isAssignableFrom(getClass()) ||
- connection.isWrapperFor(iface);
- }
-
- public <T> T unwrap(Class<T> iface) throws SQLException {
- if (iface.isAssignableFrom(getClass())) {
- return iface.cast(this);
- } else if (iface.isAssignableFrom(connection.getClass())) {
- return iface.cast(connection);
- } else {
- return connection.unwrap(iface);
+ checkOpen();
+ try {
+ return new DelegatingPreparedStatement(this,
+ pooledConnection.prepareStatement(sql, columnNames));
+ }
+ catch (SQLException e) {
+ handleException(e);
+ return null;
}
}
+/* JDBC_3_ANT_KEY_END */
- public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
- assertOpen();
- return connection.createArrayOf(typeName, elements);
- }
-
- public Blob createBlob() throws SQLException {
- assertOpen();
- return connection.createBlob();
- }
-
- public Clob createClob() throws SQLException {
- assertOpen();
- return connection.createClob();
- }
-
- public NClob createNClob() throws SQLException {
- assertOpen();
- return connection.createNClob();
- }
-
- public SQLXML createSQLXML() throws SQLException {
- assertOpen();
- return connection.createSQLXML();
- }
-
- public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
- assertOpen();
- return connection.createStruct(typeName, attributes);
- }
+ //
+ // Methods for accessing the delegate connection
+ //
- public boolean isValid(int timeout) throws SQLException {
- assertOpen();
- return connection.isValid(timeout);
+ /**
+ * If false, getDelegate() and getInnermostDelegate() will return null.
+ * @return if false, getDelegate() and getInnermostDelegate() will return null
+ */
+ public boolean isAccessToUnderlyingConnectionAllowed() {
+ return accessToUnderlyingConnectionAllowed;
}
- public void setClientInfo(String name, String value) throws SQLClientInfoException {
- try {
- assertOpen();
- connection.setClientInfo(name, value);
- }
- catch (SQLClientInfoException e) {
- throw e;
- }
- catch (SQLException e) {
- throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e);
+ public Connection getDelegate() {
+ if (isAccessToUnderlyingConnectionAllowed()) {
+ return getDelegateInternal();
+ } else {
+ return null;
}
}
- public void setClientInfo(Properties properties) throws SQLClientInfoException {
- try {
- assertOpen();
- connection.setClientInfo(properties);
- }
- catch (SQLClientInfoException e) {
- throw e;
- }
- catch (SQLException e) {
- throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e);
+ public Connection getInnermostDelegate() {
+ if (isAccessToUnderlyingConnectionAllowed()) {
+ return super.getInnermostDelegateInternal();
+ } else {
+ return null;
}
}
- public Properties getClientInfo() throws SQLException {
- assertOpen();
- return connection.getClientInfo();
- }
-
- public String getClientInfo(String name) throws SQLException {
- assertOpen();
- return connection.getClientInfo(name);
- }
-/* JDBC_4_ANT_KEY_END */
}
Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java?rev=821997&r1=821996&r2=821997&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/DriverAdapterCPDS.java Mon Oct 5 20:33:44 2009
@@ -128,6 +128,11 @@
DriverManager.getDrivers();
}
+ /**
+ * Controls access to the underlying connection
+ */
+ private boolean accessToUnderlyingConnectionAllowed = false;
+
/**
* Default no-arg constructor for Serialization
*/
@@ -184,29 +189,35 @@
// Workaround for buggy WebLogic 5.1 classloader - ignore the
// exception upon first invocation.
try {
+ PooledConnectionImpl pci = null;
if (connectionProperties != null) {
connectionProperties.put("user", username);
connectionProperties.put("password", password);
- return new PooledConnectionImpl(
+ pci = new PooledConnectionImpl(
DriverManager.getConnection(getUrl(), connectionProperties),
- stmtPool);
+ stmtPool);
} else {
- return new PooledConnectionImpl(
+ pci = new PooledConnectionImpl(
DriverManager.getConnection(getUrl(), username, password),
- stmtPool );
+ stmtPool);
}
+ pci.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
+ return pci;
}
catch (ClassCircularityError e)
{
+ PooledConnectionImpl pci = null;
if (connectionProperties != null) {
- return new PooledConnectionImpl(
+ pci = new PooledConnectionImpl(
DriverManager.getConnection(getUrl(), connectionProperties),
- stmtPool);
+ stmtPool);
} else {
- return new PooledConnectionImpl(
+ pci = new PooledConnectionImpl(
DriverManager.getConnection(getUrl(), username, password),
- stmtPool );
+ stmtPool);
}
+ pci.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
+ return pci;
}
}
@@ -645,6 +656,26 @@
}
/**
+ * 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;
+ }
+
+ /**
+ * 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.
+ */
+ public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
+ this.accessToUnderlyingConnectionAllowed = allow;
+ }
+
+ /**
* Returns the maximun number of prepared statements.
*
* @return maxPrepartedStatements value
Modified: commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/PooledConnectionImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/PooledConnectionImpl.java?rev=821997&r1=821996&r2=821997&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/PooledConnectionImpl.java (original)
+++ commons/proper/dbcp/trunk/src/java/org/apache/commons/dbcp/cpdsadapter/PooledConnectionImpl.java Mon Oct 5 20:33:44 2009
@@ -20,7 +20,7 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-import java.util.Iterator;
+import java.util.Arrays;
import java.util.Vector;
import javax.sql.ConnectionEvent;
@@ -81,6 +81,10 @@
/** My pool of {*link PreparedStatement}s. */
protected KeyedObjectPool pstmtPool = null;
+ /**
+ * Controls access to the underlying connection
+ */
+ private boolean accessToUnderlyingConnectionAllowed = false;
/**
* Wrap the real connection.
@@ -90,7 +94,7 @@
if (connection instanceof DelegatingConnection) {
this.delegatingConnection = (DelegatingConnection) connection;
} else {
- this.delegatingConnection = new DelegatingConnection(connection);
+ this.delegatingConnection = new DelegatingConnection(connection);
}
eventListeners = new Vector();
isClosed = false;
@@ -173,7 +177,8 @@
}
// the spec requires that this return a new Connection instance.
- logicalConnection = new ConnectionImpl(this, connection);
+ logicalConnection = new ConnectionImpl(
+ this, connection, isAccessToUnderlyingConnectionAllowed());
return logicalConnection;
}
@@ -264,6 +269,110 @@
}
}
+/* JDBC_3_ANT_KEY_BEGIN */
+ /**
+ * Create or obtain a {*link PreparedStatement} from my pool.
+ * @return a {*link PoolablePreparedStatement}
+ */
+ PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException {
+ if (pstmtPool == null) {
+ return connection.prepareStatement(sql, autoGeneratedKeys);
+ } else {
+ try {
+ return (PreparedStatement) pstmtPool.borrowObject(
+ createKey(sql,autoGeneratedKeys));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
+ }
+ }
+ }
+
+ PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ if (pstmtPool == null) {
+ return connection.prepareStatement(sql, resultSetType,
+ resultSetConcurrency, resultSetHoldability);
+ } else {
+ try {
+ return (PreparedStatement) pstmtPool.borrowObject(
+ createKey(sql, resultSetType, resultSetConcurrency,
+ resultSetHoldability));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
+ }
+ }
+ }
+
+ PreparedStatement prepareStatement(String sql, int columnIndexes[])
+ throws SQLException {
+ if (pstmtPool == null) {
+ return connection.prepareStatement(sql, columnIndexes);
+ } else {
+ try {
+ return (PreparedStatement) pstmtPool.borrowObject(
+ createKey(sql, columnIndexes));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
+ }
+ }
+ }
+
+ PreparedStatement prepareStatement(String sql, String columnNames[])
+ throws SQLException {
+ if (pstmtPool == null) {
+ return connection.prepareStatement(sql, columnNames);
+ } else {
+ try {
+ return (PreparedStatement) pstmtPool.borrowObject(
+ createKey(sql, columnNames));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SQLNestedException("Borrow prepareStatement from pool failed", e);
+ }
+ }
+ }
+
+ /**
+ * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
+ */
+ protected Object createKey(String sql, int autoGeneratedKeys) {
+ return new PStmtKey(normalizeSQL(sql), autoGeneratedKeys);
+ }
+
+ /**
+ * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
+ */
+ protected Object createKey(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability) {
+ return new PStmtKey(normalizeSQL(sql), resultSetType,
+ resultSetConcurrency, resultSetHoldability);
+ }
+
+ /**
+ * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
+ */
+ protected Object createKey(String sql, int columnIndexes[]) {
+ return new PStmtKey(normalizeSQL(sql), columnIndexes);
+ }
+
+ /**
+ * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
+ */
+ protected Object createKey(String sql, String columnNames[]) {
+ return new PStmtKey(normalizeSQL(sql), columnNames);
+ }
+
+/* JDBC_3_ANT_KEY_END */
+
/**
* Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
*/
@@ -272,7 +381,7 @@
return new PStmtKey(normalizeSQL(sql), resultSetType,
resultSetConcurrency);
}
-
+
/**
* Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
*/
@@ -362,13 +471,37 @@
}
/**
+ * 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;
+ }
+
+ /**
+ * 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.
+ */
+ public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
+ this.accessToUnderlyingConnectionAllowed = allow;
+ }
+
+ /**
* A key uniquely identifying {*link PreparedStatement}s.
*/
class PStmtKey {
protected String _sql = null;
protected Integer _resultSetType = null;
protected Integer _resultSetConcurrency = null;
-
+ protected Integer _autoGeneratedKeys = null;
+ protected Integer _resultSetHoldability = null;
+ protected int _columnIndexes[] = null;
+ protected String _columnNames[] = null;
+
PStmtKey(String sql) {
_sql = sql;
}
@@ -379,12 +512,40 @@
_resultSetConcurrency = new Integer(resultSetConcurrency);
}
+ PStmtKey(String sql, int autoGeneratedKeys) {
+ _sql = sql;
+ _autoGeneratedKeys = new Integer(autoGeneratedKeys);
+ }
+
+ PStmtKey(String sql, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) {
+ _sql = sql;
+ _resultSetType = new Integer(resultSetType);
+ _resultSetConcurrency = new Integer(resultSetConcurrency);
+ _resultSetHoldability = new Integer(resultSetHoldability);
+ }
+
+ PStmtKey(String sql, int columnIndexes[]) {
+ _sql = sql;
+ _columnIndexes = columnIndexes;
+ }
+
+ PStmtKey(String sql, String columnNames[]) {
+ _sql = sql;
+ _columnNames = columnNames;
+ }
+
+
public boolean equals(Object that) {
try {
PStmtKey key = (PStmtKey) that;
return(((null == _sql && null == key._sql) || _sql.equals(key._sql)) &&
((null == _resultSetType && null == key._resultSetType) || _resultSetType.equals(key._resultSetType)) &&
- ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency))
+ ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency)) &&
+ ((null == _autoGeneratedKeys && null == key._autoGeneratedKeys) || _autoGeneratedKeys.equals(key._autoGeneratedKeys)) &&
+ ((null == _resultSetHoldability && null == key._resultSetHoldability) || _resultSetHoldability.equals(key._resultSetHoldability)) &&
+ ((null == _columnIndexes && null == key._columnIndexes) || Arrays.equals(_columnIndexes, key._columnIndexes)) &&
+ ((null == _columnNames && null == key._columnNames) || Arrays.equals(_columnNames, key._columnNames))
);
} catch (ClassCastException e) {
return false;
@@ -405,6 +566,14 @@
buf.append(_resultSetType);
buf.append(", resultSetConcurrency=");
buf.append(_resultSetConcurrency);
+ buf.append(", autoGeneratedKeys=");
+ buf.append(_autoGeneratedKeys);
+ 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();
}
}
Modified: commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestPerUserPoolDataSource.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestPerUserPoolDataSource.java?rev=821997&r1=821996&r2=821997&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestPerUserPoolDataSource.java (original)
+++ commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestPerUserPoolDataSource.java Mon Oct 5 20:33:44 2009
@@ -61,6 +61,7 @@
pcds.setUrl("jdbc:apache:commons:testdriver");
pcds.setUser("foo");
pcds.setPassword("bar");
+ pcds.setAccessToUnderlyingConnectionAllowed(true);
PerUserPoolDataSource tds = new PerUserPoolDataSource();
tds.setConnectionPoolDataSource(pcds);
Modified: commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java
URL: http://svn.apache.org/viewvc/commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java?rev=821997&r1=821996&r2=821997&view=diff
==============================================================================
--- commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java (original)
+++ commons/proper/dbcp/trunk/src/test/org/apache/commons/dbcp/datasources/TestSharedPoolDataSource.java Mon Oct 5 20:33:44 2009
@@ -59,6 +59,7 @@
pcds.setUser("foo");
pcds.setPassword("bar");
pcds.setPoolPreparedStatements(false);
+ pcds.setAccessToUnderlyingConnectionAllowed(true);
SharedPoolDataSource tds = new SharedPoolDataSource();
tds.setConnectionPoolDataSource(pcds);
@@ -520,7 +521,47 @@
conn.close();
}
- public void testPoolPreparedStatements() throws Exception {
+ // There are 6 different prepareStatement statement methods so add a little
+ // complexity to reduce what would otherwise be lots of copy and paste
+ private static abstract class PrepareStatementCallback {
+ protected Connection conn;
+ void setConnection(Connection conn) {
+ this.conn = conn;
+ }
+ abstract PreparedStatement getPreparedStatement() throws SQLException;
+ }
+ private static class PscbString extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual");
+ }
+ }
+ private static class PscbStringIntInt extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual",0,0);
+ }
+ }
+ private static class PscbStringInt extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual",0);
+ }
+ }
+ private static class PscbStringIntArray extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual", new int[0]);
+ }
+ }
+ private static class PscbStringStringArray extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual",new String[0]);
+ }
+ }
+ private static class PscbStringIntIntInt extends PrepareStatementCallback {
+ PreparedStatement getPreparedStatement() throws SQLException {
+ return conn.prepareStatement("select * from dual",0,0,0);
+ }
+ }
+ private void doTestPoolPreparedStatements(PrepareStatementCallback callBack)
+ throws Exception {
DriverAdapterCPDS mypcds = new DriverAdapterCPDS();
DataSource myds = null;
mypcds.setDriver("org.apache.commons.dbcp.TesterDriver");
@@ -540,12 +581,13 @@
myds = tds;
Connection conn = ds.getConnection();
+ callBack.setConnection(conn);
PreparedStatement stmt = null;
ResultSet rset = null;
assertTrue(null != conn);
- stmt = conn.prepareStatement("select * from dual");
+ stmt = callBack.getPreparedStatement();
assertTrue(null != stmt);
long l1HashCode = stmt.hashCode();
rset = stmt.executeQuery();
@@ -554,7 +596,7 @@
rset.close();
stmt.close();
- stmt = conn.prepareStatement("select * from dual");
+ stmt = callBack.getPreparedStatement();
assertTrue(null != stmt);
long l2HashCode = stmt.hashCode();
rset = stmt.executeQuery();
@@ -569,8 +611,9 @@
conn = null;
conn = myds.getConnection();
+ callBack.setConnection(conn);
- stmt = conn.prepareStatement("select * from dual");
+ stmt = callBack.getPreparedStatement();
assertTrue(null != stmt);
long l3HashCode = stmt.hashCode();
rset = stmt.executeQuery();
@@ -579,7 +622,7 @@
rset.close();
stmt.close();
- stmt = conn.prepareStatement("select * from dual");
+ stmt = callBack.getPreparedStatement();
assertTrue(null != stmt);
long l4HashCode = stmt.hashCode();
rset = stmt.executeQuery();
@@ -593,4 +636,12 @@
conn.close();
conn = null;
}
+ public void testPoolPreparedStatements() throws Exception {
+ doTestPoolPreparedStatements(new PscbString());
+ doTestPoolPreparedStatements(new PscbStringIntInt());
+ doTestPoolPreparedStatements(new PscbStringInt());
+ doTestPoolPreparedStatements(new PscbStringIntArray());
+ doTestPoolPreparedStatements(new PscbStringStringArray());
+ doTestPoolPreparedStatements(new PscbStringIntIntInt());
+ }
}