Coverage Report - org.apache.commons.dbcp.BasicDataSource
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicDataSource
78%
277/353
64%
68/106
2.049
 
 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;
 19  
 
 20  
 import java.io.PrintWriter;
 21  
 import java.util.Properties;
 22  
 import java.util.Collection;
 23  
 import java.util.List;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Iterator;
 26  
 import java.util.Collections;
 27  
 import java.sql.Connection;
 28  
 import java.sql.Driver;
 29  
 import java.sql.DriverManager;
 30  
 import java.sql.SQLException;
 31  
 import javax.sql.DataSource;
 32  
 
 33  
 import org.apache.commons.pool.KeyedObjectPoolFactory;
 34  
 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
 35  
 import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
 36  
 import org.apache.commons.pool.impl.GenericObjectPool;
 37  
 
 38  
 
 39  
 /**
 40  
  * <p>Basic implementation of <code>javax.sql.DataSource</code> that is
 41  
  * configured via JavaBeans properties.  This is not the only way to
 42  
  * combine the <em>commons-dbcp</em> and <em>commons-pool</em> packages,
 43  
  * but provides a "one stop shopping" solution for basic requirements.</p>
 44  
  * 
 45  
  * <p>Users extending this class should take care to use appropriate accessors
 46  
  * rather than accessing protected fields directly to ensure thread-safety.</p>
 47  
  *
 48  
  * @author Glenn L. Nielsen
 49  
  * @author Craig R. McClanahan
 50  
  * @author Dirk Verbeeck
 51  
  * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $
 52  
  */
 53  398
 public class BasicDataSource implements DataSource {
 54  
     
 55  
     static {
 56  
         // Attempt to prevent deadlocks - see DBCP - 272
 57  2
         DriverManager.getDrivers();
 58  2
     }
 59  
 
 60  
     // ------------------------------------------------------------- Properties
 61  
 
 62  
     /**
 63  
      * The default auto-commit state of connections created by this pool.
 64  
      */
 65  398
     protected volatile boolean defaultAutoCommit = true;
 66  
 
 67  
     /**
 68  
      * Returns the default auto-commit property.
 69  
      * 
 70  
      * @return true if default auto-commit is enabled
 71  
      */
 72  
     public boolean getDefaultAutoCommit() {
 73  2
         return this.defaultAutoCommit;
 74  
     }
 75  
 
 76  
     /**
 77  
      * <p>Sets default auto-commit state of connections returned by this
 78  
      * datasource.</p>
 79  
      * <p>
 80  
      * Note: this method currently has no effect once the pool has been
 81  
      * initialized.  The pool is initialized the first time one of the
 82  
      * following methods is invoked: <code>getConnection, setLogwriter,
 83  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 84  
      * 
 85  
      * @param defaultAutoCommit default auto-commit value
 86  
      */
 87  
     public void setDefaultAutoCommit(boolean defaultAutoCommit) {
 88  408
         this.defaultAutoCommit = defaultAutoCommit;
 89  408
         this.restartNeeded = true;
 90  408
     }
 91  
 
 92  
 
 93  
     /**
 94  
      * The default read-only state of connections created by this pool.
 95  
      */
 96  398
     protected transient Boolean defaultReadOnly = null;
 97  
 
 98  
     /**
 99  
      * Returns the default readOnly property.
 100  
      * 
 101  
      * @return true if connections are readOnly by default
 102  
      */
 103  
     public boolean getDefaultReadOnly() {
 104  2
         Boolean val = defaultReadOnly;
 105  2
         if (val != null) {
 106  2
             return val.booleanValue();
 107  
         }
 108  0
         return false;
 109  
     }
 110  
 
 111  
     /**
 112  
      * <p>Sets defaultReadonly property.</p>
 113  
      * <p>
 114  
      * Note: this method currently has no effect once the pool has been
 115  
      * initialized.  The pool is initialized the first time one of the
 116  
      * following methods is invoked: <code>getConnection, setLogwriter,
 117  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 118  
      * 
 119  
      * @param defaultReadOnly default read-only value
 120  
      */
 121  
     public void setDefaultReadOnly(boolean defaultReadOnly) {
 122  400
         this.defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
 123  400
         this.restartNeeded = true;
 124  400
     }
 125  
 
 126  
     /**
 127  
      * The default TransactionIsolation state of connections created by this pool.
 128  
      */
 129  398
     protected volatile int defaultTransactionIsolation =
 130  
         PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION;
 131  
 
 132  
     /**
 133  
      * Returns the default transaction isolation state of returned connections.
 134  
      * 
 135  
      * @return the default value for transaction isolation state
 136  
      * @see Connection#getTransactionIsolation
 137  
      */
 138  
     public int getDefaultTransactionIsolation() {
 139  2
         return this.defaultTransactionIsolation;
 140  
     }
 141  
 
 142  
     /**
 143  
      * <p>Sets the default transaction isolation state for returned
 144  
      * connections.</p>
 145  
      * <p>
 146  
      * Note: this method currently has no effect once the pool has been
 147  
      * initialized.  The pool is initialized the first time one of the
 148  
      * following methods is invoked: <code>getConnection, setLogwriter,
 149  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 150  
      * 
 151  
      * @param defaultTransactionIsolation the default transaction isolation
 152  
      * state
 153  
      * @see Connection#getTransactionIsolation
 154  
      */
 155  
     public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
 156  392
         this.defaultTransactionIsolation = defaultTransactionIsolation;
 157  392
         this.restartNeeded = true;
 158  392
     }
 159  
 
 160  
 
 161  
     /**
 162  
      * The default "catalog" of connections created by this pool.
 163  
      */
 164  398
     protected volatile String defaultCatalog = null;
 165  
 
 166  
     /**
 167  
      * Returns the default catalog.
 168  
      * 
 169  
      * @return the default catalog
 170  
      */
 171  
     public String getDefaultCatalog() {
 172  2
         return this.defaultCatalog;
 173  
     }
 174  
 
 175  
     /**
 176  
      * <p>Sets the default catalog.</p>
 177  
      * <p>
 178  
      * Note: this method currently has no effect once the pool has been
 179  
      * initialized.  The pool is initialized the first time one of the
 180  
      * following methods is invoked: <code>getConnection, setLogwriter,
 181  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 182  
      * 
 183  
      * @param defaultCatalog the default catalog
 184  
      */
 185  
     public void setDefaultCatalog(String defaultCatalog) {
 186  392
         if ((defaultCatalog != null) && (defaultCatalog.trim().length() > 0)) {
 187  392
             this.defaultCatalog = defaultCatalog;
 188  
         }
 189  
         else {
 190  0
             this.defaultCatalog = null;
 191  
         }
 192  392
         this.restartNeeded = true;
 193  392
     }
 194  
 
 195  
   
 196  
     /**
 197  
      * The fully qualified Java class name of the JDBC driver to be used.
 198  
      */
 199  398
     protected String driverClassName = null;
 200  
 
 201  
     /**
 202  
      * Returns the jdbc driver class name.
 203  
      * 
 204  
      * @return the jdbc driver class name
 205  
      */
 206  
     public synchronized String getDriverClassName() {
 207  2
         return this.driverClassName;
 208  
     }
 209  
 
 210  
     /**
 211  
      * <p>Sets the jdbc driver class name.</p>
 212  
      * <p>
 213  
      * Note: this method currently has no effect once the pool has been
 214  
      * initialized.  The pool is initialized the first time one of the
 215  
      * following methods is invoked: <code>getConnection, setLogwriter,
 216  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 217  
      * 
 218  
      * @param driverClassName the class name of the jdbc driver
 219  
      */
 220  
     public synchronized void setDriverClassName(String driverClassName) {
 221  394
         if ((driverClassName != null) && (driverClassName.trim().length() > 0)) {
 222  394
             this.driverClassName = driverClassName;
 223  
         }
 224  
         else {
 225  0
             this.driverClassName = null;
 226  
         }
 227  394
         this.restartNeeded = true;
 228  394
     }
 229  
 
 230  
     /**
 231  
      * The class loader instance to use to load the JDBC driver. If not
 232  
      * specified, {@link Class#forName(String)} is used to load the JDBC driver.
 233  
      * If specified, {@link Class#forName(String, boolean, ClassLoader)} is
 234  
      * used.
 235  
      */
 236  398
     protected ClassLoader driverClassLoader = null;
 237  
     
 238  
     /**
 239  
      * Returns the class loader specified for loading the JDBC driver. Returns
 240  
      * <code>null</code> if no class loader has been explicitly specified.
 241  
      */
 242  
     public synchronized ClassLoader getDriverClassLoader() {
 243  0
         return this.driverClassLoader;
 244  
     }
 245  
 
 246  
     /**
 247  
      * <p>Sets the class loader to be used to load the JDBC driver.</p>
 248  
      * <p>
 249  
      * Note: this method currently has no effect once the pool has been
 250  
      * initialized.  The pool is initialized the first time one of the
 251  
      * following methods is invoked: <code>getConnection, setLogwriter,
 252  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 253  
      * 
 254  
      * @param driverClassLoader the class loader with which to load the JDBC
 255  
      *                          driver
 256  
      */
 257  
     public synchronized void setDriverClassLoader(
 258  
             ClassLoader driverClassLoader) {
 259  0
         this.driverClassLoader = driverClassLoader;
 260  0
         this.restartNeeded = true;
 261  0
     }
 262  
     
 263  
     /**
 264  
      * The maximum number of active connections that can be allocated from
 265  
      * this pool at the same time, or negative for no limit.
 266  
      */
 267  398
     protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
 268  
 
 269  
     /**
 270  
      * <p>Returns the maximum number of active connections that can be
 271  
      * allocated at the same time.
 272  
      * </p>
 273  
      * <p>A negative number means that there is no limit.</p>
 274  
      * 
 275  
      * @return the maximum number of active connections
 276  
      */
 277  
     public synchronized int getMaxActive() {
 278  2
         return this.maxActive;
 279  
     }
 280  
 
 281  
     /**
 282  
      * Sets the maximum number of active connections that can be
 283  
      * allocated at the same time. Use a negative value for no limit.
 284  
      * 
 285  
      * @param maxActive the new value for maxActive
 286  
      * @see #getMaxActive()
 287  
      */
 288  
     public synchronized void setMaxActive(int maxActive) {
 289  422
         this.maxActive = maxActive;
 290  422
         if (connectionPool != null) {
 291  0
             connectionPool.setMaxActive(maxActive);
 292  
         }
 293  422
     }
 294  
 
 295  
     /**
 296  
      * The maximum number of connections that can remain idle in the
 297  
      * pool, without extra ones being destroyed, or negative for no limit.
 298  
      * If maxIdle is set too low on heavily loaded systems it is possible you
 299  
      * will see connections being closed and almost immediately new connections
 300  
      * being opened. This is a result of the active threads momentarily closing
 301  
      * connections faster than they are opening them, causing the number of idle
 302  
      * connections to rise above maxIdle. The best value for maxIdle for heavily
 303  
      * loaded system will vary but the default is a good starting point.
 304  
      */
 305  398
     protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
 306  
 
 307  
     /**
 308  
      * <p>Returns the maximum number of connections that can remain idle in the
 309  
      * pool. Excess idle connections are destroyed on return to the pool.
 310  
      * </p>
 311  
      * <p>A negative value indicates that there is no limit</p>
 312  
      * 
 313  
      * @return the maximum number of idle connections
 314  
      */
 315  
     public synchronized int getMaxIdle() {
 316  2
         return this.maxIdle;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Sets the maximum number of connections that can remain idle in the
 321  
      * pool. Excess idle connections are destroyed on return to the pool.
 322  
      * 
 323  
      * @see #getMaxIdle()
 324  
      * @param maxIdle the new value for maxIdle
 325  
      */
 326  
     public synchronized void setMaxIdle(int maxIdle) {
 327  16
         this.maxIdle = maxIdle;
 328  16
         if (connectionPool != null) {
 329  0
             connectionPool.setMaxIdle(maxIdle);
 330  
         }
 331  16
     }
 332  
 
 333  
     /**
 334  
      * The minimum number of active connections that can remain idle in the
 335  
      * pool, without extra ones being created when the evictor runs, or 0 to create none. 
 336  
      * The pool attempts to ensure that minIdle connections are available when the idle object evictor
 337  
      * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis}
 338  
      * has a positive value.
 339  
      */
 340  398
     protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
 341  
 
 342  
     /**
 343  
      * Returns the minimum number of idle connections in the pool. The pool attempts
 344  
      * to ensure that minIdle connections are available when the idle object evictor
 345  
      * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis}
 346  
      * has a positive value.
 347  
      * 
 348  
      * @return the minimum number of idle connections
 349  
      * @see GenericObjectPool#getMinIdle()
 350  
      */
 351  
     public synchronized int getMinIdle() {
 352  2
         return this.minIdle;
 353  
     }
 354  
 
 355  
     /**
 356  
      * Sets the minimum number of idle connections in the pool. The pool attempts
 357  
      * to ensure that minIdle connections are available when the idle object evictor
 358  
      * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis}
 359  
      * has a positive value.
 360  
      * 
 361  
      * @param minIdle the new value for minIdle
 362  
      * @see GenericObjectPool#setMinIdle(int)
 363  
      */
 364  
     public synchronized void setMinIdle(int minIdle) {
 365  2
        this.minIdle = minIdle;
 366  2
        if (connectionPool != null) {
 367  0
            connectionPool.setMinIdle(minIdle);
 368  
        }
 369  2
     }
 370  
 
 371  
     /**
 372  
      * The initial number of connections that are created when the pool
 373  
      * is started.
 374  
      * 
 375  
      * @since 1.2
 376  
      */
 377  398
     protected int initialSize = 0;
 378  
     
 379  
     /**
 380  
      * Returns the initial size of the connection pool.
 381  
      * 
 382  
      * @return the number of connections created when the pool is initialized
 383  
      */
 384  
     public synchronized int getInitialSize() {
 385  6
         return this.initialSize;
 386  
     }
 387  
     
 388  
     /**
 389  
      * <p>Sets the initial size of the connection pool.</p>
 390  
      * <p>
 391  
      * Note: this method currently has no effect once the pool has been
 392  
      * initialized.  The pool is initialized the first time one of the
 393  
      * following methods is invoked: <code>getConnection, setLogwriter,
 394  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 395  
      * 
 396  
      * @param initialSize the number of connections created when the pool
 397  
      * is initialized
 398  
      */
 399  
     public synchronized void setInitialSize(int initialSize) {
 400  10
         this.initialSize = initialSize;
 401  10
         this.restartNeeded = true;
 402  10
     }
 403  
 
 404  
     /**
 405  
      * The maximum number of milliseconds that the pool will wait (when there
 406  
      * are no available connections) for a connection to be returned before
 407  
      * throwing an exception, or <= 0 to wait indefinitely.
 408  
      */
 409  398
     protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
 410  
 
 411  
     /**
 412  
      * <p>Returns the maximum number of milliseconds that the pool will wait
 413  
      * for a connection to be returned before throwing an exception.
 414  
      * </p>
 415  
      * <p>A value less than or equal to zero means the pool is set to wait
 416  
      * indefinitely.</p>
 417  
      * 
 418  
      * @return the maxWait property value
 419  
      */
 420  
     public synchronized long getMaxWait() {
 421  2
         return this.maxWait;
 422  
     }
 423  
 
 424  
     /**
 425  
      * <p>Sets the maxWait property.
 426  
      * </p>
 427  
      * <p>Use -1 to make the pool wait indefinitely.
 428  
      * </p>
 429  
      * 
 430  
      * @param maxWait the new value for maxWait
 431  
      * @see #getMaxWait()
 432  
      */
 433  
     public synchronized void setMaxWait(long maxWait) {
 434  392
         this.maxWait = maxWait;
 435  392
         if (connectionPool != null) {
 436  0
             connectionPool.setMaxWait(maxWait);
 437  
         }
 438  392
     }
 439  
 
 440  
     /**
 441  
      * Prepared statement pooling for this pool. When this property is set to <code>true</code>
 442  
      * both PreparedStatements and CallableStatements are pooled.
 443  
      */
 444  398
     protected boolean poolPreparedStatements = false;
 445  
     
 446  
     /**
 447  
      * Returns true if we are pooling statements.
 448  
      * 
 449  
      * @return true if prepared and callable statements are pooled
 450  
      */
 451  
     public synchronized boolean isPoolPreparedStatements() {
 452  424
         return this.poolPreparedStatements;
 453  
     }
 454  
 
 455  
     /**
 456  
      * <p>Sets whether to pool statements or not.</p>
 457  
      * <p>
 458  
      * Note: this method currently has no effect once the pool has been
 459  
      * initialized.  The pool is initialized the first time one of the
 460  
      * following methods is invoked: <code>getConnection, setLogwriter,
 461  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 462  
      * 
 463  
      * @param poolingStatements pooling on or off
 464  
      */
 465  
     public synchronized void setPoolPreparedStatements(boolean poolingStatements) {
 466  102
         this.poolPreparedStatements = poolingStatements;
 467  102
         this.restartNeeded = true;
 468  102
     }
 469  
 
 470  
     /**
 471  
      * <p>The maximum number of open statements that can be allocated from
 472  
      * the statement pool at the same time, or non-positive for no limit.  Since 
 473  
      * a connection usually only uses one or two statements at a time, this is
 474  
      * mostly used to help detect resource leaks.</p>
 475  
      * 
 476  
      * <p>Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall})
 477  
      * are pooled along with PreparedStatements (produced by {@link Connection#prepareStatement})
 478  
      * and <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements
 479  
      * that may be in use at a given time.</p>
 480  
      */
 481  398
     protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
 482  
 
 483  
     /**
 484  
      * Gets the value of the {@link #maxOpenPreparedStatements} property.
 485  
      * 
 486  
      * @return the maximum number of open statements
 487  
      * @see #maxOpenPreparedStatements
 488  
      */
 489  
     public synchronized int getMaxOpenPreparedStatements() {
 490  2
         return this.maxOpenPreparedStatements;
 491  
     }
 492  
 
 493  
     /** 
 494  
      * <p>Sets the value of the {@link #maxOpenPreparedStatements}
 495  
      * property.</p>
 496  
      * <p>
 497  
      * Note: this method currently has no effect once the pool has been
 498  
      * initialized.  The pool is initialized the first time one of the
 499  
      * following methods is invoked: <code>getConnection, setLogwriter,
 500  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 501  
      * 
 502  
      * @param maxOpenStatements the new maximum number of prepared statements
 503  
      * @see #maxOpenPreparedStatements
 504  
      */
 505  
     public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) {
 506  104
         this.maxOpenPreparedStatements = maxOpenStatements;
 507  104
         this.restartNeeded = true;
 508  104
     }
 509  
 
 510  
     /**
 511  
      * The indication of whether objects will be validated before being
 512  
      * borrowed from the pool.  If the object fails to validate, it will be
 513  
      * dropped from the pool, and we will attempt to borrow another.
 514  
      */
 515  398
     protected boolean testOnBorrow = true;
 516  
 
 517  
     /**
 518  
      * Returns the {@link #testOnBorrow} property.
 519  
      * 
 520  
      * @return true if objects are validated before being borrowed from the
 521  
      * pool
 522  
      * 
 523  
      * @see #testOnBorrow
 524  
      */
 525  
     public synchronized boolean getTestOnBorrow() {
 526  34
         return this.testOnBorrow;
 527  
     }
 528  
 
 529  
     /**
 530  
      * Sets the {@link #testOnBorrow} property. This property determines
 531  
      * whether or not the pool will validate objects before they are borrowed
 532  
      * from the pool. For a <code>true</code> value to have any effect, the 
 533  
      * <code>validationQuery</code> property must be set to a non-null string.
 534  
      * 
 535  
      * @param testOnBorrow new value for testOnBorrow property
 536  
      */
 537  
     public synchronized void setTestOnBorrow(boolean testOnBorrow) {
 538  76
         this.testOnBorrow = testOnBorrow;
 539  76
         if (connectionPool != null) {
 540  0
             connectionPool.setTestOnBorrow(testOnBorrow);
 541  
         }
 542  76
     }
 543  
 
 544  
     /**
 545  
      * The indication of whether objects will be validated before being
 546  
      * returned to the pool.
 547  
      */
 548  398
     protected boolean testOnReturn = false;
 549  
 
 550  
     /**
 551  
      * Returns the value of the {@link #testOnReturn} property.
 552  
      * 
 553  
      * @return true if objects are validated before being returned to the
 554  
      * pool
 555  
      * @see #testOnReturn
 556  
      */
 557  
     public synchronized boolean getTestOnReturn() {
 558  34
         return this.testOnReturn;
 559  
     }
 560  
 
 561  
     /**
 562  
      * Sets the <code>testOnReturn</code> property. This property determines
 563  
      * whether or not the pool will validate objects before they are returned
 564  
      * to the pool. For a <code>true</code> value to have any effect, the 
 565  
      * <code>validationQuery</code> property must be set to a non-null string.
 566  
      * 
 567  
      * @param testOnReturn new value for testOnReturn property
 568  
      */
 569  
     public synchronized void setTestOnReturn(boolean testOnReturn) {
 570  68
         this.testOnReturn = testOnReturn;
 571  68
         if (connectionPool != null) {
 572  0
             connectionPool.setTestOnReturn(testOnReturn);
 573  
         }
 574  68
     }
 575  
 
 576  
     /**
 577  
      * The number of milliseconds to sleep between runs of the idle object
 578  
      * evictor thread.  When non-positive, no idle object evictor thread will
 579  
      * be run.
 580  
      */
 581  398
     protected long timeBetweenEvictionRunsMillis =
 582  
         GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
 583  
         
 584  
     /**
 585  
      * Returns the value of the {@link #timeBetweenEvictionRunsMillis}
 586  
      * property.
 587  
      * 
 588  
      * @return the time (in miliseconds) between evictor runs
 589  
      * @see #timeBetweenEvictionRunsMillis
 590  
      */
 591  
     public synchronized long getTimeBetweenEvictionRunsMillis() {
 592  2
         return this.timeBetweenEvictionRunsMillis;
 593  
     }
 594  
 
 595  
     /**
 596  
      * Sets the {@link #timeBetweenEvictionRunsMillis} property.
 597  
      * 
 598  
      * @param timeBetweenEvictionRunsMillis the new time between evictor runs
 599  
      * @see #timeBetweenEvictionRunsMillis
 600  
      */
 601  
     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
 602  10
         this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
 603  10
         if (connectionPool != null) {
 604  0
             connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
 605  
         }
 606  10
     }
 607  
 
 608  
     /**
 609  
      * The number of objects to examine during each run of the idle object
 610  
      * evictor thread (if any).
 611  
      */
 612  398
     protected int numTestsPerEvictionRun =
 613  
         GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
 614  
 
 615  
     /**
 616  
      * Returns the value of the {@link #numTestsPerEvictionRun} property.
 617  
      * 
 618  
      * @return the number of objects to examine during idle object evictor
 619  
      * runs
 620  
      * @see #numTestsPerEvictionRun
 621  
      */
 622  
     public synchronized int getNumTestsPerEvictionRun() {
 623  2
         return this.numTestsPerEvictionRun;
 624  
     }
 625  
 
 626  
     /**
 627  
      * Sets the value of the {@link #numTestsPerEvictionRun} property.
 628  
      * 
 629  
      * @param numTestsPerEvictionRun the new {@link #numTestsPerEvictionRun} 
 630  
      * value
 631  
      * @see #numTestsPerEvictionRun
 632  
      */
 633  
     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
 634  2
         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
 635  2
         if (connectionPool != null) {
 636  0
             connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
 637  
         }
 638  2
     }
 639  
 
 640  
     /**
 641  
      * The minimum amount of time an object may sit idle in the pool before it
 642  
      * is eligible for eviction by the idle object evictor (if any).
 643  
      */
 644  398
     protected long minEvictableIdleTimeMillis =
 645  
         GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
 646  
 
 647  
     /**
 648  
      * Returns the {@link #minEvictableIdleTimeMillis} property.
 649  
      * 
 650  
      * @return the value of the {@link #minEvictableIdleTimeMillis} property
 651  
      * @see #minEvictableIdleTimeMillis
 652  
      */
 653  
     public synchronized long getMinEvictableIdleTimeMillis() {
 654  2
         return this.minEvictableIdleTimeMillis;
 655  
     }
 656  
 
 657  
     /**
 658  
      * Sets the {@link #minEvictableIdleTimeMillis} property.
 659  
      * 
 660  
      * @param minEvictableIdleTimeMillis the minimum amount of time an object
 661  
      * may sit idle in the pool 
 662  
      * @see #minEvictableIdleTimeMillis
 663  
      */
 664  
     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
 665  2
         this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
 666  2
         if (connectionPool != null) {
 667  0
             connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
 668  
         }
 669  2
     }
 670  
 
 671  
     /**
 672  
      * The indication of whether objects will be validated by the idle object
 673  
      * evictor (if any).  If an object fails to validate, it will be dropped
 674  
      * from the pool.
 675  
      */
 676  398
     protected boolean testWhileIdle = false;
 677  
 
 678  
     /**
 679  
      * Returns the value of the {@link #testWhileIdle} property.
 680  
      * 
 681  
      * @return true if objects examined by the idle object evictor are
 682  
      * validated
 683  
      * @see #testWhileIdle
 684  
      */
 685  
     public synchronized boolean getTestWhileIdle() {
 686  34
         return this.testWhileIdle;
 687  
     }
 688  
 
 689  
     /**
 690  
      * Sets the <code>testWhileIdle</code> property. This property determines
 691  
      * whether or not the idle object evictor will validate connections.  For a
 692  
      * <code>true</code> value to have any effect, the 
 693  
      * <code>validationQuery</code> property must be set to a non-null string.
 694  
      * 
 695  
      * @param testWhileIdle new value for testWhileIdle property
 696  
      */
 697  
     public synchronized void setTestWhileIdle(boolean testWhileIdle) {
 698  44
         this.testWhileIdle = testWhileIdle;
 699  44
         if (connectionPool != null) {
 700  0
             connectionPool.setTestWhileIdle(testWhileIdle);
 701  
         }
 702  44
     }
 703  
 
 704  
     /**
 705  
      * [Read Only] The current number of active connections that have been
 706  
      * allocated from this data source.
 707  
      * 
 708  
      * @return the current number of active connections
 709  
      */
 710  
     public synchronized int getNumActive() {
 711  50
         if (connectionPool != null) {
 712  50
             return connectionPool.getNumActive();
 713  
         } else {
 714  0
             return 0;
 715  
         }
 716  
     }
 717  
 
 718  
 
 719  
     /**
 720  
      * [Read Only] The current number of idle connections that are waiting
 721  
      * to be allocated from this data source.
 722  
      * 
 723  
      * @return the current number of idle connections
 724  
      */
 725  
     public synchronized int getNumIdle() {
 726  20
         if (connectionPool != null) {
 727  20
             return connectionPool.getNumIdle();
 728  
         } else {
 729  0
             return 0;
 730  
         }
 731  
     }
 732  
 
 733  
     /**
 734  
      * The connection password to be passed to our JDBC driver to establish
 735  
      * a connection.
 736  
      */
 737  398
     protected volatile String password = null;
 738  
 
 739  
     /**
 740  
      * Returns the password passed to the JDBC driver to establish connections.
 741  
      * 
 742  
      * @return the connection password
 743  
      */
 744  
     public String getPassword() {
 745  2
         return this.password;
 746  
     }
 747  
 
 748  
     /** 
 749  
      * <p>Sets the {@link #password}.</p>
 750  
      * <p>
 751  
      * Note: this method currently has no effect once the pool has been
 752  
      * initialized.  The pool is initialized the first time one of the
 753  
      * following methods is invoked: <code>getConnection, setLogwriter,
 754  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 755  
      * 
 756  
      * @param password new value for the password
 757  
      */
 758  
     public void setPassword(String password) {
 759  394
         this.password = password;
 760  394
         this.restartNeeded = true;
 761  394
     }
 762  
 
 763  
     /**
 764  
      * The connection URL to be passed to our JDBC driver to establish
 765  
      * a connection.
 766  
      */
 767  398
     protected String url = null;
 768  
 
 769  
     /**
 770  
      * Returns the JDBC connection {@link #url} property.
 771  
      * 
 772  
      * @return the {@link #url} passed to the JDBC driver to establish
 773  
      * connections
 774  
      */
 775  
     public synchronized String getUrl() {
 776  2
         return this.url;
 777  
     }
 778  
 
 779  
     /** 
 780  
      * <p>Sets the {@link #url}.</p>
 781  
      * <p>
 782  
      * Note: this method currently has no effect once the pool has been
 783  
      * initialized.  The pool is initialized the first time one of the
 784  
      * following methods is invoked: <code>getConnection, setLogwriter,
 785  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 786  
      * 
 787  
      * @param url the new value for the JDBC connection url
 788  
      */
 789  
     public synchronized void setUrl(String url) {
 790  394
         this.url = url;
 791  394
         this.restartNeeded = true;
 792  394
     }
 793  
 
 794  
     /**
 795  
      * The connection username to be passed to our JDBC driver to
 796  
      * establish a connection.
 797  
      */
 798  398
     protected String username = null;
 799  
 
 800  
     /**
 801  
      * Returns the JDBC connection {@link #username} property.
 802  
      * 
 803  
      * @return the {@link #username} passed to the JDBC driver to establish
 804  
      * connections
 805  
      */
 806  
     public String getUsername() {
 807  2
         return this.username;
 808  
     }
 809  
 
 810  
     /** 
 811  
      * <p>Sets the {@link #username}.</p>
 812  
      * <p>
 813  
      * Note: this method currently has no effect once the pool has been
 814  
      * initialized.  The pool is initialized the first time one of the
 815  
      * following methods is invoked: <code>getConnection, setLogwriter,
 816  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 817  
      * 
 818  
      * @param username the new value for the JDBC connection username
 819  
      */
 820  
     public void setUsername(String username) {
 821  394
         this.username = username;
 822  394
         this.restartNeeded = true;
 823  394
     }
 824  
 
 825  
     /**
 826  
      * The SQL query that will be used to validate connections from this pool
 827  
      * before returning them to the caller.  If specified, this query
 828  
      * <strong>MUST</strong> be an SQL SELECT statement that returns at least
 829  
      * one row.
 830  
      */
 831  398
     protected volatile String validationQuery = null;
 832  
 
 833  
     /**
 834  
      * Returns the validation query used to validate connections before
 835  
      * returning them.
 836  
      * 
 837  
      * @return the SQL validation query
 838  
      * @see #validationQuery
 839  
      */
 840  
     public String getValidationQuery() {
 841  26
         return this.validationQuery;
 842  
     }
 843  
 
 844  
     /** 
 845  
      * <p>Sets the {@link #validationQuery}.</p>
 846  
      * <p>
 847  
      * Note: this method currently has no effect once the pool has been
 848  
      * initialized.  The pool is initialized the first time one of the
 849  
      * following methods is invoked: <code>getConnection, setLogwriter,
 850  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 851  
      * 
 852  
      * @param validationQuery the new value for the validation query
 853  
      */
 854  
     public void setValidationQuery(String validationQuery) {
 855  432
         if ((validationQuery != null) && (validationQuery.trim().length() > 0)) {
 856  408
             this.validationQuery = validationQuery;
 857  
         } else {
 858  24
             this.validationQuery = null;
 859  
         }
 860  432
         this.restartNeeded = true;
 861  432
     }
 862  
     
 863  
     /**
 864  
      * Timeout in seconds before connection validation queries fail. 
 865  
      * 
 866  
      * @since 1.3
 867  
      */
 868  398
     protected volatile int validationQueryTimeout = -1;
 869  
     
 870  
     /**
 871  
      * Returns the validation query timeout.
 872  
      * 
 873  
      * @return the timeout in seconds before connection validation queries fail.
 874  
      * @since 1.3
 875  
      */
 876  
     public int getValidationQueryTimeout() {
 877  2
         return validationQueryTimeout;
 878  
     }
 879  
     
 880  
     /**
 881  
      * Sets the validation query timeout, the amount of time, in seconds, that
 882  
      * connection validation will wait for a response from the database when
 883  
      * executing a validation query.  Use a value less than or equal to 0 for
 884  
      * no timeout.
 885  
      * <p>
 886  
      * Note: this method currently has no effect once the pool has been
 887  
      * initialized.  The pool is initialized the first time one of the
 888  
      * following methods is invoked: <code>getConnection, setLogwriter,
 889  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 890  
      * 
 891  
      * @param timeout new validation query timeout value in seconds
 892  
      * @since 1.3
 893  
      */
 894  
     public void setValidationQueryTimeout(int timeout) {
 895  34
         this.validationQueryTimeout = timeout;
 896  34
         restartNeeded = true;
 897  34
     }
 898  
     
 899  
     /**
 900  
      * These SQL statements run once after a Connection is created.
 901  
      * <p>
 902  
      * This property can be used for example to run ALTER SESSION SET
 903  
      * NLS_SORT=XCYECH in an Oracle Database only once after connection
 904  
      * creation.
 905  
      * </p>
 906  
      * 
 907  
      * @since 1.3
 908  
      */
 909  
     protected volatile List connectionInitSqls;
 910  
 
 911  
     /**
 912  
      * Returns the list of SQL statements executed when a physical connection
 913  
      * is first created. Returns an empty list if there are no initialization
 914  
      * statements configured.
 915  
      * 
 916  
      * @return initialization SQL statements
 917  
      * @since 1.3
 918  
      */
 919  
     public Collection getConnectionInitSqls() {
 920  32
         Collection result = connectionInitSqls; 
 921  32
         if (result == null) {
 922  32
             return Collections.EMPTY_LIST;
 923  
         }
 924  0
         return result;
 925  
     }
 926  
 
 927  
     /**
 928  
      * Sets the list of SQL statements to be executed when a physical
 929  
      * connection is first created.
 930  
      * <p>
 931  
      * Note: this method currently has no effect once the pool has been
 932  
      * initialized.  The pool is initialized the first time one of the
 933  
      * following methods is invoked: <code>getConnection, setLogwriter,
 934  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 935  
      * 
 936  
      * @param connectionInitSqls Collection of SQL statements to execute
 937  
      * on connection creation
 938  
      */
 939  
     public void setConnectionInitSqls(Collection connectionInitSqls) {
 940  408
         if ((connectionInitSqls != null) && (connectionInitSqls.size() > 0)) {
 941  400
             ArrayList newVal = null;
 942  400
             for (Iterator iterator = connectionInitSqls.iterator();
 943  1200
             iterator.hasNext();) {
 944  800
                 Object o = iterator.next();
 945  800
                 if (o != null) {
 946  800
                     String s = o.toString();
 947  800
                     if (s.trim().length() > 0) {
 948  784
                         if (newVal == null) {
 949  392
                             newVal = new ArrayList();
 950  
                         }
 951  784
                         newVal.add(s);
 952  
                     }
 953  
                 }
 954  800
             }
 955  400
             this.connectionInitSqls = newVal;
 956  400
         } else {
 957  8
             this.connectionInitSqls = null;
 958  
         }
 959  408
         this.restartNeeded = true;
 960  408
     }
 961  
 
 962  
 
 963  
     /** 
 964  
      * Controls access to the underlying connection.
 965  
      */
 966  398
     private boolean accessToUnderlyingConnectionAllowed = false; 
 967  
 
 968  
     /**
 969  
      * Returns the value of the accessToUnderlyingConnectionAllowed property.
 970  
      * 
 971  
      * @return true if access to the underlying connection is allowed, false
 972  
      * otherwise.
 973  
      */
 974  
     public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
 975  336
         return this.accessToUnderlyingConnectionAllowed;
 976  
     }
 977  
 
 978  
     /**
 979  
      * <p>Sets the value of the accessToUnderlyingConnectionAllowed property.
 980  
      * It controls if the PoolGuard allows access to the underlying connection.
 981  
      * (Default: false)</p>
 982  
      * <p>
 983  
      * Note: this method currently has no effect once the pool has been
 984  
      * initialized.  The pool is initialized the first time one of the
 985  
      * following methods is invoked: <code>getConnection, setLogwriter,
 986  
      * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
 987  
      * 
 988  
      * @param allow Access to the underlying connection is granted when true.
 989  
      */
 990  
     public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
 991  50
         this.accessToUnderlyingConnectionAllowed = allow;
 992  50
         this.restartNeeded = true;
 993  50
     }
 994  
 
 995  
     // ----------------------------------------------------- Instance Variables
 996  
 
 997  
     // TODO: review & make isRestartNeeded() public, restartNeeded protected
 998  
 
 999  
     /**
 1000  
      * A property setter has been invoked that will require the connection
 1001  
      * pool to be re-initialized. Currently, restart is not triggered, so
 1002  
      * this property has no effect.
 1003  
      */
 1004  398
     private volatile boolean restartNeeded = false;
 1005  
     
 1006  
     /**
 1007  
      * Returns whether or not a restart is needed. 
 1008  
      *  
 1009  
      * Note: restart is not currently triggered by property changes.
 1010  
      * 
 1011  
      * @return true if a restart is needed
 1012  
      */
 1013  
     private boolean isRestartNeeded() {
 1014  0
         return restartNeeded;
 1015  
     }
 1016  
 
 1017  
     /**
 1018  
      * The object pool that internally manages our connections.
 1019  
      */
 1020  398
     protected volatile GenericObjectPool connectionPool = null;
 1021  
     
 1022  
     /**
 1023  
      * The connection properties that will be sent to our JDBC driver when
 1024  
      * establishing new connections.  <strong>NOTE</strong> - The "user" and
 1025  
      * "password" properties will be passed explicitly, so they do not need
 1026  
      * to be included here.
 1027  
      */
 1028  398
     protected Properties connectionProperties = new Properties();
 1029  
 
 1030  
     /**
 1031  
      * The data source we will use to manage connections.  This object should
 1032  
      * be acquired <strong>ONLY</strong> by calls to the
 1033  
      * <code>createDataSource()</code> method.
 1034  
      */
 1035  398
     protected volatile DataSource dataSource = null;
 1036  
 
 1037  
     /**
 1038  
      * The PrintWriter to which log messages should be directed.
 1039  
      */
 1040  398
     protected PrintWriter logWriter = new PrintWriter(System.out);
 1041  
 
 1042  
 
 1043  
     // ----------------------------------------------------- DataSource Methods
 1044  
 
 1045  
 
 1046  
     /**
 1047  
      * Create (if necessary) and return a connection to the database.
 1048  
      *
 1049  
      * @throws SQLException if a database access error occurs
 1050  
      * @return a database connection
 1051  
      */
 1052  
     public Connection getConnection() throws SQLException {
 1053  6278
         return createDataSource().getConnection();
 1054  
     }
 1055  
 
 1056  
 
 1057  
     /**
 1058  
      * <strong>BasicDataSource does NOT support this method. </strong>
 1059  
      *
 1060  
      * @param user Database user on whose behalf the Connection
 1061  
      *   is being made
 1062  
      * @param pass The database user's password
 1063  
      *
 1064  
      * @throws UnsupportedOperationException
 1065  
      * @throws SQLException if a database access error occurs
 1066  
      * @return nothing - always throws UnsupportedOperationException
 1067  
      */
 1068  
     public Connection getConnection(String user, String pass) throws SQLException {
 1069  
         // This method isn't supported by the PoolingDataSource returned by
 1070  
         // the createDataSource
 1071  0
         throw new UnsupportedOperationException("Not supported by BasicDataSource");
 1072  
         // return createDataSource().getConnection(username, password);
 1073  
     }
 1074  
 
 1075  
 
 1076  
     /**
 1077  
      * <strong>BasicDataSource does NOT support this method. </strong>
 1078  
      *
 1079  
      * <p>Returns the login timeout (in seconds) for connecting to the database.
 1080  
      * </p>
 1081  
      * <p>Calls {@link #createDataSource()}, so has the side effect
 1082  
      * of initializing the connection pool.</p>
 1083  
      *
 1084  
      * @throws SQLException if a database access error occurs
 1085  
      * @throws UnsupportedOperationException If the DataSource implementation
 1086  
      *   does not support the login timeout feature.
 1087  
      * @return login timeout in seconds
 1088  
      */
 1089  
     public int getLoginTimeout() throws SQLException {
 1090  
         // This method isn't supported by the PoolingDataSource returned by
 1091  
         // the createDataSource
 1092  0
         throw new UnsupportedOperationException("Not supported by BasicDataSource");
 1093  
         //return createDataSource().getLoginTimeout();
 1094  
     }
 1095  
 
 1096  
 
 1097  
     /**
 1098  
      * <p>Returns the log writer being used by this data source.</p>
 1099  
      * <p>
 1100  
      * Calls {@link #createDataSource()}, so has the side effect
 1101  
      * of initializing the connection pool.</p>
 1102  
      *
 1103  
      * @throws SQLException if a database access error occurs
 1104  
      * @return log writer in use
 1105  
      */
 1106  
     public PrintWriter getLogWriter() throws SQLException {
 1107  2
         return createDataSource().getLogWriter();
 1108  
     }
 1109  
 
 1110  
 
 1111  
     /**
 1112  
      * <strong>BasicDataSource does NOT support this method. </strong>
 1113  
      *
 1114  
      * <p>Set the login timeout (in seconds) for connecting to the
 1115  
      * database.</p>
 1116  
      * <p>
 1117  
      * Calls {@link #createDataSource()}, so has the side effect
 1118  
      * of initializing the connection pool.</p>
 1119  
      *
 1120  
      * @param loginTimeout The new login timeout, or zero for no timeout
 1121  
      * @throws UnsupportedOperationException If the DataSource implementation
 1122  
      *   does not support the login timeout feature.
 1123  
      * @throws SQLException if a database access error occurs
 1124  
      */
 1125  
     public void setLoginTimeout(int loginTimeout) throws SQLException {
 1126  
         // This method isn't supported by the PoolingDataSource returned by
 1127  
         // the createDataSource
 1128  0
         throw new UnsupportedOperationException("Not supported by BasicDataSource");
 1129  
         //createDataSource().setLoginTimeout(loginTimeout);
 1130  
     }
 1131  
 
 1132  
 
 1133  
     /**
 1134  
      * <p>Sets the log writer being used by this data source.</p>
 1135  
      * <p>
 1136  
      * Calls {@link #createDataSource()}, so has the side effect
 1137  
      * of initializing the connection pool.</p>
 1138  
      *
 1139  
      * @param logWriter The new log writer
 1140  
      * @throws SQLException if a database access error occurs
 1141  
      */
 1142  
     public void setLogWriter(PrintWriter logWriter) throws SQLException {
 1143  0
         createDataSource().setLogWriter(logWriter);
 1144  0
         this.logWriter = logWriter;
 1145  0
     }
 1146  
 
 1147  
     private AbandonedConfig abandonedConfig;
 1148  
 
 1149  
     /**                       
 1150  
      * Flag to remove abandoned connections if they exceed the
 1151  
      * removeAbandonedTimout.
 1152  
      *
 1153  
      * Set to true or false, default false.
 1154  
      * If set to true a connection is considered abandoned and eligible
 1155  
      * for removal if it has been idle longer than the removeAbandonedTimeout.
 1156  
      * Setting this to true can recover db connections from poorly written    
 1157  
      * applications which fail to close a connection.
 1158  
      * <p>
 1159  
      * Abandonded connections are identified and removed when 
 1160  
      * {@link #getConnection()} is invoked and the following conditions hold
 1161  
      * <ul><li>{@link #getRemoveAbandoned()} = true </li>
 1162  
      *     <li>{@link #getNumActive()} > {@link #getMaxActive()} - 3 </li>
 1163  
      *     <li>{@link #getNumIdle()} < 2 </li></ul></p>
 1164  
      */                                                                   
 1165  
     public boolean getRemoveAbandoned() {   
 1166  2
         if (abandonedConfig != null) {
 1167  2
             return abandonedConfig.getRemoveAbandoned();
 1168  
         }
 1169  0
         return false;
 1170  
     }                                    
 1171  
                                  
 1172  
     /**
 1173  
      * @param removeAbandoned new removeAbandoned property value
 1174  
      * @see #getRemoveAbandoned()
 1175  
      */
 1176  
     public void setRemoveAbandoned(boolean removeAbandoned) {
 1177  102
         if (abandonedConfig == null) {
 1178  2
             abandonedConfig = new AbandonedConfig();
 1179  
         }
 1180  102
         abandonedConfig.setRemoveAbandoned(removeAbandoned);
 1181  102
         this.restartNeeded = true;
 1182  102
     }                                                        
 1183  
                                                
 1184  
     /**
 1185  
      * Timeout in seconds before an abandoned connection can be removed.
 1186  
      *
 1187  
      * Defaults to 300 seconds. 
 1188  
      * @return abandoned connection timeout        
 1189  
      */                                                                 
 1190  
     public int getRemoveAbandonedTimeout() { 
 1191  2
         if (abandonedConfig != null) {
 1192  2
             return abandonedConfig.getRemoveAbandonedTimeout();
 1193  
         }
 1194  0
         return 300;
 1195  
     }                                        
 1196  
 
 1197  
     /**
 1198  
      * @param removeAbandonedTimeout new removeAbandonedTimeout value
 1199  
      */               
 1200  
     public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
 1201  112
         if (abandonedConfig == null) {
 1202  0
             abandonedConfig = new AbandonedConfig();
 1203  
         }
 1204  112
         abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
 1205  112
         this.restartNeeded = true;
 1206  112
     }                                                                  
 1207  
                                                              
 1208  
     /**
 1209  
      * <p>Flag to log stack traces for application code which abandoned
 1210  
      * a Statement or Connection.
 1211  
      * </p>
 1212  
      * <p>Defaults to false.                
 1213  
      * </p>                                                            
 1214  
      * <p>Logging of abandoned Statements and Connections adds overhead
 1215  
      * for every Connection open or new Statement because a stack   
 1216  
      * trace has to be generated. </p>
 1217  
      */                                                          
 1218  
     public boolean getLogAbandoned() {   
 1219  2
         if (abandonedConfig != null) {
 1220  2
             return abandonedConfig.getLogAbandoned();
 1221  
         }
 1222  0
         return false;
 1223  
     }                                 
 1224  
 
 1225  
     /**
 1226  
      * @param logAbandoned new logAbandoned property value
 1227  
      */
 1228  
     public void setLogAbandoned(boolean logAbandoned) {
 1229  102
         if (abandonedConfig == null) {
 1230  100
             abandonedConfig = new AbandonedConfig();
 1231  
         }
 1232  102
         abandonedConfig.setLogAbandoned(logAbandoned);
 1233  102
         this.restartNeeded = true;
 1234  102
     }
 1235  
 
 1236  
     // --------------------------------------------------------- Public Methods
 1237  
 
 1238  
     /**
 1239  
      * Add a custom connection property to the set that will be passed to our
 1240  
      * JDBC driver. This <strong>MUST</strong> be called before the first
 1241  
      * connection is retrieved (along with all the other configuration
 1242  
      * property setters). Calls to this method after the connection pool
 1243  
      * has been initialized have no effect.
 1244  
      *
 1245  
      * @param name Name of the custom connection property
 1246  
      * @param value Value of the custom connection property
 1247  
      */
 1248  
     public void addConnectionProperty(String name, String value) {
 1249  0
         connectionProperties.put(name, value);
 1250  0
         this.restartNeeded = true;
 1251  0
     }
 1252  
 
 1253  
     /**
 1254  
      * Remove a custom connection property.
 1255  
      * 
 1256  
      * @param name Name of the custom connection property to remove
 1257  
      * @see #addConnectionProperty(String, String)
 1258  
      */
 1259  
     public void removeConnectionProperty(String name) {
 1260  0
         connectionProperties.remove(name);
 1261  0
         this.restartNeeded = true;
 1262  0
     }
 1263  
 
 1264  
     /**
 1265  
      * Sets the connection properties passed to driver.connect(...).
 1266  
      *
 1267  
      * Format of the string must be [propertyName=property;]*
 1268  
      *
 1269  
      * NOTE - The "user" and "password" properties will be added
 1270  
      * explicitly, so they do not need to be included here.
 1271  
      *
 1272  
      * @param connectionProperties the connection properties used to
 1273  
      * create new connections
 1274  
      */
 1275  
     public void setConnectionProperties(String connectionProperties) {
 1276  64
         if (connectionProperties == null) throw new NullPointerException("connectionProperties is null");
 1277  
 
 1278  56
         String[] entries = connectionProperties.split(";");
 1279  56
         Properties properties = new Properties();
 1280  152
         for (int i = 0; i < entries.length; i++) {
 1281  96
             String entry = entries[i];
 1282  96
             if (entry.length() > 0) {
 1283  96
                 int index = entry.indexOf('=');
 1284  96
                 if (index > 0) {
 1285  80
                     String name = entry.substring(0, index);
 1286  80
                     String value = entry.substring(index + 1);
 1287  80
                     properties.setProperty(name, value);
 1288  80
                 } else {
 1289  
                     // no value is empty string which is how java.util.Properties works
 1290  16
                     properties.setProperty(entry, "");
 1291  
                 }
 1292  
             }
 1293  
         }
 1294  56
         this.connectionProperties = properties;
 1295  56
         this.restartNeeded = true;
 1296  56
     }
 1297  
 
 1298  
     protected boolean closed;
 1299  
 
 1300  
     /**
 1301  
      * <p>Closes and releases all idle connections that are currently stored in the connection pool
 1302  
      * associated with this data source.</p>
 1303  
      *
 1304  
      * <p>Connections that are checked out to clients when this method is invoked are not affected.  
 1305  
      * When client applications subsequently invoke {@link Connection#close()} to return
 1306  
      * these connections to the pool, the underlying JDBC connections are closed.</p>
 1307  
      * 
 1308  
      * <p>Attempts to acquire connections using {@link #getConnection()} after this method has been
 1309  
      * invoked result in SQLExceptions.<p>
 1310  
      * 
 1311  
      * <p>This method is idempotent - i.e., closing an already closed BasicDataSource has no effect
 1312  
      * and does not generate exceptions.</p>
 1313  
      * 
 1314  
      * @throws SQLException if an error occurs closing idle connections
 1315  
      */
 1316  
     public synchronized void close() throws SQLException {
 1317  408
         closed = true;
 1318  408
         GenericObjectPool oldpool = connectionPool;
 1319  408
         connectionPool = null;
 1320  408
         dataSource = null;
 1321  
         try {
 1322  408
             if (oldpool != null) {
 1323  348
                 oldpool.close();
 1324  
             }
 1325  0
         } catch(SQLException e) {
 1326  0
             throw e;
 1327  0
         } catch(RuntimeException e) {
 1328  0
             throw e;
 1329  0
         } catch(Exception e) {
 1330  0
             throw new SQLNestedException("Cannot close connection pool", e);
 1331  408
         }
 1332  408
     }
 1333  
 
 1334  
     /**
 1335  
      * If true, this data source is closed and no more connections can be retrieved from this datasource.
 1336  
      * @return true, if the data source is closed; false otherwise
 1337  
      */
 1338  
     public synchronized boolean isClosed() {
 1339  0
         return closed;
 1340  
     }
 1341  
 
 1342  
     /* JDBC_4_ANT_KEY_BEGIN */
 1343  
     public boolean isWrapperFor(Class<?> iface) throws SQLException {
 1344  0
         return false;
 1345  
     }
 1346  
 
 1347  
     public <T> T unwrap(Class<T> iface) throws SQLException {
 1348  0
         throw new SQLException("BasicDataSource is not a wrapper.");
 1349  
     }
 1350  
     /* JDBC_4_ANT_KEY_END */
 1351  
 
 1352  
         
 1353  
     // ------------------------------------------------------ Protected Methods
 1354  
 
 1355  
 
 1356  
     /**
 1357  
      * <p>Create (if necessary) and return the internal data source we are
 1358  
      * using to manage our connections.</p>
 1359  
      *
 1360  
      * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the
 1361  
      * "double checked locking" idiom in an attempt to avoid synchronizing
 1362  
      * on every single call to this method.  However, this idiom fails to
 1363  
      * work correctly in the face of some optimizations that are legal for
 1364  
      * a JVM to perform.</p>
 1365  
      *
 1366  
      * @throws SQLException if the object pool cannot be created.
 1367  
      */
 1368  
     protected synchronized DataSource createDataSource()
 1369  
         throws SQLException {
 1370  6280
         if (closed) {
 1371  8
             throw new SQLException("Data source is closed");
 1372  
         }
 1373  
 
 1374  
         // Return the pool if we have already created it
 1375  6272
         if (dataSource != null) {
 1376  5850
             return (dataSource);
 1377  
         }
 1378  
 
 1379  
         // create factory which returns raw physical connections
 1380  422
         ConnectionFactory driverConnectionFactory = createConnectionFactory();
 1381  
 
 1382  
         // create a pool for our connections
 1383  422
         createConnectionPool();
 1384  
 
 1385  
         // Set up statement pool, if desired
 1386  422
         GenericKeyedObjectPoolFactory statementPoolFactory = null;
 1387  422
         if (isPoolPreparedStatements()) {
 1388  92
             statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
 1389  
                         -1, // unlimited maxActive (per key)
 1390  
                         GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
 1391  
                         0, // maxWait
 1392  
                         1, // maxIdle (per key)
 1393  
                         maxOpenPreparedStatements);
 1394  
         }
 1395  
 
 1396  
         // Set up the poolable connection factory
 1397  422
         createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig);
 1398  
 
 1399  
         // Create and return the pooling data source to manage the connections
 1400  318
         createDataSourceInstance();
 1401  
         
 1402  
         try {
 1403  408
             for (int i = 0 ; i < initialSize ; i++) {
 1404  90
                 connectionPool.addObject();
 1405  
             }
 1406  0
         } catch (Exception e) {
 1407  0
             throw new SQLNestedException("Error preloading the connection pool", e);
 1408  318
         }
 1409  
         
 1410  318
         return dataSource;
 1411  
     }
 1412  
 
 1413  
     /**
 1414  
      * Creates a JDBC connection factory for this datasource.  This method only
 1415  
      * exists so subclasses can replace the implementation class.
 1416  
      */
 1417  
     protected ConnectionFactory createConnectionFactory() throws SQLException {
 1418  
         // Load the JDBC driver class
 1419  422
         Class driverFromCCL = null;
 1420  422
         if (driverClassName != null) {
 1421  
             try {
 1422  
                 try {
 1423  422
                     if (driverClassLoader == null) {
 1424  422
                         Class.forName(driverClassName);
 1425  
                     } else {
 1426  0
                         Class.forName(driverClassName, true, driverClassLoader);
 1427  
                     }
 1428  0
                 } catch (ClassNotFoundException cnfe) {
 1429  0
                     driverFromCCL = Thread.currentThread(
 1430  
                             ).getContextClassLoader().loadClass(
 1431  
                                     driverClassName);
 1432  422
                 }
 1433  0
             } catch (Throwable t) {
 1434  0
                 String message = "Cannot load JDBC driver class '" +
 1435  
                     driverClassName + "'";
 1436  0
                 logWriter.println(message);
 1437  0
                 t.printStackTrace(logWriter);
 1438  0
                 throw new SQLNestedException(message, t);
 1439  422
             }
 1440  
         }
 1441  
 
 1442  
         // Create a JDBC driver instance
 1443  422
         Driver driver = null;
 1444  
         try {
 1445  422
             if (driverFromCCL == null) {
 1446  422
                 driver = DriverManager.getDriver(url);
 1447  
             } else {
 1448  
                 // Usage of DriverManager is not possible, as it does not
 1449  
                 // respect the ContextClassLoader
 1450  0
                 driver = (Driver) driverFromCCL.newInstance();
 1451  0
                 if (!driver.acceptsURL(url)) {
 1452  0
                     throw new SQLException("No suitable driver", "08001"); 
 1453  
                 }
 1454  
             }
 1455  0
         } catch (Throwable t) {
 1456  0
             String message = "Cannot create JDBC driver of class '" +
 1457  
                 (driverClassName != null ? driverClassName : "") +
 1458  
                 "' for connect URL '" + url + "'";
 1459  0
             logWriter.println(message);
 1460  0
             t.printStackTrace(logWriter);
 1461  0
             throw new SQLNestedException(message, t);
 1462  422
         }
 1463  
 
 1464  
         // Can't test without a validationQuery
 1465  422
         if (validationQuery == null) {
 1466  10
             setTestOnBorrow(false);
 1467  10
             setTestOnReturn(false);
 1468  10
             setTestWhileIdle(false);
 1469  
         }
 1470  
 
 1471  
         // Set up the driver connection factory we will use
 1472  422
         String user = username;
 1473  422
         if (user != null) {
 1474  422
             connectionProperties.put("user", user);
 1475  
         } else {
 1476  0
             log("DBCP DataSource configured without a 'username'");
 1477  
         }
 1478  
 
 1479  422
         String pwd = password;
 1480  422
         if (pwd != null) {
 1481  422
             connectionProperties.put("password", pwd);
 1482  
         } else {
 1483  0
             log("DBCP DataSource configured without a 'password'");
 1484  
         }
 1485  
 
 1486  422
         ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driver, url, connectionProperties);
 1487  422
         return driverConnectionFactory;
 1488  
     }
 1489  
 
 1490  
     /**
 1491  
      * Creates a connection pool for this datasource.  This method only exists
 1492  
      * so subclasses can replace the implementation class.
 1493  
      */
 1494  
     protected void createConnectionPool() {
 1495  
         // Create an object pool to contain our active connections
 1496  
         GenericObjectPool gop;
 1497  422
         if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned())) {
 1498  92
             gop = new AbandonedObjectPool(null,abandonedConfig);
 1499  
         }
 1500  
         else {
 1501  330
             gop = new GenericObjectPool();
 1502  
         }
 1503  422
         gop.setMaxActive(maxActive);
 1504  422
         gop.setMaxIdle(maxIdle);
 1505  422
         gop.setMinIdle(minIdle);
 1506  422
         gop.setMaxWait(maxWait);
 1507  422
         gop.setTestOnBorrow(testOnBorrow);
 1508  422
         gop.setTestOnReturn(testOnReturn);
 1509  422
         gop.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
 1510  422
         gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
 1511  422
         gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
 1512  422
         gop.setTestWhileIdle(testWhileIdle);
 1513  422
         connectionPool = gop;
 1514  422
     }
 1515  
 
 1516  
     /**
 1517  
      * Creates the actual data source instance.  This method only exists so
 1518  
      * subclasses can replace the implementation class.
 1519  
      * 
 1520  
      * @throws SQLException if unable to create a datasource instance
 1521  
      */
 1522  
     protected void createDataSourceInstance() throws SQLException {
 1523  244
         PoolingDataSource pds = new PoolingDataSource(connectionPool);
 1524  244
         pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
 1525  244
         pds.setLogWriter(logWriter);
 1526  244
         dataSource = pds;
 1527  244
     }
 1528  
 
 1529  
     /**
 1530  
      * Creates the PoolableConnectionFactory and attaches it to the connection pool.  This method only exists
 1531  
      * so subclasses can replace the default implementation.
 1532  
      * 
 1533  
      * @param driverConnectionFactory JDBC connection factory
 1534  
      * @param statementPoolFactory statement pool factory (null if statement pooling is turned off)
 1535  
      * @param configuration abandoned connection tracking configuration (null if no tracking)
 1536  
      * @throws SQLException if an error occurs creating the PoolableConnectionFactory
 1537  
      */
 1538  
     protected void createPoolableConnectionFactory(ConnectionFactory driverConnectionFactory,
 1539  
             KeyedObjectPoolFactory statementPoolFactory, AbandonedConfig configuration) throws SQLException {
 1540  322
         PoolableConnectionFactory connectionFactory = null;
 1541  
         try {
 1542  322
             connectionFactory =
 1543  
                 new PoolableConnectionFactory(driverConnectionFactory,
 1544  
                                               connectionPool,
 1545  
                                               statementPoolFactory,
 1546  
                                               validationQuery,
 1547  
                                               validationQueryTimeout,
 1548  
                                               connectionInitSqls,
 1549  
                                               defaultReadOnly,
 1550  
                                               defaultAutoCommit,
 1551  
                                               defaultTransactionIsolation,
 1552  
                                               defaultCatalog,
 1553  
                                               configuration);
 1554  322
             validateConnectionFactory(connectionFactory);
 1555  0
         } catch (RuntimeException e) {
 1556  0
             throw e;
 1557  78
         } catch (Exception e) {
 1558  78
             throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
 1559  244
         }
 1560  244
     }
 1561  
 
 1562  
     protected static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception {
 1563  422
         Connection conn = null;
 1564  
         try {
 1565  422
             conn = (Connection) connectionFactory.makeObject();
 1566  334
             connectionFactory.activateObject(conn);
 1567  334
             connectionFactory.validateConnection(conn);
 1568  318
             connectionFactory.passivateObject(conn);
 1569  
         }
 1570  
         finally {
 1571  422
             connectionFactory.destroyObject(conn);
 1572  318
         }
 1573  318
     }
 1574  
 
 1575  
     /**
 1576  
      * Not used currently
 1577  
      */
 1578  
     private void restart() {
 1579  
         try {
 1580  0
             close();
 1581  0
         } catch (SQLException e) {
 1582  0
             log("Could not restart DataSource, cause: " + e.getMessage());
 1583  0
         }
 1584  0
     }
 1585  
 
 1586  
     protected void log(String message) {
 1587  0
         if (logWriter != null) {
 1588  0
             logWriter.println(message);
 1589  
         }
 1590  0
     }
 1591  
 }