Home » commons-dbcp-1.2.2-src » org.apache.commons » dbcp » [javadoc | source]
    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.sql.Connection;
   23   import java.sql.Driver;
   24   import java.sql.DriverManager;
   25   import java.sql.SQLException;
   26   import javax.sql.DataSource;
   27   
   28   import org.apache.commons.pool.impl.GenericKeyedObjectPool;
   29   import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
   30   import org.apache.commons.pool.impl.GenericObjectPool;
   31   
   32   
   33   /**
   34    * <p>Basic implementation of <code>javax.sql.DataSource</code> that is
   35    * configured via JavaBeans properties.  This is not the only way to
   36    * combine the <em>commons-dbcp</em> and <em>commons-pool</em> packages,
   37    * but provides a "one stop shopping" solution for basic requirements.</p>
   38    *
   39    * @author Glenn L. Nielsen
   40    * @author Craig R. McClanahan
   41    * @author Dirk Verbeeck
   42    * @version $Revision: 506087 $ $Date: 2007-02-11 11:37:43 -0700 (Sun, 11 Feb 2007) $
   43    */
   44   public class BasicDataSource implements DataSource {
   45   
   46       // ------------------------------------------------------------- Properties
   47   
   48       /**
   49        * The default auto-commit state of connections created by this pool.
   50        */
   51       protected boolean defaultAutoCommit = true;
   52   
   53       /**
   54        * Returns the default auto-commit property.
   55        * 
   56        * @return true if default auto-commit is enabled
   57        */
   58       public synchronized boolean getDefaultAutoCommit() {
   59           return this.defaultAutoCommit;
   60       }
   61   
   62       /**
   63        * <p>Sets default auto-commit state of connections returned by this
   64        * datasource.</p>
   65        * <p>
   66        * Note: this method currently has no effect once the pool has been
   67        * initialized.  The pool is initialized the first time one of the
   68        * following methods is invoked: <code>getConnection, setLogwriter,
   69        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
   70        * 
   71        * @param defaultAutoCommit default auto-commit value
   72        */
   73       public synchronized void setDefaultAutoCommit(boolean defaultAutoCommit) {
   74           this.defaultAutoCommit = defaultAutoCommit;
   75           this.restartNeeded = true;
   76       }
   77   
   78   
   79       /**
   80        * The default read-only state of connections created by this pool.
   81        */
   82       protected Boolean defaultReadOnly = null;
   83   
   84       /**
   85        * Returns the default readOnly property.
   86        * 
   87        * @return true if connections are readOnly by default
   88        */
   89       public synchronized boolean getDefaultReadOnly() {
   90           if (this.defaultReadOnly != null) {
   91               return this.defaultReadOnly.booleanValue();
   92           }
   93           return false;
   94       }
   95   
   96       /**
   97        * <p>Sets defaultReadonly property.</p>
   98        * <p>
   99        * Note: this method currently has no effect once the pool has been
  100        * initialized.  The pool is initialized the first time one of the
  101        * following methods is invoked: <code>getConnection, setLogwriter,
  102        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  103        * 
  104        * @param defaultReadOnly default read-only value
  105        */
  106       public synchronized void setDefaultReadOnly(boolean defaultReadOnly) {
  107           this.defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
  108           this.restartNeeded = true;
  109       }
  110   
  111       /**
  112        * The default TransactionIsolation state of connections created by this pool.
  113        */
  114       protected int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION;
  115   
  116       /**
  117        * Returns the default transaction isolation state of returned connections.
  118        * 
  119        * @return the default value for transaction isolation state
  120        * @see Connection#getTransactionIsolation
  121        */
  122       public synchronized int getDefaultTransactionIsolation() {
  123           return this.defaultTransactionIsolation;
  124       }
  125   
  126       /**
  127        * <p>Sets the default transaction isolation state for returned
  128        * connections.</p>
  129        * <p>
  130        * Note: this method currently has no effect once the pool has been
  131        * initialized.  The pool is initialized the first time one of the
  132        * following methods is invoked: <code>getConnection, setLogwriter,
  133        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  134        * 
  135        * @param defaultTransactionIsolation the default transaction isolation
  136        * state
  137        * @see Connection#getTransactionIsolation
  138        */
  139       public synchronized void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
  140           this.defaultTransactionIsolation = defaultTransactionIsolation;
  141           this.restartNeeded = true;
  142       }
  143   
  144   
  145       /**
  146        * The default "catalog" of connections created by this pool.
  147        */
  148       protected String defaultCatalog = null;
  149   
  150       /**
  151        * Returns the default catalog.
  152        * 
  153        * @return the default catalog
  154        */
  155       public synchronized String getDefaultCatalog() {
  156           return this.defaultCatalog;
  157       }
  158   
  159       /**
  160        * <p>Sets the default catalog.</p>
  161        * <p>
  162        * Note: this method currently has no effect once the pool has been
  163        * initialized.  The pool is initialized the first time one of the
  164        * following methods is invoked: <code>getConnection, setLogwriter,
  165        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  166        * 
  167        * @param defaultCatalog the default catalog
  168        */
  169       public synchronized void setDefaultCatalog(String defaultCatalog) {
  170           if ((defaultCatalog != null) && (defaultCatalog.trim().length() > 0)) {
  171               this.defaultCatalog = defaultCatalog;
  172           }
  173           else {
  174               this.defaultCatalog = null;
  175           }
  176           this.restartNeeded = true;
  177       }
  178   
  179     
  180       /**
  181        * The fully qualified Java class name of the JDBC driver to be used.
  182        */
  183       protected String driverClassName = null;
  184   
  185       /**
  186        * Returns the jdbc driver class name.
  187        * 
  188        * @return the jdbc driver class name
  189        */
  190       public synchronized String getDriverClassName() {
  191           return this.driverClassName;
  192       }
  193   
  194       /**
  195        * <p>Sets the jdbc driver class name.</p>
  196        * <p>
  197        * Note: this method currently has no effect once the pool has been
  198        * initialized.  The pool is initialized the first time one of the
  199        * following methods is invoked: <code>getConnection, setLogwriter,
  200        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  201        * 
  202        * @param driverClassName the class name of the jdbc driver
  203        */
  204       public synchronized void setDriverClassName(String driverClassName) {
  205           if ((driverClassName != null) && (driverClassName.trim().length() > 0)) {
  206               this.driverClassName = driverClassName;
  207           }
  208           else {
  209               this.driverClassName = null;
  210           }
  211           this.restartNeeded = true;
  212       }
  213   
  214   
  215       /**
  216        * The maximum number of active connections that can be allocated from
  217        * this pool at the same time, or non-positive for no limit.
  218        */
  219       protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
  220   
  221       /**
  222        * <p>Returns the maximum number of active connections that can be
  223        * allocated at the same time.
  224        * </p>
  225        * <p>A non-positive number means that there is no limit.</p>
  226        * 
  227        * @return the maximum number of active connections
  228        */
  229       public synchronized int getMaxActive() {
  230           return this.maxActive;
  231       }
  232   
  233       /**
  234        * Sets the maximum number of active connections that can be
  235        * allocated at the same time.
  236        * 
  237        * @param maxActive the new value for maxActive
  238        * @see #getMaxActive()
  239        */
  240       public synchronized void setMaxActive(int maxActive) {
  241           this.maxActive = maxActive;
  242           if (connectionPool != null) {
  243               connectionPool.setMaxActive(maxActive);
  244           }
  245       }
  246   
  247       /**
  248        * The maximum number of connections that can remain idle in the
  249        * pool, without extra ones being released, or negative for no limit.
  250        */
  251       protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
  252   
  253       /**
  254        * <p>Returns the maximum number of connections that can remain idle in the
  255        * pool.
  256        * </p>
  257        * <p>A negative value indicates that there is no limit</p>
  258        * 
  259        * @return the maximum number of idle connections
  260        */
  261       public synchronized int getMaxIdle() {
  262           return this.maxIdle;
  263       }
  264   
  265       /**
  266        * Sets the maximum number of connections that can remail idle in the
  267        * pool.
  268        * 
  269        * @see #getMaxIdle()
  270        * @param maxIdle the new value for maxIdle
  271        */
  272       public synchronized void setMaxIdle(int maxIdle) {
  273           this.maxIdle = maxIdle;
  274           if (connectionPool != null) {
  275               connectionPool.setMaxIdle(maxIdle);
  276           }
  277       }
  278   
  279       /**
  280        * The minimum number of active connections that can remain idle in the
  281        * pool, without extra ones being created, or 0 to create none.
  282        */
  283       protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
  284   
  285       /**
  286        * Returns the minimum number of idle connections in the pool
  287        * 
  288        * @return the minimum number of idle connections
  289        * @see GenericObjectPool#getMinIdle()
  290        */
  291       public synchronized int getMinIdle() {
  292           return this.minIdle;
  293       }
  294   
  295       /**
  296        * Sets the minimum number of idle connections in the pool.
  297        * 
  298        * @param minIdle the new value for minIdle
  299        * @see GenericObjectPool#setMinIdle(int)
  300        */
  301       public synchronized void setMinIdle(int minIdle) {
  302          this.minIdle = minIdle;
  303          if (connectionPool != null) {
  304              connectionPool.setMinIdle(minIdle);
  305          }
  306       }
  307   
  308       /**
  309        * The initial number of connections that are created when the pool
  310        * is started.
  311        * 
  312        * @since 1.2
  313        */
  314       protected int initialSize = 0;
  315       
  316       /**
  317        * Returns the initial size of the connection pool.
  318        * 
  319        * @return the number of connections created when the pool is initialized
  320        */
  321       public synchronized int getInitialSize() {
  322           return this.initialSize;
  323       }
  324       
  325       /**
  326        * <p>Sets the initial size of the connection pool.</p>
  327        * <p>
  328        * Note: this method currently has no effect once the pool has been
  329        * initialized.  The pool is initialized the first time one of the
  330        * following methods is invoked: <code>getConnection, setLogwriter,
  331        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  332        * 
  333        * @param initialSize the number of connections created when the pool
  334        * is initialized
  335        */
  336       public synchronized void setInitialSize(int initialSize) {
  337           this.initialSize = initialSize;
  338           this.restartNeeded = true;
  339       }
  340   
  341       /**
  342        * The maximum number of milliseconds that the pool will wait (when there
  343        * are no available connections) for a connection to be returned before
  344        * throwing an exception, or -1 to wait indefinitely.
  345        */
  346       protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
  347   
  348       /**
  349        * <p>Returns the maximum number of milliseconds that the pool will wait
  350        * for a connection to be returned before throwing an exception.
  351        * </p>
  352        * <p>Returns -1 if the pool is set to wait indefinitely.</p>
  353        * 
  354        * @return the maxWait property value
  355        */
  356       public synchronized long getMaxWait() {
  357           return this.maxWait;
  358       }
  359   
  360       /**
  361        * Sets the maxWait property.
  362        * 
  363        * @param maxWait the new value for maxWait
  364        * @see #getMaxWait()
  365        */
  366       public synchronized void setMaxWait(long maxWait) {
  367           this.maxWait = maxWait;
  368           if (connectionPool != null) {
  369               connectionPool.setMaxWait(maxWait);
  370           }
  371       }
  372   
  373       /**
  374        * Prepared statement pooling for this pool.
  375        */
  376       protected boolean poolPreparedStatements = false;
  377       
  378       /**
  379        * Returns true if we are pooling statements.
  380        * 
  381        * @return true if prepared statements are pooled
  382        */
  383       public synchronized boolean isPoolPreparedStatements() {
  384           return this.poolPreparedStatements;
  385       }
  386   
  387       /**
  388        * <p>Sets whether to pool statements or not.</p>
  389        * <p>
  390        * Note: this method currently has no effect once the pool has been
  391        * initialized.  The pool is initialized the first time one of the
  392        * following methods is invoked: <code>getConnection, setLogwriter,
  393        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  394        * 
  395        * @param poolingStatements pooling on or off
  396        */
  397       public synchronized void setPoolPreparedStatements(boolean poolingStatements) {
  398           this.poolPreparedStatements = poolingStatements;
  399           this.restartNeeded = true;
  400       }
  401   
  402       /**
  403        * The maximum number of open statements that can be allocated from
  404        * the statement pool at the same time, or non-positive for no limit.  Since 
  405        * a connection usually only uses one or two statements at a time, this is
  406        * mostly used to help detect resource leaks.
  407        */
  408       protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
  409   
  410       /**
  411        * Gets the value of the {@link #maxOpenPreparedStatements} property.
  412        * 
  413        * @return the maximum number of open statements
  414        * @see #maxOpenPreparedStatements
  415        */
  416       public synchronized int getMaxOpenPreparedStatements() {
  417           return this.maxOpenPreparedStatements;
  418       }
  419   
  420       /** 
  421        * <p>Sets the value of the {@link #maxOpenPreparedStatements}
  422        * property.</p>
  423        * <p>
  424        * Note: this method currently has no effect once the pool has been
  425        * initialized.  The pool is initialized the first time one of the
  426        * following methods is invoked: <code>getConnection, setLogwriter,
  427        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  428        * 
  429        * @param maxOpenStatements the new maximum number of prepared statements
  430        * @see #maxOpenPreparedStatements
  431        */
  432       public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) {
  433           this.maxOpenPreparedStatements = maxOpenStatements;
  434           this.restartNeeded = true;
  435       }
  436   
  437       /**
  438        * The indication of whether objects will be validated before being
  439        * borrowed from the pool.  If the object fails to validate, it will be
  440        * dropped from the pool, and we will attempt to borrow another.
  441        */
  442       protected boolean testOnBorrow = true;
  443   
  444       /**
  445        * Returns the {@link #testOnBorrow} property.
  446        * 
  447        * @return true if objects are validated before being borrowed from the
  448        * pool
  449        * 
  450        * @see #testOnBorrow
  451        */
  452       public synchronized boolean getTestOnBorrow() {
  453           return this.testOnBorrow;
  454       }
  455   
  456       /**
  457        * Sets the {@link #testOnBorrow} property. This property determines
  458        * whether or not the pool will validate objects before they are borrowed
  459        * from the pool. For a <code>true</code> value to have any effect, the 
  460        * <code>validationQuery</code> property must be set to a non-null string.
  461        * 
  462        * @param testOnBorrow new value for testOnBorrow property
  463        */
  464       public synchronized void setTestOnBorrow(boolean testOnBorrow) {
  465           this.testOnBorrow = testOnBorrow;
  466           if (connectionPool != null) {
  467               connectionPool.setTestOnBorrow(testOnBorrow);
  468           }
  469       }
  470   
  471       /**
  472        * The indication of whether objects will be validated before being
  473        * returned to the pool.
  474        */
  475       protected boolean testOnReturn = false;
  476   
  477       /**
  478        * Returns the value of the {@link #testOnReturn} property.
  479        * 
  480        * @return true if objects are validated before being returned to the
  481        * pool
  482        * @see #testOnReturn
  483        */
  484       public synchronized boolean getTestOnReturn() {
  485           return this.testOnReturn;
  486       }
  487   
  488       /**
  489        * Sets the <code>testOnReturn</code> property. This property determines
  490        * whether or not the pool will validate objects before they are returned
  491        * to the pool. For a <code>true</code> value to have any effect, the 
  492        * <code>validationQuery</code> property must be set to a non-null string.
  493        * 
  494        * @param testOnReturn new value for testOnReturn property
  495        */
  496       public synchronized void setTestOnReturn(boolean testOnReturn) {
  497           this.testOnReturn = testOnReturn;
  498           if (connectionPool != null) {
  499               connectionPool.setTestOnReturn(testOnReturn);
  500           }
  501       }
  502   
  503       /**
  504        * The number of milliseconds to sleep between runs of the idle object
  505        * evictor thread.  When non-positive, no idle object evictor thread will
  506        * be run.
  507        */
  508       protected long timeBetweenEvictionRunsMillis =
  509           GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
  510           
  511       /**
  512        * Returns the value of the {@link #timeBetweenEvictionRunsMillis}
  513        * property.
  514        * 
  515        * @return the time (in miliseconds) between evictor runs
  516        * @see #timeBetweenEvictionRunsMillis
  517        */
  518       public synchronized long getTimeBetweenEvictionRunsMillis() {
  519           return this.timeBetweenEvictionRunsMillis;
  520       }
  521   
  522       /**
  523        * Sets the {@link #timeBetweenEvictionRunsMillis} property.
  524        * 
  525        * @param timeBetweenEvictionRunsMillis the new time between evictor runs
  526        * @see #timeBetweenEvictionRunsMillis
  527        */
  528       public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
  529           this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
  530           if (connectionPool != null) {
  531               connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
  532           }
  533       }
  534   
  535       /**
  536        * The number of objects to examine during each run of the idle object
  537        * evictor thread (if any).
  538        */
  539       protected int numTestsPerEvictionRun =
  540           GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
  541   
  542       /**
  543        * Returns the value of the {@link #numTestsPerEvictionRun} property.
  544        * 
  545        * @return the number of objects to examine during idle object evictor
  546        * runs
  547        * @see #numTestsPerEvictionRun
  548        */
  549       public synchronized int getNumTestsPerEvictionRun() {
  550           return this.numTestsPerEvictionRun;
  551       }
  552   
  553       /**
  554        * Sets the value of the {@link #numTestsPerEvictionRun} property.
  555        * 
  556        * @param numTestsPerEvictionRun the new {@link #numTestsPerEvictionRun} 
  557        * value
  558        * @see #numTestsPerEvictionRun
  559        */
  560       public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
  561           this.numTestsPerEvictionRun = numTestsPerEvictionRun;
  562           if (connectionPool != null) {
  563               connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
  564           }
  565       }
  566   
  567       /**
  568        * The minimum amount of time an object may sit idle in the pool before it
  569        * is eligable for eviction by the idle object evictor (if any).
  570        */
  571       protected long minEvictableIdleTimeMillis =
  572           GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
  573   
  574       /**
  575        * Returns the {@link #minEvictableIdleTimeMillis} property.
  576        * 
  577        * @return the value of the {@link #minEvictableIdleTimeMillis} property
  578        * @see #minEvictableIdleTimeMillis
  579        */
  580       public synchronized long getMinEvictableIdleTimeMillis() {
  581           return this.minEvictableIdleTimeMillis;
  582       }
  583   
  584       /**
  585        * Sets the {@link #minEvictableIdleTimeMillis} property.
  586        * 
  587        * @param minEvictableIdleTimeMillis the minimum amount of time an object
  588        * may sit idle in the pool 
  589        * @see #minEvictableIdleTimeMillis
  590        */
  591       public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
  592           this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
  593           if (connectionPool != null) {
  594               connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
  595           }
  596       }
  597   
  598       /**
  599        * The indication of whether objects will be validated by the idle object
  600        * evictor (if any).  If an object fails to validate, it will be dropped
  601        * from the pool.
  602        */
  603       protected boolean testWhileIdle = false;
  604   
  605       /**
  606        * Returns the value of the {@link #testWhileIdle} property.
  607        * 
  608        * @return true if objects examined by the idle object evictor are
  609        * validated
  610        * @see #testWhileIdle
  611        */
  612       public synchronized boolean getTestWhileIdle() {
  613           return this.testWhileIdle;
  614       }
  615   
  616       /**
  617        * Sets the <code>testWhileIdle</code> property. This property determines
  618        * whether or not the idle object evictor will validate connections.  For a
  619        * <code>true</code> value to have any effect, the 
  620        * <code>validationQuery</code> property must be set to a non-null string.
  621        * 
  622        * @param testWhileIdle new value for testWhileIdle property
  623        */
  624       public synchronized void setTestWhileIdle(boolean testWhileIdle) {
  625           this.testWhileIdle = testWhileIdle;
  626           if (connectionPool != null) {
  627               connectionPool.setTestWhileIdle(testWhileIdle);
  628           }
  629       }
  630   
  631       /**
  632        * [Read Only] The current number of active connections that have been
  633        * allocated from this data source.
  634        * 
  635        * @return the current number of active connections
  636        */
  637       public synchronized int getNumActive() {
  638           if (connectionPool != null) {
  639               return connectionPool.getNumActive();
  640           } else {
  641               return 0;
  642           }
  643       }
  644   
  645   
  646       /**
  647        * [Read Only] The current number of idle connections that are waiting
  648        * to be allocated from this data source.
  649        * 
  650        * @return the current number of idle connections
  651        */
  652       public synchronized int getNumIdle() {
  653           if (connectionPool != null) {
  654               return connectionPool.getNumIdle();
  655           } else {
  656               return 0;
  657           }
  658       }
  659   
  660       /**
  661        * The connection password to be passed to our JDBC driver to establish
  662        * a connection.
  663        */
  664       protected String password = null;
  665   
  666       /**
  667        * Returns the password passed to the JDBC driver to establish connections.
  668        * 
  669        * @return the connection password
  670        */
  671       public synchronized String getPassword() {
  672           return this.password;
  673       }
  674   
  675       /** 
  676        * <p>Sets the {@link #password}.</p>
  677        * <p>
  678        * Note: this method currently has no effect once the pool has been
  679        * initialized.  The pool is initialized the first time one of the
  680        * following methods is invoked: <code>getConnection, setLogwriter,
  681        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  682        * 
  683        * @param password new value for the password
  684        */
  685       public synchronized void setPassword(String password) {
  686           this.password = password;
  687           this.restartNeeded = true;
  688       }
  689   
  690       /**
  691        * The connection URL to be passed to our JDBC driver to establish
  692        * a connection.
  693        */
  694       protected String url = null;
  695   
  696       /**
  697        * Returns the JDBC connection {@link #url} property.
  698        * 
  699        * @return the {@link #url} passed to the JDBC driver to establish
  700        * connections
  701        */
  702       public synchronized String getUrl() {
  703           return this.url;
  704       }
  705   
  706       /** 
  707        * <p>Sets the {@link #url}.</p>
  708        * <p>
  709        * Note: this method currently has no effect once the pool has been
  710        * initialized.  The pool is initialized the first time one of the
  711        * following methods is invoked: <code>getConnection, setLogwriter,
  712        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  713        * 
  714        * @param url the new value for the JDBC connection url
  715        */
  716       public synchronized void setUrl(String url) {
  717           this.url = url;
  718           this.restartNeeded = true;
  719       }
  720   
  721       /**
  722        * The connection username to be passed to our JDBC driver to
  723        * establish a connection.
  724        */
  725       protected String username = null;
  726   
  727       /**
  728        * Returns the JDBC connection {@link #username} property.
  729        * 
  730        * @return the {@link #username} passed to the JDBC driver to establish
  731        * connections
  732        */
  733       public synchronized String getUsername() {
  734           return this.username;
  735       }
  736   
  737       /** 
  738        * <p>Sets the {@link #username}.</p>
  739        * <p>
  740        * Note: this method currently has no effect once the pool has been
  741        * initialized.  The pool is initialized the first time one of the
  742        * following methods is invoked: <code>getConnection, setLogwriter,
  743        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  744        * 
  745        * @param username the new value for the JDBC connection username
  746        */
  747       public synchronized void setUsername(String username) {
  748           this.username = username;
  749           this.restartNeeded = true;
  750       }
  751   
  752       /**
  753        * The SQL query that will be used to validate connections from this pool
  754        * before returning them to the caller.  If specified, this query
  755        * <strong>MUST</strong> be an SQL SELECT statement that returns at least
  756        * one row.
  757        */
  758       protected String validationQuery = null;
  759   
  760       /**
  761        * Returns the validation query used to validate connections before
  762        * returning them.
  763        * 
  764        * @return the SQL validation query
  765        * @see #validationQuery
  766        */
  767       public synchronized String getValidationQuery() {
  768           return this.validationQuery;
  769       }
  770   
  771       /** 
  772        * <p>Sets the {@link #validationQuery}.</p>
  773        * <p>
  774        * Note: this method currently has no effect once the pool has been
  775        * initialized.  The pool is initialized the first time one of the
  776        * following methods is invoked: <code>getConnection, setLogwriter,
  777        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  778        * 
  779        * @param validationQuery the new value for the validation query
  780        */
  781       public synchronized void setValidationQuery(String validationQuery) {
  782           if ((validationQuery != null) && (validationQuery.trim().length() > 0)) {
  783               this.validationQuery = validationQuery;
  784           } else {
  785               this.validationQuery = null;
  786           }
  787           this.restartNeeded = true;
  788       }
  789   
  790       /** 
  791        * Controls access to the underlying connection.
  792        */
  793       private boolean accessToUnderlyingConnectionAllowed = false; 
  794   
  795       /**
  796        * Returns the value of the accessToUnderlyingConnectionAllowed property.
  797        * 
  798        * @return true if access to the underlying connection is allowed, false
  799        * otherwise.
  800        */
  801       public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
  802           return this.accessToUnderlyingConnectionAllowed;
  803       }
  804   
  805       /**
  806        * <p>Sets the value of the accessToUnderlyingConnectionAllowed property.
  807        * It controls if the PoolGuard allows access to the underlying connection.
  808        * (Default: false)</p>
  809        * <p>
  810        * Note: this method currently has no effect once the pool has been
  811        * initialized.  The pool is initialized the first time one of the
  812        * following methods is invoked: <code>getConnection, setLogwriter,
  813        * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p>
  814        * 
  815        * @param allow Access to the underlying connection is granted when true.
  816        */
  817       public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
  818           this.accessToUnderlyingConnectionAllowed = allow;
  819           this.restartNeeded = true;
  820       }
  821   
  822       // ----------------------------------------------------- Instance Variables
  823   
  824       // TODO: review & make isRestartNeeded() public, restartNeeded protected
  825   
  826       /**
  827        * A property setter has been invoked that will require the connection
  828        * pool to be re-initialized. Currently, restart is not triggered, so
  829        * this property has no effect.
  830        */
  831       private boolean restartNeeded = false;
  832       
  833       /**
  834        * Returns whether or not a restart is needed. 
  835        *  
  836        * Note: restart is not currently triggered by property changes.
  837        * 
  838        * @return true if a restart is needed
  839        */
  840       private synchronized boolean isRestartNeeded() {
  841           return restartNeeded;
  842       }
  843   
  844       /**
  845        * The object pool that internally manages our connections.
  846        */
  847       protected GenericObjectPool connectionPool = null;
  848       
  849       /**
  850        * The connection properties that will be sent to our JDBC driver when
  851        * establishing new connections.  <strong>NOTE</strong> - The "user" and
  852        * "password" properties will be passed explicitly, so they do not need
  853        * to be included here.
  854        */
  855       protected Properties connectionProperties = new Properties();
  856   
  857       /**
  858        * The data source we will use to manage connections.  This object should
  859        * be acquired <strong>ONLY</strong> by calls to the
  860        * <code>createDataSource()</code> method.
  861        */
  862       protected DataSource dataSource = null;
  863   
  864       /**
  865        * The PrintWriter to which log messages should be directed.
  866        */
  867       protected PrintWriter logWriter = new PrintWriter(System.out);
  868   
  869   
  870       // ----------------------------------------------------- DataSource Methods
  871   
  872   
  873       /**
  874        * Create (if necessary) and return a connection to the database.
  875        *
  876        * @throws SQLException if a database access error occurs
  877        * @return a database connection
  878        */
  879       public Connection getConnection() throws SQLException {
  880           return createDataSource().getConnection();
  881       }
  882   
  883   
  884       /**
  885        * <strong>BasicDataSource does NOT support this method.
  886        * </strong>
  887        *
  888        * @param username Database user on whose behalf the Connection
  889        *   is being made
  890        * @param password The database user's password
  891        *
  892        * @throws UnsupportedOperationException
  893        * @throws SQLException if a database access error occurs
  894        * @return nothing - always throws UnsupportedOperationException
  895        */
  896       public Connection getConnection(String username, String password) throws SQLException {
  897           // This method isn't supported by the PoolingDataSource returned by
  898           // the createDataSource
  899           throw new UnsupportedOperationException("Not supported by BasicDataSource");
  900           // return createDataSource().getConnection(username, password);
  901       }
  902   
  903   
  904       /**
  905        * <p>Returns the login timeout (in seconds) for connecting to the database.
  906        * </p>
  907        * <p>Calls {@link #createDataSource()}, so has the side effect
  908        * of initializing the connection pool.</p>
  909        *
  910        * @throws SQLException if a database access error occurs
  911        * @throws UnsupportedOperationException If the DataSource implementation
  912        *   does not support the login timeout feature.
  913        * @return login timeout in seconds
  914        */
  915       public int getLoginTimeout() throws SQLException {
  916           return createDataSource().getLoginTimeout();
  917       }
  918   
  919   
  920       /**
  921        * <p>Returns the log writer being used by this data source.</p>
  922        * <p>
  923        * Calls {@link #createDataSource()}, so has the side effect
  924        * of initializing the connection pool.</p>
  925        *
  926        * @throws SQLException if a database access error occurs
  927        * @return log writer in use
  928        */
  929       public PrintWriter getLogWriter() throws SQLException {
  930           return createDataSource().getLogWriter();
  931       }
  932   
  933   
  934       /**
  935        * <p>Set the login timeout (in seconds) for connecting to the
  936        * database.</p>
  937        * <p>
  938        * Calls {@link #createDataSource()}, so has the side effect
  939        * of initializing the connection pool.</p>
  940        *
  941        * @param loginTimeout The new login timeout, or zero for no timeout
  942        * @throws SQLException if a database access error occurs
  943        */
  944       public void setLoginTimeout(int loginTimeout) throws SQLException {
  945           createDataSource().setLoginTimeout(loginTimeout);
  946       }
  947   
  948   
  949       /**
  950        * <p>Sets the log writer being used by this data source.</p>
  951        * <p>
  952        * Calls {@link #createDataSource()}, so has the side effect
  953        * of initializing the connection pool.</p>
  954        *
  955        * @param logWriter The new log writer
  956        * @throws SQLException if a database access error occurs
  957        */
  958       public void setLogWriter(PrintWriter logWriter) throws SQLException {
  959           createDataSource().setLogWriter(logWriter);
  960           this.logWriter = logWriter;
  961       }
  962   
  963       private AbandonedConfig abandonedConfig;
  964   
  965       /**                       
  966        * Flag to remove abandoned connections if they exceed the
  967        * removeAbandonedTimout.
  968        *
  969        * Set to true or false, default false.
  970        * If set to true a connection is considered abandoned and eligible
  971        * for removal if it has been idle longer than the removeAbandonedTimeout.
  972        * Setting this to true can recover db connections from poorly written    
  973        * applications which fail to close a connection.      
  974        * @deprecated                   
  975        */                                                                   
  976       public boolean getRemoveAbandoned() {   
  977           if (abandonedConfig != null) {
  978               return abandonedConfig.getRemoveAbandoned();
  979           }
  980           return false;
  981       }                                    
  982                                    
  983       /**
  984        * @deprecated
  985        * @param removeAbandoned new removeAbandoned property value
  986        */
  987       public void setRemoveAbandoned(boolean removeAbandoned) {
  988           if (abandonedConfig == null) {
  989               abandonedConfig = new AbandonedConfig();
  990           }
  991           abandonedConfig.setRemoveAbandoned(removeAbandoned);
  992           this.restartNeeded = true;
  993       }                                                        
  994                                                  
  995       /**
  996        * Timeout in seconds before an abandoned connection can be removed.
  997        *
  998        * Defaults to 300 seconds. 
  999        * @return abandoned connection timeout        
 1000        * @deprecated                                
 1001        */                                                                 
 1002       public int getRemoveAbandonedTimeout() { 
 1003           if (abandonedConfig != null) {
 1004               return abandonedConfig.getRemoveAbandonedTimeout();
 1005           }
 1006           return 300;
 1007       }                                        
 1008   
 1009       /**
 1010        * @deprecated
 1011        * @param removeAbandonedTimeout new removeAbandonedTimeout value
 1012        */               
 1013       public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
 1014           if (abandonedConfig == null) {
 1015               abandonedConfig = new AbandonedConfig();
 1016           }
 1017           abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
 1018           this.restartNeeded = true;
 1019       }                                                                  
 1020                                                                
 1021       /**
 1022        * <p>Flag to log stack traces for application code which abandoned
 1023        * a Statement or Connection.
 1024        * </p>
 1025        * <p>Defaults to false.                
 1026        * </p>                                                            
 1027        * <p>Logging of abandoned Statements and Connections adds overhead
 1028        * for every Connection open or new Statement because a stack   
 1029        * trace has to be generated. </p>
 1030        *             
 1031        * @deprecated                      
 1032        */                                                          
 1033       public boolean getLogAbandoned() {   
 1034           if (abandonedConfig != null) {
 1035               return abandonedConfig.getLogAbandoned();
 1036           }
 1037           return false;
 1038       }                                 
 1039   
 1040       /**
 1041        * @deprecated
 1042        * @param logAbandoned new logAbandoned property value
 1043        */
 1044       public void setLogAbandoned(boolean logAbandoned) {
 1045           if (abandonedConfig == null) {
 1046               abandonedConfig = new AbandonedConfig();
 1047           }
 1048           abandonedConfig.setLogAbandoned(logAbandoned);
 1049           this.restartNeeded = true;
 1050       }
 1051   
 1052       // --------------------------------------------------------- Public Methods
 1053   
 1054       /**
 1055        * Add a custom connection property to the set that will be passed to our
 1056        * JDBC driver. This <strong>MUST</strong> be called before the first
 1057        * connection is retrieved (along with all the other configuration
 1058        * property setters). Calls to this method after the connection pool
 1059        * has been initialized have no effect.
 1060        *
 1061        * @param name Name of the custom connection property
 1062        * @param value Value of the custom connection property
 1063        */
 1064       public void addConnectionProperty(String name, String value) {
 1065           connectionProperties.put(name, value);
 1066           this.restartNeeded = true;
 1067       }
 1068   
 1069       /**
 1070        * Remove a custom connection property.
 1071        * 
 1072        * @param name Name of the custom connection property to remove
 1073        * @see #addConnectionProperty(String, String)
 1074        */
 1075       public void removeConnectionProperty(String name) {
 1076           connectionProperties.remove(name);
 1077           this.restartNeeded = true;
 1078       }
 1079   
 1080       /**
 1081        * Close and release all connections that are currently stored in the
 1082        * connection pool associated with our data source.
 1083        *
 1084        * @throws SQLException if a database error occurs
 1085        */
 1086       public synchronized void close() throws SQLException {
 1087           GenericObjectPool oldpool = connectionPool;
 1088           connectionPool = null;
 1089           dataSource = null;
 1090           try {
 1091               if (oldpool != null) {
 1092                   oldpool.close();
 1093               }
 1094           } catch(SQLException e) {
 1095               throw e;
 1096           } catch(RuntimeException e) {
 1097               throw e;
 1098           } catch(Exception e) {
 1099               throw new SQLNestedException("Cannot close connection pool", e);
 1100           }
 1101       }
 1102   
 1103   
 1104       // ------------------------------------------------------ Protected Methods
 1105   
 1106   
 1107       /**
 1108        * <p>Create (if necessary) and return the internal data source we are
 1109        * using to manage our connections.</p>
 1110        *
 1111        * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the
 1112        * "double checked locking" idiom in an attempt to avoid synchronizing
 1113        * on every single call to this method.  However, this idiom fails to
 1114        * work correctly in the face of some optimizations that are legal for
 1115        * a JVM to perform.</p>
 1116        *
 1117        * @throws SQLException if the object pool cannot be created.
 1118        */
 1119       protected synchronized DataSource createDataSource()
 1120           throws SQLException {
 1121   
 1122           // Return the pool if we have already created it
 1123           if (dataSource != null) {
 1124               return (dataSource);
 1125           }
 1126   
 1127           // Load the JDBC driver class
 1128           if (driverClassName != null) {
 1129               try {
 1130                   Class.forName(driverClassName);
 1131               } catch (Throwable t) {
 1132                   String message = "Cannot load JDBC driver class '" +
 1133                       driverClassName + "'";
 1134                   logWriter.println(message);
 1135                   t.printStackTrace(logWriter);
 1136                   throw new SQLNestedException(message, t);
 1137               }
 1138           }
 1139   
 1140           // Create a JDBC driver instance
 1141           Driver driver = null;
 1142           try {
 1143               driver = DriverManager.getDriver(url);
 1144           } catch (Throwable t) {
 1145               String message = "Cannot create JDBC driver of class '" +
 1146                   (driverClassName != null ? driverClassName : "") + 
 1147                   "' for connect URL '" + url + "'";
 1148               logWriter.println(message);
 1149               t.printStackTrace(logWriter);
 1150               throw new SQLNestedException(message, t);
 1151           }
 1152   
 1153           // Can't test without a validationQuery
 1154           if (validationQuery == null) {
 1155               setTestOnBorrow(false);
 1156               setTestOnReturn(false);
 1157               setTestWhileIdle(false);
 1158           }
 1159   
 1160           // Create an object pool to contain our active connections
 1161           if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned())) {
 1162               connectionPool = new AbandonedObjectPool(null,abandonedConfig);
 1163           }
 1164           else {
 1165               connectionPool = new GenericObjectPool();
 1166           }
 1167           connectionPool.setMaxActive(maxActive);
 1168           connectionPool.setMaxIdle(maxIdle);
 1169           connectionPool.setMinIdle(minIdle);
 1170           connectionPool.setMaxWait(maxWait);
 1171           connectionPool.setTestOnBorrow(testOnBorrow);
 1172           connectionPool.setTestOnReturn(testOnReturn);
 1173           connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
 1174           connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
 1175           connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
 1176           connectionPool.setTestWhileIdle(testWhileIdle);
 1177           
 1178           // Set up statement pool, if desired
 1179           GenericKeyedObjectPoolFactory statementPoolFactory = null;
 1180           if (isPoolPreparedStatements()) {
 1181               statementPoolFactory = new GenericKeyedObjectPoolFactory(null, 
 1182                           -1, // unlimited maxActive (per key)
 1183                           GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL, 
 1184                           0, // maxWait
 1185                           1, // maxIdle (per key) 
 1186                           maxOpenPreparedStatements); 
 1187           }
 1188   
 1189           // Set up the driver connection factory we will use
 1190           if (username != null) {
 1191               connectionProperties.put("user", username);
 1192           } else {
 1193               log("DBCP DataSource configured without a 'username'");
 1194           }
 1195           
 1196           if (password != null) {
 1197               connectionProperties.put("password", password);
 1198           } else {
 1199               log("DBCP DataSource configured without a 'password'");
 1200           }
 1201           
 1202           DriverConnectionFactory driverConnectionFactory =
 1203               new DriverConnectionFactory(driver, url, connectionProperties);
 1204   
 1205           // Set up the poolable connection factory we will use
 1206           PoolableConnectionFactory connectionFactory = null;
 1207           try {
 1208               connectionFactory =
 1209                   new PoolableConnectionFactory(driverConnectionFactory,
 1210                                                 connectionPool,
 1211                                                 statementPoolFactory,
 1212                                                 validationQuery,
 1213                                                 defaultReadOnly,
 1214                                                 defaultAutoCommit,
 1215                                                 defaultTransactionIsolation,
 1216                                                 defaultCatalog,
 1217                                                 abandonedConfig);
 1218               if (connectionFactory == null) {
 1219                   throw new SQLException("Cannot create PoolableConnectionFactory");
 1220               }
 1221               validateConnectionFactory(connectionFactory);
 1222           } catch (RuntimeException e) {
 1223               throw e;
 1224           } catch (Exception e) {
 1225               throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
 1226           }
 1227   
 1228           // Create and return the pooling data source to manage the connections
 1229           dataSource = new PoolingDataSource(connectionPool);
 1230           ((PoolingDataSource) dataSource).setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
 1231           dataSource.setLogWriter(logWriter);
 1232           
 1233           try {
 1234               for (int i = 0 ; i < initialSize ; i++) {
 1235                   connectionPool.addObject();
 1236               }
 1237           } catch (Exception e) {
 1238               throw new SQLNestedException("Error preloading the connection pool", e);
 1239           }
 1240           
 1241           return dataSource;
 1242       }
 1243   
 1244       private static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception {
 1245           Connection conn = null;
 1246           try {
 1247               conn = (Connection) connectionFactory.makeObject();
 1248               connectionFactory.activateObject(conn);
 1249               connectionFactory.validateConnection(conn);
 1250               connectionFactory.passivateObject(conn);
 1251           }
 1252           finally {
 1253               connectionFactory.destroyObject(conn);
 1254           }
 1255       }
 1256   
 1257       /**
 1258        * Not used currently
 1259        */
 1260       private void restart() {
 1261           try {
 1262               close();
 1263           } catch (SQLException e) {
 1264               log("Could not restart DataSource, cause: " + e.getMessage());
 1265           }
 1266       }
 1267   
 1268       private void log(String message) {
 1269           if (logWriter != null) {
 1270               logWriter.println(message);
 1271           }
 1272       }
 1273   }

Save This Page
Home » commons-dbcp-1.2.2-src » org.apache.commons » dbcp » [javadoc | source]