diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ClosedConnection.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ClosedConnection.java new file mode 100644 index 00000000..0be77866 --- /dev/null +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ClosedConnection.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Brett Wooldridge + * + * Licensed 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 com.zaxxer.hikari.proxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * + * @author Brett Wooldridge + */ +final class ClosedConnection +{ + public static final Connection CLOSED_CONNECTION = getClosedConnection(); + + private static Connection getClosedConnection() + { + InvocationHandler handler = new InvocationHandler() { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + final String methodName = method.getName(); + if ("isClosed".equals(methodName)) { + return Boolean.TRUE; + } + else if ("close".equals(methodName)) { + return Void.TYPE; + } + else if ("abort".equals(methodName)) { + return Void.TYPE; + } + else if ("isValid".equals(methodName)) { + return Boolean.FALSE; + } + else if ("toString".equals(methodName)) { + return String.format("%s(%s) wrapping %s", this.getClass().getSimpleName(), System.identityHashCode(this), "ClosedConnection"); + } + + throw new SQLException("Connection is closed"); + } + }; + + return (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), + new Class[] { Connection.class }, + handler); + } +} diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index cd519026..0f208822 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -44,7 +44,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy private static final Logger LOGGER; private static final Set SQL_ERRORS; - protected final Connection delegate; + protected Connection delegate; private final HikariPool parentPool; private final PoolBagEntry bagEntry; @@ -140,13 +140,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy // Internal methods // *********************************************************************** - protected final void checkClosed() throws SQLException - { - if (isClosed) { - throw new SQLException("Connection is closed"); - } - } - private final T trackStatement(T statement) { openStatements.add(statement); @@ -183,7 +176,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy { if (!isClosed) { isClosed = true; - leakTask.cancel(); final int size = openStatements.size(); @@ -213,18 +205,12 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy throw checkException(e); } finally { + delegate = ClosedConnection.CLOSED_CONNECTION; parentPool.releaseConnection(bagEntry, forceClose); } } } - /** {@inheritDoc} */ - @Override - public final boolean isClosed() throws SQLException - { - return isClosed; - } - /** {@inheritDoc} */ @Override public Statement createStatement() throws SQLException @@ -345,22 +331,6 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy commitStateDirty = false; } - /** {@inheritDoc} */ - @Override - public final boolean isValid(int timeout) throws SQLException - { - if (isClosed) { - return false; - } - - try { - return delegate.isValid(timeout); - } - catch (SQLException e) { - throw checkException(e); - } - } - /** {@inheritDoc} */ @Override public void setAutoCommit(boolean autoCommit) throws SQLException diff --git a/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/JavassistProxyFactory.java b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/JavassistProxyFactory.java index fa1001f5..246cc34e 100644 --- a/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/JavassistProxyFactory.java +++ b/hikaricp-java6/src/main/java/com/zaxxer/hikari/proxy/JavassistProxyFactory.java @@ -78,7 +78,7 @@ public final class JavassistProxyFactory classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader())); // Connection is special, it has a checkClosed() call at the beginning - String methodBody = "{ checkClosed(); try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }"; + String methodBody = "{ try { return delegate.method($$); } catch (SQLException e) { throw checkException(e); } }"; generateProxyClass(Connection.class, ConnectionProxy.class, methodBody); // Cast is not needed for these diff --git a/hikaricp-java6/src/test/java/com/zaxxer/hikari/ConnectionStateTest.java b/hikaricp-java6/src/test/java/com/zaxxer/hikari/ConnectionStateTest.java index 24bf1a2e..586c1263 100644 --- a/hikaricp-java6/src/test/java/com/zaxxer/hikari/ConnectionStateTest.java +++ b/hikaricp-java6/src/test/java/com/zaxxer/hikari/ConnectionStateTest.java @@ -30,15 +30,11 @@ public class ConnectionStateTest try { Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); connection.setAutoCommit(false); connection.close(); - PoolUtilities.quietlySleep(1100L); - - Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); - Assert.assertTrue(connection2.getAutoCommit()); - connection2.close(); + Assert.assertTrue(unwrap.getAutoCommit()); } finally { ds.close(); @@ -57,13 +53,11 @@ public class ConnectionStateTest try { Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); connection.close(); - Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); - Assert.assertEquals(Connection.TRANSACTION_READ_COMMITTED, connection2.getTransactionIsolation()); - connection2.close(); + Assert.assertEquals(Connection.TRANSACTION_READ_COMMITTED, unwrap.getTransactionIsolation()); } finally { ds.close(); @@ -94,13 +88,11 @@ public class ConnectionStateTest try { Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); connection.setReadOnly(true); connection.close(); - Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); - Assert.assertFalse(connection2.isReadOnly()); - connection2.close(); + Assert.assertFalse(unwrap.isReadOnly()); } finally { ds.close(); @@ -119,13 +111,11 @@ public class ConnectionStateTest try { Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); connection.setCatalog("other"); connection.close(); - Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); - Assert.assertEquals("test", connection2.getCatalog()); - connection2.close(); + Assert.assertEquals("test", unwrap.getCatalog()); } finally { ds.close(); diff --git a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestConnections.java b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestConnections.java index 97e4d138..faf43c9b 100644 --- a/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestConnections.java +++ b/hikaricp-java6/src/test/java/com/zaxxer/hikari/TestConnections.java @@ -112,6 +112,7 @@ public class TestConnections Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections()); Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); Assert.assertNotNull(connection); Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections()); @@ -121,7 +122,8 @@ public class TestConnections Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections()); Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); + Connection unwrap2 = connection2.unwrap(Connection.class); + Assert.assertSame(unwrap, unwrap2); Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections()); Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections()); connection2.close(); @@ -160,6 +162,7 @@ public class TestConnections Assert.assertSame("Idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections()); Connection connection = ds.getConnection(); + Connection unwrap = connection.unwrap(Connection.class); Assert.assertNotNull(connection); Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections()); @@ -169,7 +172,8 @@ public class TestConnections Assert.assertSame("Idle connections not as expected", 1, TestElf.getPool(ds).getIdleConnections()); Connection connection2 = ds.getConnection(); - Assert.assertSame(connection.unwrap(Connection.class), connection2.unwrap(Connection.class)); + Connection unwrap2 = connection2.unwrap(Connection.class); + Assert.assertSame(unwrap, unwrap2); Assert.assertSame("Second total connections not as expected", 1, TestElf.getPool(ds).getTotalConnections()); Assert.assertSame("Second idle connections not as expected", 0, TestElf.getPool(ds).getIdleConnections()); connection2.close(); diff --git a/hikaricp/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java b/hikaricp/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java index c73e6019..0f208822 100644 --- a/hikaricp/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java +++ b/hikaricp/src/main/java/com/zaxxer/hikari/proxy/ConnectionProxy.java @@ -177,7 +177,7 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy if (!isClosed) { isClosed = true; leakTask.cancel(); - + final int size = openStatements.size(); if (size > 0) { for (int i = 0; i < size; i++) { @@ -189,16 +189,16 @@ public abstract class ConnectionProxy implements IHikariConnectionProxy } } } - + try { if (commitStateDirty && !delegate.getAutoCommit()) { delegate.rollback(); } - + if (isAnythingDirty) { resetConnectionState(); } - + delegate.clearWarnings(); } catch (SQLException e) {