jmcnally 2002/11/16 11:18:28 Modified: dbcp/src/java/org/apache/commons/dbcp/jdbc2pool CPDSConnectionFactory.java Jdbc2PoolDataSource.java KeyedCPDSConnectionFactory.java PoolKey.java UserPassKey.java dbcp/src/test/org/apache/commons/dbcp/jdbc2pool TestJdbc2PoolDataSource.java Added: dbcp/src/java/org/apache/commons/dbcp/jdbc2pool PooledConnectionAndInfo.java Log: Removed pools of PoolKey and UserPassKey and made the keys immutable. Storing the username and password used to obtain a PooledConnection along with the connection, so that it can be checked on later requests for the same connection. Revision Changes Path 1.3 +34 -13 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/CPDSConnectionFactory.java Index: CPDSConnectionFactory.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/CPDSConnectionFactory.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- CPDSConnectionFactory.java 1 Nov 2002 16:03:20 -0000 1.2 +++ CPDSConnectionFactory.java 16 Nov 2002 19:18:27 -0000 1.3 @@ -63,6 +63,7 @@ import java.util.Map; import java.util.HashMap; +import java.util.WeakHashMap; import java.sql.*; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; @@ -153,9 +154,10 @@ synchronized public Object makeObject() { - PooledConnection pc = null; + Object obj; try { + PooledConnection pc = null; if ( _username == null ) { pc = _cpds.getPooledConnection(); @@ -167,18 +169,21 @@ // should we add this object as a listener or the pool. // consider the validateObject method in decision pc.addConnectionEventListener(this); + obj = new PooledConnectionAndInfo(pc, _username, _password); + pcMap.put(pc, obj); } catch (SQLException e) { throw new RuntimeException(e.getMessage()); } - return pc; + return obj; } public void destroyObject(Object obj) { - if(obj instanceof PooledConnection) { + if(obj instanceof PooledConnectionAndInfo) { try { - ((PooledConnection)obj).close(); + ((PooledConnectionAndInfo)obj) + .getPooledConnection().close(); } catch(RuntimeException e) { throw e; } catch(SQLException e) { @@ -189,8 +194,9 @@ public boolean validateObject(Object obj) { boolean valid = false; - if(obj instanceof PooledConnection) { - PooledConnection pconn = (PooledConnection)obj; + if(obj instanceof PooledConnectionAndInfo) { + PooledConnection pconn = + ((PooledConnectionAndInfo)obj).getPooledConnection(); String query = _validationQuery; if(null != query) { Connection conn = null; @@ -264,13 +270,19 @@ // otherwise return the connection to the pool. if (!validatingMap.containsKey(pc)) { + Object info = pcMap.get(pc); + if (info == null) + { + throw new IllegalStateException(NO_KEY_MESSAGE); + } + try { - _pool.returnObject(pc); + _pool.returnObject(info); } catch (Exception e) { - destroyObject(pc); + destroyObject(info); System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); } @@ -300,9 +312,17 @@ // ignore } - destroyObject(pc); + Object info = pcMap.get(pc); + if (info == null) + { + throw new IllegalStateException(NO_KEY_MESSAGE); + } + destroyObject(info); } + private static final String NO_KEY_MESSAGE = + "close() was called on a Connection, but " + + "I have no record of the underlying PooledConnection."; protected ConnectionPoolDataSource _cpds = null; protected String _validationQuery = null; @@ -310,4 +330,5 @@ protected String _username = null; protected String _password = null; private Map validatingMap = new HashMap(); + private WeakHashMap pcMap = new WeakHashMap(); } 1.7 +65 -63 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/Jdbc2PoolDataSource.java Index: Jdbc2PoolDataSource.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/Jdbc2PoolDataSource.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- Jdbc2PoolDataSource.java 8 Nov 2002 19:17:24 -0000 1.6 +++ Jdbc2PoolDataSource.java 16 Nov 2002 19:18:27 -0000 1.7 @@ -83,12 +83,13 @@ import javax.sql.PooledConnection; import org.apache.commons.collections.FastHashMap; +import org.apache.commons.collections.LRUMap; import org.apache.commons.lang.SerializationUtils; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.pool.KeyedObjectPool; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.commons.pool.impl.GenericObjectPool; -import org.apache.commons.pool.impl.StackObjectPool; /** * <p> @@ -155,11 +156,8 @@ private static Map dsInstanceMap = new HashMap(); - private static ObjectPool userPassKeyPool = - new StackObjectPool(new UserPassKey.Factory(), 256); - - private static ObjectPool poolKeyPool = - new StackObjectPool(new PoolKey.Factory(), 256); + private static final Map userKeys = new LRUMap(10); + private static final Map poolKeys = new HashMap(); private boolean getConnectionCalled = false; @@ -1042,6 +1040,7 @@ "through setDataSourceName or setConnectionPoolDataSource " + "before calling getConnection."); } + getConnectionCalled = true; Map pools = (Map)dsInstanceMap.get(instanceKey); PoolKey key = getPoolKey(username); @@ -1059,29 +1058,33 @@ throw new SQLException(e.getMessage()); } } - returnPoolKey(key); - PooledConnection pc = null; + PooledConnectionAndInfo info = null; if (pool instanceof ObjectPool) { try { - pc = (PooledConnection)((ObjectPool)pool).borrowObject(); + info = (PooledConnectionAndInfo) + ((ObjectPool)pool).borrowObject(); } catch(NoSuchElementException e) { + closeDueToException(info); throw new SQLException(e.getMessage()); } catch(RuntimeException e) { + closeDueToException(info); throw e; } catch(SQLException e) { + closeDueToException(info); throw e; } catch(Exception e) { + closeDueToException(info); throw new SQLException(e.getMessage()); } } @@ -1089,29 +1092,39 @@ { try { - UserPassKey upkey = getPCKey(username, password); - pc = (PooledConnection) + UserPassKey upkey = getUserPassKey(username, password); + info = (PooledConnectionAndInfo) ((KeyedObjectPool)pool).borrowObject(upkey); - returnPCKey(upkey); } catch(NoSuchElementException e) { + closeDueToException(info); throw new SQLException(e.getMessage()); } catch(RuntimeException e) { + closeDueToException(info); throw e; } catch(SQLException e) - { + { + closeDueToException(info); throw e; } catch(Exception e) { + closeDueToException(info); throw new SQLException(e.getMessage()); } } - + if (!ObjectUtils.equals(password, info.getPassword())) + { + closeDueToException(info); + throw new SQLException("Given password did not match password used " + + "to create the PooledConnection."); + } + PooledConnection pc = info.getPooledConnection(); + boolean defaultAutoCommit = isDefaultAutoCommit(); if ( username != null ) { @@ -1139,38 +1152,22 @@ con.setReadOnly(defaultReadOnly); return con; } - - private UserPassKey getPCKey(String username, String password) - { - UserPassKey upk = null; - try - { - upk = (UserPassKey)userPassKeyPool.borrowObject(); - } - catch (Exception e) - { - getLogWriter().println("[WARN] Jdbc2PoolDataSource::getPCKey" - + " could not get key from pool. Created a new instance. " - + e.getMessage()); - upk = new UserPassKey(); - } - upk.init(username, password); - return upk; - } - - private void returnPCKey(UserPassKey key) + + private void closeDueToException(PooledConnectionAndInfo info) { - if (key.isReusable()) + if (info != null) { - try + try { - userPassKeyPool.returnObject(key); + info.getPooledConnection().getConnection().close(); } catch (Exception e) { - getLogWriter().println( - "[WARN] Jdbc2PoolDataSource::returnPCKey could not return" - + " key to pool. " + e.getMessage()); + // do not throw this exception because we are in the middle + // of handling another exception. But record it because + // it potentially leaks connections from the pool. + getLogWriter().println("[ERROR] Could not return connection to " + + "pool during exception handling. " + e.getMessage()); } } } @@ -1178,41 +1175,46 @@ private PoolKey getPoolKey(String username) { PoolKey key = null; - try - { - key = (PoolKey)poolKeyPool.borrowObject(); - } - catch (Exception e) - { - getLogWriter().println("[WARN] Jdbc2PoolDataSource::getPoolKey" - + " could not get key from pool. Created a new instance. " - + e.getMessage()); - key = new PoolKey(); - } + if ( username != null && (perUserMaxActive == null || !perUserMaxActive.containsKey(username)) ) { username = null; } - key.init(getDataSourceName(), username); - return key; - } - private void returnPoolKey(PoolKey key) - { - try + String dsName = getDataSourceName(); + Map dsMap = (Map)poolKeys.get(dsName); + if (dsMap != null) { - poolKeyPool.returnObject(key); + key = (PoolKey)dsMap.get(username); } - catch (Exception e) + + if (key == null) { - getLogWriter().println( - "[WARN] Jdbc2PoolDataSource::returnPoolKey could not return" - + " key to pool. " + e.getMessage()); + key = new PoolKey(dsName, username); + if (dsMap == null) + { + dsMap = new HashMap(); + poolKeys.put(dsName, dsMap); + } + dsMap.put(username, key); } + + return key; } + private UserPassKey getUserPassKey(String username, String password) + { + UserPassKey key = (UserPassKey)userKeys.get(username); + if (key == null) + { + key = new UserPassKey(username, password); + userKeys.put(username, key); + } + return key; + } + synchronized private void registerInstance() { if (isNew) 1.3 +26 -24 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/KeyedCPDSConnectionFactory.java Index: KeyedCPDSConnectionFactory.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/KeyedCPDSConnectionFactory.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- KeyedCPDSConnectionFactory.java 1 Nov 2002 16:03:21 -0000 1.2 +++ KeyedCPDSConnectionFactory.java 16 Nov 2002 19:18:27 -0000 1.3 @@ -147,38 +147,38 @@ } synchronized public Object makeObject(Object key) { + Object obj = null; UserPassKey upkey = (UserPassKey)key; - // since we are using the key to make a new object, we will - // declare the key invalid for reuse. - upkey.setReusable(false); - String username = upkey.getUsername(); - PooledConnection pc = null; try { + PooledConnection pc = null; + String username = upkey.getUsername(); + String password = upkey.getPassword(); if ( username == null ) { pc = _cpds.getPooledConnection(); } else { - pc = _cpds.getPooledConnection(username, upkey.getPassword()); + pc = _cpds.getPooledConnection(username, password); } // should we add this object as a listener or the pool. // consider the validateObject method in decision pc.addConnectionEventListener(this); - pcKeyMap.put(pc, key); + obj = new PooledConnectionAndInfo(pc, username, password); + pcMap.put(pc, obj); } catch (SQLException e) { throw new RuntimeException(e.getMessage()); } - return pc; + return obj; } public void destroyObject(Object key, Object obj) { - if(obj instanceof PooledConnection) { + if(obj instanceof PooledConnectionAndInfo) { try { - ((PooledConnection)obj).close(); + ((PooledConnectionAndInfo)obj).getPooledConnection().close(); } catch(RuntimeException e) { throw e; } catch(SQLException e) { @@ -189,8 +189,9 @@ public boolean validateObject(Object key, Object obj) { boolean valid = false; - if(obj instanceof PooledConnection) { - PooledConnection pconn = (PooledConnection)obj; + if(obj instanceof PooledConnectionAndInfo) { + PooledConnection pconn = + ((PooledConnectionAndInfo)obj).getPooledConnection(); String query = _validationQuery; if(null != query) { Connection conn = null; @@ -264,18 +265,19 @@ // otherwise return the connection to the pool. if (!validatingMap.containsKey(pc)) { - Object key = pcKeyMap.get(pc); - if (key == null) + PooledConnectionAndInfo info = + (PooledConnectionAndInfo)pcMap.get(pc); + if (info == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } try { - _pool.returnObject(key, pc); + _pool.returnObject(info.getUserPassKey(), info); } catch (Exception e) { - destroyObject(key, pc); + destroyObject(info.getUserPassKey(), info); System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); } @@ -305,12 +307,12 @@ // ignore } - Object key = pcKeyMap.get(pc); - if (key == null) + PooledConnectionAndInfo info = (PooledConnectionAndInfo)pcMap.get(pc); + if (info == null) { throw new IllegalStateException(NO_KEY_MESSAGE); } - destroyObject(key, pc); + destroyObject(info.getUserPassKey(), info); } private static final String NO_KEY_MESSAGE = @@ -321,5 +323,5 @@ protected String _validationQuery = null; protected KeyedObjectPool _pool = null; private Map validatingMap = new HashMap(); - private WeakHashMap pcKeyMap = new WeakHashMap(); + private WeakHashMap pcMap = new WeakHashMap(); } 1.2 +5 -64 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/PoolKey.java Index: PoolKey.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/PoolKey.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- PoolKey.java 5 Aug 2002 06:42:01 -0000 1.1 +++ PoolKey.java 16 Nov 2002 19:18:27 -0000 1.2 @@ -56,17 +56,17 @@ import java.io.Serializable; import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.pool.BasePoolableObjectFactory; class PoolKey implements Serializable { private String datasourceName; - private boolean reusable; private String username; - PoolKey() + PoolKey(String datasourceName, String username) { + this.datasourceName = datasourceName; + this.username = username; } /* * @@ -79,15 +79,6 @@ } /* * - * Set the value of datasourceName. - * @param v Value to assign to datasourceName. - * / - public void setDatasourceName(String v) - { - this.datasourceName = v; - } - - /* * * Get the value of username. * @return value of username. * / @@ -95,30 +86,8 @@ { return username; } + */ - /* * - * Set the value of username. - * @param v Value to assign to username. - * / - public void setUsername(String v) - { - this.username = v; - } - */ - - /** - * Initialize key for method with no arguments. - * - * @param instanceOrClass the Object on which the method is invoked. if - * the method is static, a String representing the class name is used. - * @param method the method name - */ - void init(String username, String datasourceName) - { - this.datasourceName = datasourceName; - this.username = username; - } - public boolean equals(Object obj) { boolean equal = false; @@ -141,7 +110,7 @@ } if (username != null) { - h += username.hashCode(); + h = 29 * h + username.hashCode(); } return h; } @@ -153,33 +122,5 @@ sb.append(username).append(", ").append(datasourceName); sb.append(')'); return sb.toString(); - } - - // ************* PoolableObjectFactory implementation ******************* - - static class Factory - extends BasePoolableObjectFactory - { - /** - * Creates an instance that can be returned by the pool. - * @return an instance that can be returned by the pool. - */ - public Object makeObject() - throws Exception - { - return new PoolKey(); - } - - /** - * Uninitialize an instance to be returned to the pool. - * @param obj the instance to be passivated - */ - public void passivateObject(Object obj) - throws Exception - { - PoolKey key = (PoolKey)obj; - key.datasourceName = null; - key.username = null; - } } } 1.2 +4 -86 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/UserPassKey.java Index: UserPassKey.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/UserPassKey.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- UserPassKey.java 5 Aug 2002 06:42:01 -0000 1.1 +++ UserPassKey.java 16 Nov 2002 19:18:27 -0000 1.2 @@ -56,17 +56,17 @@ import java.io.Serializable; import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.pool.BasePoolableObjectFactory; class UserPassKey implements Serializable { private String password; - private boolean reusable; private String username; - UserPassKey() + UserPassKey(String username, String password) { + this.username = username; + this.password = password; } /** @@ -79,35 +79,6 @@ } /** - * Set the value of password. - * @param v Value to assign to password. - */ - public void setPassword(String v) - { - this.password = v; - } - - - /** - * Get the value of reusable. - * @return value of reusable. - */ - public boolean isReusable() - { - return reusable; - } - - /** - * Set the value of reusable. - * @param v Value to assign to reusable. - */ - public void setReusable(boolean v) - { - this.reusable = v; - } - - - /** * Get the value of username. * @return value of username. */ @@ -116,29 +87,6 @@ return username; } - /** - * Set the value of username. - * @param v Value to assign to username. - */ - public void setUsername(String v) - { - this.username = v; - } - - /** - * Initialize key for method with no arguments. - * - * @param instanceOrClass the Object on which the method is invoked. if - * the method is static, a String representing the class name is used. - * @param method the method name - */ - void init(String username, String password) - { - this.reusable = true; - this.username = username; - this.password = password; - } - public boolean equals(Object obj) { boolean equal = false; @@ -165,37 +113,7 @@ { StringBuffer sb = new StringBuffer(50); sb.append("UserPassKey("); - sb.append(username).append(", ").append(password) - .append(", ").append(reusable); - sb.append(')'); + sb.append(username).append(", ").append(password).append(')'); return sb.toString(); - } - - // ************* PoolableObjectFactory implementation ******************* - - static class Factory - extends BasePoolableObjectFactory - { - /** - * Creates an instance that can be returned by the pool. - * @return an instance that can be returned by the pool. - */ - public Object makeObject() - throws Exception - { - return new UserPassKey(); - } - - /** - * Uninitialize an instance to be returned to the pool. - * @param obj the instance to be passivated - */ - public void passivateObject(Object obj) - throws Exception - { - UserPassKey key = (UserPassKey)obj; - key.username = null; - key.password = null; - } } } 1.1 jakarta-commons/dbcp/src/java/org/apache/commons/dbcp/jdbc2pool/PooledConnectionAndInfo.java Index: PooledConnectionAndInfo.java =================================================================== package org.apache.commons.dbcp.jdbc2pool; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache Turbine" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * "Apache Turbine", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ //import org.apache.commons.lang.ObjectUtils; import javax.sql.PooledConnection; final class PooledConnectionAndInfo { private final PooledConnection pooledConnection; private final String password; private final String username; private final UserPassKey upkey; PooledConnectionAndInfo(PooledConnection pc, String username, String password) { this.pooledConnection = pc; this.username = username; this.password = password; upkey = new UserPassKey(username, password); } final PooledConnection getPooledConnection() { return pooledConnection; } final UserPassKey getUserPassKey() { return upkey; } /** * Get the value of password. * @return value of password. */ final String getPassword() { return password; } /** * Get the value of username. * @return value of username. */ final String getUsername() { return username; } } 1.4 +212 -4 jakarta-commons/dbcp/src/test/org/apache/commons/dbcp/jdbc2pool/TestJdbc2PoolDataSource.java Index: TestJdbc2PoolDataSource.java =================================================================== RCS file: /home/cvs/jakarta-commons/dbcp/src/test/org/apache/commons/dbcp/jdbc2pool/TestJdbc2PoolDataSource.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- TestJdbc2PoolDataSource.java 8 Nov 2002 19:37:26 -0000 1.3 +++ TestJdbc2PoolDataSource.java 16 Nov 2002 19:18:27 -0000 1.4 @@ -64,6 +64,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import javax.sql.DataSource; import junit.framework.Test; @@ -107,6 +108,213 @@ tds.setPerUserMaxWait("foo",new Integer((int)(getMaxWait()))); ds = tds; + } + + public void testSimple() throws Exception + { + Connection conn = ds.getConnection(); + assertTrue(null != conn); + PreparedStatement stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + ResultSet rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + conn.close(); + } + + public void testSimpleWithUsername() throws Exception + { + Connection conn = ds.getConnection("u", "p"); + assertTrue(null != conn); + PreparedStatement stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + ResultSet rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + conn.close(); + } + + public void testClosingWithUserName() + throws Exception + { + Connection[] c = new Connection[getMaxActive()]; + // open the maximum connections + for (int i=0; i<c.length; i++) + { + c[i] = ds.getConnection("u", "p"); + } + + // close one of the connections + c[0].close(); + assertTrue(c[0].isClosed()); + // get a new connection + c[0] = ds.getConnection("u", "p"); + + for (int i=0; i<c.length; i++) + { + c[i].close(); + } + + // open the maximum connections + for (int i=0; i<c.length; i++) + { + c[i] = ds.getConnection("u", "p"); + } + for (int i=0; i<c.length; i++) + { + c[i].close(); + } + } + + public void testIncorrectPassword() + throws Exception + { + ds.getConnection("u", "p").close(); + try + { + ds.getConnection("u", "x").close(); + fail("Able to retrieve connection with incorrect password"); + } + catch (SQLException e) + { + if (!e.getMessage().startsWith("Given password did not match")) + { + throw e; + } + // else the exception was expected + } + } + + public void testSimple2() + throws Exception + { + Connection conn = ds.getConnection(); + assertTrue(null != conn); + + PreparedStatement stmt = + conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + ResultSet rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + conn.close(); + try + { + conn.createStatement(); + fail("Can't use closed connections"); + } + catch(SQLException e) + { + // expected + } + + conn = ds.getConnection(); + assertTrue(null != conn); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + stmt = conn.prepareStatement("select * from dual"); + assertTrue(null != stmt); + rset = stmt.executeQuery(); + assertTrue(null != rset); + assertTrue(rset.next()); + rset.close(); + stmt.close(); + + conn.close(); + conn = null; + } + + public void testOpening() + throws Exception + { + Connection[] c = new Connection[getMaxActive()]; + // test that opening new connections is not closing previous + for (int i=0; i<c.length; i++) + { + c[i] = ds.getConnection(); + assertTrue(c[i] != null); + for (int j=0; j<=i; j++) + { + assertTrue(!c[j].isClosed()); + } + } + + for (int i=0; i<c.length; i++) + { + c[i].close(); + } + } + + public void testClosing() + throws Exception + { + Connection[] c = new Connection[getMaxActive()]; + // open the maximum connections + for (int i=0; i<c.length; i++) + { + c[i] = ds.getConnection(); + } + + // close one of the connections + c[0].close(); + assertTrue(c[0].isClosed()); + + // get a new connection + c[0] = ds.getConnection(); + + for (int i=0; i<c.length; i++) + { + c[i].close(); + } + } + + public void testMaxActive() + throws Exception + { + Connection[] c = new Connection[getMaxActive()]; + for (int i=0; i<c.length; i++) + { + c[i] = ds.getConnection(); + assertTrue(c[i] != null); + } + + try + { + ds.getConnection(); + fail("Allowed to open more than DefaultMaxActive connections."); + } + catch(java.sql.SQLException e) + { + // should only be able to open 10 connections, so this test should + // throw an exception + } + + for (int i=0; i<c.length; i++) + { + c[i].close(); + } } public void testMultipleThreads() throws Exception {
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>