Author: fhanik Date: Tue Mar 20 15:45:19 2012 New Revision: 1302948 URL: http://svn.apache.org/viewvc?rev=1302948&view=rev Log: https://issues.apache.org/bugzilla/show_bug.cgi?id=52002 add in ability to configure pool so that connections can not be reused
Added: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java Tue Mar 20 15:45:19 2012 @@ -312,7 +312,12 @@ public class ConnectionPool { 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 = null; + if (getPoolProperties().getUseDisposableConnectionFacade() ) { + connection = (Connection)proxyClassConstructor.newInstance(new Object[] { new DisposableConnectionFacade(handler) }); + } else { + connection = (Connection)proxyClassConstructor.newInstance(new Object[] {handler}); + } //return the connection return connection; }catch (Exception x) { Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java Tue Mar 20 15:45:19 2012 @@ -1226,4 +1226,20 @@ public class DataSourceProxy implements return getPoolProperties().getRollbackOnReturn(); } + /** + * {@inheritDoc} + */ + @Override + public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade) { + getPoolProperties().setUseDisposableConnectionFacade(useDisposableConnectionFacade); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getUseDisposableConnectionFacade() { + return getPoolProperties().getUseDisposableConnectionFacade(); + } + } Added: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java?rev=1302948&view=auto ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java (added) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java Tue Mar 20 15:45:19 2012 @@ -0,0 +1,69 @@ +/* + * 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 DisposableConnectionFacade object is the top most interceptor that wraps an object of type + * {@link PooledConnection}. The ProxyCutOffConnection intercepts two methods: + * <ul> + * <li>{@link java.sql.Connection#close()} - returns the connection to the pool then breaks the link between cutoff and the next interceptor. May be called multiple times.</li> + * <li>{@link java.lang.Object#toString()} - returns a custom string for this object</li> + * </ul> + * By default method comparisons is done on a String reference level, unless the {@link PoolConfiguration#setUseEquals(boolean)} has been called + * with a <code>true</code> argument. + * @author Kevin Grainer + */ +public class DisposableConnectionFacade extends JdbcInterceptor { + protected DisposableConnectionFacade(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; + } + if (compare(CLOSE_VAL, method) && getNext() == null) { + return null; + } + + try { + return super.invoke(proxy, method, args); + } catch (NullPointerException e) { + if (getNext() == null) { + if (compare(TOSTRING_VAL, method)) { + return "DisposableConnectionFacade[null]"; + } + throw new SQLException("Connection has already been closed."); + } + + throw e; + } finally { + if (compare(CLOSE_VAL, method)) { + setNext(null); + } + } + } +} Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java Tue Mar 20 15:45:19 2012 @@ -70,7 +70,7 @@ public abstract class JdbcInterceptor im /** * The next interceptor in the chain */ - private JdbcInterceptor next = null; + private volatile JdbcInterceptor next = null; /** * Property that decides how we do string comparison, default is to use * {@link String#equals(Object)}. If set to <code>false</code> then the Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java Tue Mar 20 15:45:19 2012 @@ -821,4 +821,18 @@ public interface PoolConfiguration { */ public boolean getRollbackOnReturn(); + /** + * If set to true, the connection will be wrapped with facade that will disallow the connection to be used after + * {@link java.sql.Connection#close()} is called. If set to true, after {@link java.sql.Connection#close()} all calls except + * {@link java.sql.Connection#close()} and {@link java.sql.Connection#isClosed()} will throw an exception. + * @param useDisposableConnectionFacade + */ + public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade); + /** + * Returns true if this connection pool is configured to use a connection facade to prevent re-use of connection after + * {@link java.sql.Connection#close()} has been invoked + * @return true if {@link java.sql.Connection#close()} has been invoked. + */ + public boolean getUseDisposableConnectionFacade(); + } Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java Tue Mar 20 15:45:19 2012 @@ -86,6 +86,7 @@ public class PoolProperties implements P protected boolean alternateUsernameAllowed = false; protected boolean commitOnReturn = false; protected boolean rollbackOnReturn = false; + protected boolean useDisposableConnectionFacade; /** @@ -1194,4 +1195,29 @@ public class PoolProperties implements P public boolean getRollbackOnReturn() { return this.rollbackOnReturn; } + + /** + * {@inheritDoc} + */ + @Override + public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade) { + this.useDisposableConnectionFacade = useDisposableConnectionFacade; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getUseDisposableConnectionFacade() { + return useDisposableConnectionFacade; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + // TODO Auto-generated method stub + return super.clone(); + } + + + } Modified: tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java?rev=1302948&r1=1302947&r2=1302948&view=diff ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java (original) +++ tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java Tue Mar 20 15:45:19 2012 @@ -777,5 +777,22 @@ public class ConnectionPool extends Noti return getPoolProperties().getRollbackOnReturn(); } + /** + * {@inheritDoc} + */ + @Override + public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade) { + getPoolProperties().setUseDisposableConnectionFacade(useDisposableConnectionFacade); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean getUseDisposableConnectionFacade() { + return getPoolProperties().getUseDisposableConnectionFacade(); + } + + } Added: tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java?rev=1302948&view=auto ============================================================================== --- tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java (added) +++ tomcat/trunk/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/MultipleCloseTest.java Tue Mar 20 15:45:19 2012 @@ -0,0 +1,67 @@ +/* + * 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); + ds.getPoolProperties().setUseDisposableConnectionFacade(true); + 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()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org