Coverage Report - org.apache.commons.dbcp.datasources.SharedPoolDataSource
 
Classes in this File Line Coverage Branch Coverage Complexity
SharedPoolDataSource
85%
64/75
78%
11/14
1.812
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.dbcp.datasources;
 19  
 
 20  
 import java.io.IOException;
 21  
 import java.io.ObjectInputStream;
 22  
 import java.sql.Connection;
 23  
 import java.sql.SQLException;
 24  
 
 25  
 import javax.naming.NamingException;
 26  
 import javax.naming.Reference;
 27  
 import javax.naming.StringRefAddr;
 28  
 import javax.sql.ConnectionPoolDataSource;
 29  
 
 30  
 import org.apache.commons.pool.KeyedObjectPool;
 31  
 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
 32  
 import org.apache.commons.pool.impl.GenericObjectPool;
 33  
 import org.apache.commons.dbcp.SQLNestedException;
 34  
 
 35  
 /**
 36  
  * <p>A pooling <code>DataSource</code> appropriate for deployment within
 37  
  * J2EE environment.  There are many configuration options, most of which are
 38  
  * defined in the parent class. All users (based on username) share a single 
 39  
  * maximum number of Connections in this datasource.</p>
 40  
  * 
 41  
  * <p>User passwords can be changed without re-initializing the datasource.
 42  
  * When a <code>getConnection(username, password)</code> request is processed 
 43  
  * with a password that is different from those used to create connections in the
 44  
  * pool associated with <code>username</code>, an attempt is made to create a
 45  
  * new connection using the supplied password and if this succeeds, idle connections
 46  
  * created using the old password are destroyed and new connections are created
 47  
  * using the new password.</p>
 48  
  *
 49  
  * @author John D. McNally
 50  
  * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $
 51  
  */
 52  
 public class SharedPoolDataSource
 53  
     extends InstanceKeyDataSource {
 54  
 
 55  
     private static final long serialVersionUID = -8132305535403690372L;
 56  
 
 57  92
     private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
 58  92
     private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
 59  92
     private int maxWait = (int)Math.min(Integer.MAX_VALUE,
 60  
         GenericObjectPool.DEFAULT_MAX_WAIT);
 61  92
     private transient KeyedObjectPool pool = null;
 62  92
     private transient KeyedCPDSConnectionFactory factory = null;
 63  
 
 64  
     /**
 65  
      * Default no-arg constructor for Serialization
 66  
      */
 67  92
     public SharedPoolDataSource() {
 68  92
     }
 69  
 
 70  
     /**
 71  
      * Close pool being maintained by this datasource.
 72  
      */
 73  
     public void close() throws Exception {
 74  4
         if (pool != null) {
 75  0
             pool.close();
 76  
         }
 77  4
         InstanceKeyObjectFactory.removeInstance(instanceKey);
 78  4
     }
 79  
 
 80  
     // -------------------------------------------------------------------
 81  
     // Properties
 82  
 
 83  
     /**
 84  
      * The maximum number of active connections that can be allocated from
 85  
      * this pool at the same time, or non-positive for no limit.
 86  
      */
 87  
     public int getMaxActive() {
 88  78
         return (this.maxActive);
 89  
     }
 90  
 
 91  
     /**
 92  
      * The maximum number of active connections that can be allocated from
 93  
      * this pool at the same time, or non-positive for no limit.
 94  
      * The default is 8.
 95  
      */
 96  
     public void setMaxActive(int maxActive) {
 97  80
         assertInitializationAllowed();
 98  80
         this.maxActive = maxActive;
 99  80
     }
 100  
 
 101  
     /**
 102  
      * The maximum number of active connections that can remain idle in the
 103  
      * pool, without extra ones being released, or negative for no limit.
 104  
      */
 105  
     public int getMaxIdle() {
 106  78
         return (this.maxIdle);
 107  
     }
 108  
 
 109  
     /**
 110  
      * The maximum number of active connections that can remain idle in the
 111  
      * pool, without extra ones being released, or negative for no limit.
 112  
      * The default is 8.
 113  
      */
 114  
     public void setMaxIdle(int maxIdle) {
 115  2
         assertInitializationAllowed();
 116  2
         this.maxIdle = maxIdle;
 117  2
     }
 118  
 
 119  
     /**
 120  
      * The maximum number of milliseconds that the pool will wait (when there
 121  
      * are no available connections) for a connection to be returned before
 122  
      * throwing an exception, or -1 to wait indefinitely.  Will fail 
 123  
      * immediately if value is 0.
 124  
      * The default is -1.
 125  
      */
 126  
     public int getMaxWait() {
 127  78
         return (this.maxWait);
 128  
     }
 129  
 
 130  
     /**
 131  
      * The maximum number of milliseconds that the pool will wait (when there
 132  
      * are no available connections) for a connection to be returned before
 133  
      * throwing an exception, or -1 to wait indefinitely.  Will fail 
 134  
      * immediately if value is 0.
 135  
      * The default is -1.
 136  
      */
 137  
     public void setMaxWait(int maxWait) {
 138  86
         assertInitializationAllowed();
 139  86
         this.maxWait = maxWait;
 140  86
     }
 141  
 
 142  
     // ----------------------------------------------------------------------
 143  
     // Instrumentation Methods
 144  
 
 145  
     /**
 146  
      * Get the number of active connections in the pool.
 147  
      */
 148  
     public int getNumActive() {
 149  6
         return (pool == null) ? 0 : pool.getNumActive();
 150  
     }
 151  
 
 152  
     /**
 153  
      * Get the number of idle connections in the pool.
 154  
      */
 155  
     public int getNumIdle() {
 156  12
         return (pool == null) ? 0 : pool.getNumIdle();
 157  
     }
 158  
 
 159  
     // ----------------------------------------------------------------------
 160  
     // Inherited abstract methods
 161  
 
 162  
     protected PooledConnectionAndInfo 
 163  
         getPooledConnectionAndInfo(String username, String password)
 164  
         throws SQLException {
 165  
         
 166  3394
         synchronized(this) {
 167  3394
             if (pool == null) {
 168  
                 try {
 169  80
                     registerPool(username, password);
 170  0
                 } catch (NamingException e) {
 171  0
                     throw new SQLNestedException("RegisterPool failed", e);
 172  78
                 }
 173  
             }
 174  3392
         }
 175  
 
 176  3392
         PooledConnectionAndInfo info = null;
 177  
         
 178  3392
         UserPassKey key = new UserPassKey(username, password);
 179  
         
 180  
         try {
 181  3392
             info = (PooledConnectionAndInfo) pool.borrowObject(key);
 182  
         }
 183  66
         catch (Exception e) {
 184  66
             throw new SQLNestedException(
 185  
                     "Could not retrieve connection info from pool", e);
 186  3326
         }
 187  3326
         return info;
 188  
     }
 189  
     
 190  
     protected PooledConnectionManager getConnectionManager(UserPassKey upkey)  {
 191  4
         return factory;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Returns a <code>SharedPoolDataSource</code> {@link Reference}.
 196  
      * 
 197  
      * @since 1.2.2
 198  
      */
 199  
     public Reference getReference() throws NamingException {
 200  2
         Reference ref = new Reference(getClass().getName(),
 201  
             SharedPoolDataSourceFactory.class.getName(), null);
 202  2
         ref.add(new StringRefAddr("instanceKey", instanceKey));
 203  2
         return ref;
 204  
     }
 205  
     
 206  
     private void registerPool(
 207  
         String username, String password) 
 208  
         throws javax.naming.NamingException, SQLException {
 209  
 
 210  80
         ConnectionPoolDataSource cpds = testCPDS(username, password);
 211  
 
 212  
         // Create an object pool to contain our PooledConnections
 213  78
         GenericKeyedObjectPool tmpPool = new GenericKeyedObjectPool(null);
 214  78
         tmpPool.setMaxActive(getMaxActive());
 215  78
         tmpPool.setMaxIdle(getMaxIdle());
 216  78
         tmpPool.setMaxWait(getMaxWait());
 217  78
         tmpPool.setWhenExhaustedAction(whenExhaustedAction(maxActive, maxWait));
 218  78
         tmpPool.setTestOnBorrow(getTestOnBorrow());
 219  78
         tmpPool.setTestOnReturn(getTestOnReturn());
 220  78
         tmpPool.setTimeBetweenEvictionRunsMillis(
 221  
             getTimeBetweenEvictionRunsMillis());
 222  78
         tmpPool.setNumTestsPerEvictionRun(getNumTestsPerEvictionRun());
 223  78
         tmpPool.setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
 224  78
         tmpPool.setTestWhileIdle(getTestWhileIdle());
 225  78
         pool = tmpPool;
 226  
         // Set up the factory we will use (passing the pool associates
 227  
         // the factory with the pool, so we do not have to do so
 228  
         // explicitly)
 229  78
         factory = new KeyedCPDSConnectionFactory(cpds, pool, getValidationQuery(),
 230  
                                        isRollbackAfterValidation());
 231  78
     }
 232  
 
 233  
     protected void setupDefaults(Connection con, String username) throws SQLException {
 234  3314
         boolean defaultAutoCommit = isDefaultAutoCommit();
 235  3314
         if (con.getAutoCommit() != defaultAutoCommit) {
 236  2
             con.setAutoCommit(defaultAutoCommit);
 237  
         }
 238  
 
 239  3314
         int defaultTransactionIsolation = getDefaultTransactionIsolation();
 240  3314
         if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) {
 241  3308
             con.setTransactionIsolation(defaultTransactionIsolation);
 242  
         }
 243  
 
 244  3314
         boolean defaultReadOnly = isDefaultReadOnly();
 245  3314
         if (con.isReadOnly() != defaultReadOnly) {
 246  0
             con.setReadOnly(defaultReadOnly);
 247  
         }
 248  3314
     }
 249  
 
 250  
     /**
 251  
      * Supports Serialization interface.
 252  
      *
 253  
      * @param in a <code>java.io.ObjectInputStream</code> value
 254  
      * @exception IOException if an error occurs
 255  
      * @exception ClassNotFoundException if an error occurs
 256  
      */
 257  
     private void readObject(ObjectInputStream in)
 258  
         throws IOException, ClassNotFoundException {
 259  
         try 
 260  
         {
 261  0
             in.defaultReadObject();
 262  0
             SharedPoolDataSource oldDS = (SharedPoolDataSource)
 263  
                 new SharedPoolDataSourceFactory()
 264  
                     .getObjectInstance(getReference(), null, null, null);
 265  0
             this.pool = oldDS.pool;
 266  
         }
 267  0
         catch (NamingException e)
 268  
         {
 269  0
             throw new IOException("NamingException: " + e);
 270  0
         }
 271  0
     }
 272  
 }
 273