Index: src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java =================================================================== --- src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (revision 1180904) +++ src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (working copy) @@ -307,7 +307,7 @@ getProxyConstructor(con.getXAConnection() != null); //create the proxy //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade - Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler }); + Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { new ProxyCutOffConnection(handler) }); //return the connection return connection; }catch (Exception x) { Index: src/main/java/org/apache/tomcat/jdbc/pool/ProxyCutOffConnection.java =================================================================== --- src/main/java/org/apache/tomcat/jdbc/pool/ProxyCutOffConnection.java (revision 0) +++ src/main/java/org/apache/tomcat/jdbc/pool/ProxyCutOffConnection.java (working copy) @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.jdbc.pool; + +import java.lang.reflect.Method; +import java.sql.SQLException; + +/** + * A ProxyCutOffConnection object is the top most interceptor that wraps an object of type + * {@link PooledConnection}. The ProxyCutOffConnection intercepts two methods: + *
true
argument.
+ * @author Filip Hanik
+ */
+public class ProxyCutOffConnection extends JdbcInterceptor {
+ protected ProxyCutOffConnection(JdbcInterceptor interceptor) throws SQLException {
+ setUseEquals(interceptor.isUseEquals());
+ setNext(interceptor);
+ }
+
+ @Override
+ public void reset(ConnectionPool parent, PooledConnection con) {
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (compare(ISCLOSED_VAL, method) && getNext() == null) {
+ return Boolean.TRUE;
+ }
+
+ try {
+ return super.invoke(proxy, method, args);
+ } catch (NullPointerException e) {
+ if (getNext() == null) {
+ if (compare(TOSTRING_VAL, method)) {
+ return "ProxyConnection[null]";
+ }
+ throw new SQLException("Connection has already been closed.");
+ }
+
+ throw e;
+ } finally {
+ if (compare(CLOSE_VAL, method)) {
+ setNext(null);
+ }
+ }
+ }
+}
Index: src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java
===================================================================
--- src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java (revision 0)
+++ src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java (working copy)
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.jdbc.test;
+
+import java.sql.Connection;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+
+public class MultipleCloseTest extends DefaultTestCase {
+
+ public MultipleCloseTest(String name) {
+ super(name);
+ }
+
+ @Override
+ public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() {
+ org.apache.tomcat.jdbc.pool.DataSource ds = super.createDefaultDataSource();
+ ds.getPoolProperties().setDriverClassName(Driver.class.getName());
+ ds.getPoolProperties().setUrl(Driver.url);
+ ds.getPoolProperties().setInitialSize(0);
+ ds.getPoolProperties().setMaxIdle(1);
+ ds.getPoolProperties().setMinIdle(1);
+ ds.getPoolProperties().setMaxActive(1);
+ return ds;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ Driver.reset();
+ super.tearDown();
+ }
+
+ public void testClosedConnectionsNotReused() throws Exception {
+ this.init();
+
+ Connection con1 = datasource.getConnection();
+
+ // A new connection is open
+ assertFalse(con1.isClosed());
+
+ con1.close();
+
+ // Confirm that a closed connection is closed
+ assertTrue(con1.isClosed());
+
+ // Open a new connection (This will re-use the previous pooled connection)
+ datasource.getConnection();
+
+ // A connection, once closed, should stay closed
+ assertTrue(con1.isClosed());
+ }
+}