001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbcp2; 018 019import java.io.OutputStreamWriter; 020import java.io.PrintWriter; 021import java.nio.charset.StandardCharsets; 022import java.security.AccessController; 023import java.security.PrivilegedActionException; 024import java.security.PrivilegedExceptionAction; 025import java.sql.Connection; 026import java.sql.Driver; 027import java.sql.DriverManager; 028import java.sql.SQLException; 029import java.sql.SQLFeatureNotSupportedException; 030import java.util.ArrayList; 031import java.util.Collection; 032import java.util.Collections; 033import java.util.HashSet; 034import java.util.List; 035import java.util.Objects; 036import java.util.Properties; 037import java.util.Set; 038import java.util.logging.Logger; 039 040import javax.management.MBeanRegistration; 041import javax.management.MBeanServer; 042import javax.management.MalformedObjectNameException; 043import javax.management.ObjectName; 044import javax.sql.DataSource; 045 046import org.apache.commons.logging.Log; 047import org.apache.commons.logging.LogFactory; 048import org.apache.commons.pool2.PooledObject; 049import org.apache.commons.pool2.impl.AbandonedConfig; 050import org.apache.commons.pool2.impl.BaseObjectPoolConfig; 051import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 052import org.apache.commons.pool2.impl.GenericObjectPool; 053import org.apache.commons.pool2.impl.GenericObjectPoolConfig; 054 055/** 056 * <p> 057 * Basic implementation of <code>javax.sql.DataSource</code> that is configured via JavaBeans properties. This is not 058 * the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a "one stop 059 * shopping" solution for basic requirements. 060 * </p> 061 * 062 * @since 2.0 063 */ 064public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBeanRegistration, AutoCloseable { 065 066 /** 067 * @since 2.0 068 */ 069 private class PaGetConnection implements PrivilegedExceptionAction<Connection> { 070 071 @Override 072 public Connection run() throws SQLException { 073 return createDataSource().getConnection(); 074 } 075 } 076 077 private static final Log log = LogFactory.getLog(BasicDataSource.class); 078 079 // ------------------------------------------------------------- Properties 080 081 static { 082 // Attempt to prevent deadlocks - see DBCP - 272 083 DriverManager.getDrivers(); 084 try { 085 // Load classes now to prevent AccessControlExceptions later 086 // A number of classes are loaded when getConnection() is called 087 // but the following classes are not loaded and therefore require 088 // explicit loading. 089 if (Utils.IS_SECURITY_ENABLED) { 090 final ClassLoader loader = BasicDataSource.class.getClassLoader(); 091 final String dbcpPackageName = BasicDataSource.class.getPackage().getName(); 092 loader.loadClass(dbcpPackageName + ".BasicDataSource$PaGetConnection"); 093 loader.loadClass(dbcpPackageName + ".DelegatingCallableStatement"); 094 loader.loadClass(dbcpPackageName + ".DelegatingDatabaseMetaData"); 095 loader.loadClass(dbcpPackageName + ".DelegatingPreparedStatement"); 096 loader.loadClass(dbcpPackageName + ".DelegatingResultSet"); 097 loader.loadClass(dbcpPackageName + ".PoolableCallableStatement"); 098 loader.loadClass(dbcpPackageName + ".PoolablePreparedStatement"); 099 loader.loadClass(dbcpPackageName + ".PoolingConnection$StatementType"); 100 loader.loadClass(dbcpPackageName + ".PStmtKey"); 101 102 final String poolPackageName = PooledObject.class.getPackage().getName(); 103 loader.loadClass(poolPackageName + ".impl.LinkedBlockingDeque$Node"); 104 loader.loadClass(poolPackageName + ".impl.GenericKeyedObjectPool$ObjectDeque"); 105 } 106 } catch (final ClassNotFoundException cnfe) { 107 throw new IllegalStateException("Unable to pre-load classes", cnfe); 108 } 109 } 110 111 protected static void validateConnectionFactory(final PoolableConnectionFactory connectionFactory) 112 throws Exception { 113 PoolableConnection conn = null; 114 PooledObject<PoolableConnection> p = null; 115 try { 116 p = connectionFactory.makeObject(); 117 conn = p.getObject(); 118 connectionFactory.activateObject(p); 119 connectionFactory.validateConnection(conn); 120 connectionFactory.passivateObject(p); 121 } finally { 122 if (p != null) { 123 connectionFactory.destroyObject(p); 124 } 125 } 126 } 127 128 /** 129 * The default auto-commit state of connections created by this pool. 130 */ 131 private volatile Boolean defaultAutoCommit; 132 133 /** 134 * The default read-only state of connections created by this pool. 135 */ 136 private transient Boolean defaultReadOnly; 137 138 /** 139 * The default TransactionIsolation state of connections created by this pool. 140 */ 141 private volatile int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; 142 143 private Integer defaultQueryTimeoutSeconds; 144 145 /** 146 * The default "catalog" of connections created by this pool. 147 */ 148 private volatile String defaultCatalog; 149 150 /** 151 * The default "schema" of connections created by this pool. 152 */ 153 private volatile String defaultSchema; 154 155 /** 156 * The property that controls if the pooled connections cache some state rather than query the database for current 157 * state to improve performance. 158 */ 159 private boolean cacheState = true; 160 161 /** 162 * The instance of the JDBC Driver to use. 163 */ 164 private Driver driver; 165 166 /** 167 * The fully qualified Java class name of the JDBC driver to be used. 168 */ 169 private String driverClassName; 170 171 /** 172 * The class loader instance to use to load the JDBC driver. If not specified, {@link Class#forName(String)} is used 173 * to load the JDBC driver. If specified, {@link Class#forName(String, boolean, ClassLoader)} is used. 174 */ 175 private ClassLoader driverClassLoader; 176 177 /** 178 * True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle 179 * connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle 180 * instance pool in the order that they are returned to the pool. 181 */ 182 private boolean lifo = BaseObjectPoolConfig.DEFAULT_LIFO; 183 184 /** 185 * The maximum number of active connections that can be allocated from this pool at the same time, or negative for 186 * no limit. 187 */ 188 private int maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL; 189 190 /** 191 * The maximum number of connections that can remain idle in the pool, without extra ones being destroyed, or 192 * negative for no limit. If maxIdle is set too low on heavily loaded systems it is possible you will see 193 * connections being closed and almost immediately new connections being opened. This is a result of the active 194 * threads momentarily closing connections faster than they are opening them, causing the number of idle connections 195 * to rise above maxIdle. The best value for maxIdle for heavily loaded system will vary but the default is a good 196 * starting point. 197 */ 198 private int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE; 199 200 /** 201 * The minimum number of active connections that can remain idle in the pool, without extra ones being created when 202 * the evictor runs, or 0 to create none. The pool attempts to ensure that minIdle connections are available when 203 * the idle object evictor runs. The value of this property has no effect unless 204 * {@link #timeBetweenEvictionRunsMillis} has a positive value. 205 */ 206 private int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE; 207 208 /** 209 * The initial number of connections that are created when the pool is started. 210 */ 211 private int initialSize = 0; 212 213 /** 214 * The maximum number of milliseconds that the pool will wait (when there are no available connections) for a 215 * connection to be returned before throwing an exception, or <= 0 to wait indefinitely. 216 */ 217 private long maxWaitMillis = BaseObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS; 218 219 /** 220 * Prepared statement pooling for this pool. When this property is set to <code>true</code> both PreparedStatements 221 * and CallableStatements are pooled. 222 */ 223 private boolean poolPreparedStatements = false; 224 225 /** 226 * <p> 227 * The maximum number of open statements that can be allocated from the statement pool at the same time, or negative 228 * for no limit. Since a connection usually only uses one or two statements at a time, this is mostly used to help 229 * detect resource leaks. 230 * </p> 231 * <p> 232 * Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) are pooled along 233 * with PreparedStatements (produced by {@link Connection#prepareStatement}) and 234 * <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements that may be in 235 * use at a given time. 236 * </p> 237 */ 238 private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; 239 240 /** 241 * The indication of whether objects will be validated as soon as they have been created by the pool. If the object 242 * fails to validate, the borrow operation that triggered the creation will fail. 243 */ 244 private boolean testOnCreate = false; 245 246 /** 247 * The indication of whether objects will be validated before being borrowed from the pool. If the object fails to 248 * validate, it will be dropped from the pool, and we will attempt to borrow another. 249 */ 250 private boolean testOnBorrow = true; 251 252 /** 253 * The indication of whether objects will be validated before being returned to the pool. 254 */ 255 private boolean testOnReturn = false; 256 257 /** 258 * The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle 259 * object evictor thread will be run. 260 */ 261 private long timeBetweenEvictionRunsMillis = BaseObjectPoolConfig.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; 262 263 /** 264 * The number of objects to examine during each run of the idle object evictor thread (if any). 265 */ 266 private int numTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 267 268 /** 269 * The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle 270 * object evictor (if any). 271 */ 272 private long minEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 273 274 /** 275 * The minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the idle 276 * object evictor, with the extra condition that at least "minIdle" connections remain in the pool. Note that 277 * {@code minEvictableIdleTimeMillis} takes precedence over this parameter. See 278 * {@link #getSoftMinEvictableIdleTimeMillis()}. 279 */ 280 private long softMinEvictableIdleTimeMillis = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; 281 282 private String evictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; 283 284 /** 285 * The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to 286 * validate, it will be dropped from the pool. 287 */ 288 private boolean testWhileIdle = false; 289 290 /** 291 * The connection password to be passed to our JDBC driver to establish a connection. 292 */ 293 private volatile String password; 294 295 /** 296 * The connection URL to be passed to our JDBC driver to establish a connection. 297 */ 298 private String url; 299 300 /** 301 * The connection user name to be passed to our JDBC driver to establish a connection. 302 */ 303 private String userName; 304 305 /** 306 * The SQL query that will be used to validate connections from this pool before returning them to the caller. If 307 * specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not 308 * specified, {@link Connection#isValid(int)} will be used to validate connections. 309 */ 310 private volatile String validationQuery; 311 312 /** 313 * Timeout in seconds before connection validation queries fail. 314 */ 315 private volatile int validationQueryTimeoutSeconds = -1; 316 317 /** 318 * These SQL statements run once after a Connection is created. 319 * <p> 320 * This property can be used for example to run ALTER SESSION SET NLS_SORT=XCYECH in an Oracle Database only once 321 * after connection creation. 322 * </p> 323 */ 324 private volatile List<String> connectionInitSqls; 325 326 /** 327 * Controls access to the underlying connection. 328 */ 329 private boolean accessToUnderlyingConnectionAllowed = false; 330 331 private long maxConnLifetimeMillis = -1; 332 333 private boolean logExpiredConnections = true; 334 335 private String jmxName; 336 337 private boolean autoCommitOnReturn = true; 338 339 private boolean rollbackOnReturn = true; 340 341 private volatile Set<String> disconnectionSqlCodes; 342 343 private boolean fastFailValidation; 344 345 /** 346 * The object pool that internally manages our connections. 347 */ 348 private volatile GenericObjectPool<PoolableConnection> connectionPool; 349 350 /** 351 * The connection properties that will be sent to our JDBC driver when establishing new connections. 352 * <strong>NOTE</strong> - The "user" and "password" properties will be passed explicitly, so they do not need to be 353 * included here. 354 */ 355 private Properties connectionProperties = new Properties(); 356 357 /** 358 * The data source we will use to manage connections. This object should be acquired <strong>ONLY</strong> by calls 359 * to the <code>createDataSource()</code> method. 360 */ 361 private volatile DataSource dataSource; 362 363 /** 364 * The PrintWriter to which log messages should be directed. 365 */ 366 private volatile PrintWriter logWriter = new PrintWriter( 367 new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); 368 369 private AbandonedConfig abandonedConfig; 370 371 private boolean closed; 372 373 /** 374 * Actual name under which this component has been registered. 375 */ 376 private ObjectNameWrapper registeredJmxObjectName; 377 378 /** 379 * Adds a custom connection property to the set that will be passed to our JDBC driver. This <strong>MUST</strong> 380 * be called before the first connection is retrieved (along with all the other configuration property setters). 381 * Calls to this method after the connection pool has been initialized have no effect. 382 * 383 * @param name 384 * Name of the custom connection property 385 * @param value 386 * Value of the custom connection property 387 */ 388 public void addConnectionProperty(final String name, final String value) { 389 connectionProperties.put(name, value); 390 } 391 392 /** 393 * <p> 394 * Closes and releases all idle connections that are currently stored in the connection pool associated with this 395 * data source. 396 * </p> 397 * <p> 398 * Connections that are checked out to clients when this method is invoked are not affected. When client 399 * applications subsequently invoke {@link Connection#close()} to return these connections to the pool, the 400 * underlying JDBC connections are closed. 401 * </p> 402 * <p> 403 * Attempts to acquire connections using {@link #getConnection()} after this method has been invoked result in 404 * SQLExceptions. 405 * </p> 406 * <p> 407 * This method is idempotent - i.e., closing an already closed BasicDataSource has no effect and does not generate 408 * exceptions. 409 * </p> 410 * 411 * @throws SQLException 412 * if an error occurs closing idle connections 413 */ 414 @Override 415 public synchronized void close() throws SQLException { 416 if (registeredJmxObjectName != null) { 417 registeredJmxObjectName.unregisterMBean(); 418 registeredJmxObjectName = null; 419 } 420 closed = true; 421 final GenericObjectPool<?> oldpool = connectionPool; 422 connectionPool = null; 423 dataSource = null; 424 try { 425 if (oldpool != null) { 426 oldpool.close(); 427 } 428 } catch (final RuntimeException e) { 429 throw e; 430 } catch (final Exception e) { 431 throw new SQLException(Utils.getMessage("pool.close.fail"), e); 432 } 433 } 434 435 /** 436 * Closes the connection pool, silently swallowing any exception that occurs. 437 */ 438 private void closeConnectionPool() { 439 final GenericObjectPool<?> oldPool = connectionPool; 440 connectionPool = null; 441 try { 442 if (oldPool != null) { 443 oldPool.close(); 444 } 445 } catch (final Exception e) { 446 /* Ignore */ 447 } 448 } 449 450 /** 451 * Creates a JDBC connection factory for this datasource. The JDBC driver is loaded using the following algorithm: 452 * <ol> 453 * <li>If a Driver instance has been specified via {@link #setDriver(Driver)} use it</li> 454 * <li>If no Driver instance was specified and {@link #driverClassName} is specified that class is loaded using the 455 * {@link ClassLoader} of this class or, if {@link #driverClassLoader} is set, {@link #driverClassName} is loaded 456 * with the specified {@link ClassLoader}.</li> 457 * <li>If {@link #driverClassName} is specified and the previous attempt fails, the class is loaded using the 458 * context class loader of the current thread.</li> 459 * <li>If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {@link #url}. 460 * </ol> 461 * This method exists so subclasses can replace the implementation class. 462 * 463 * @return A new connection factory. 464 * 465 * @throws SQLException 466 * If the connection factort cannot be created 467 */ 468 protected ConnectionFactory createConnectionFactory() throws SQLException { 469 // Load the JDBC driver class 470 Driver driverToUse = this.driver; 471 472 if (driverToUse == null) { 473 Class<?> driverFromCCL = null; 474 if (driverClassName != null) { 475 try { 476 try { 477 if (driverClassLoader == null) { 478 driverFromCCL = Class.forName(driverClassName); 479 } else { 480 driverFromCCL = Class.forName(driverClassName, true, driverClassLoader); 481 } 482 } catch (final ClassNotFoundException cnfe) { 483 driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(driverClassName); 484 } 485 } catch (final Exception t) { 486 final String message = "Cannot load JDBC driver class '" + driverClassName + "'"; 487 logWriter.println(message); 488 t.printStackTrace(logWriter); 489 throw new SQLException(message, t); 490 } 491 } 492 493 try { 494 if (driverFromCCL == null) { 495 driverToUse = DriverManager.getDriver(url); 496 } else { 497 // Usage of DriverManager is not possible, as it does not 498 // respect the ContextClassLoader 499 // N.B. This cast may cause ClassCastException which is handled below 500 driverToUse = (Driver) driverFromCCL.getConstructor().newInstance(); 501 if (!driverToUse.acceptsURL(url)) { 502 throw new SQLException("No suitable driver", "08001"); 503 } 504 } 505 } catch (final Exception t) { 506 final String message = "Cannot create JDBC driver of class '" 507 + (driverClassName != null ? driverClassName : "") + "' for connect URL '" + url + "'"; 508 logWriter.println(message); 509 t.printStackTrace(logWriter); 510 throw new SQLException(message, t); 511 } 512 } 513 514 // Set up the driver connection factory we will use 515 final String user = userName; 516 if (user != null) { 517 connectionProperties.put("user", user); 518 } else { 519 log("DBCP DataSource configured without a 'username'"); 520 } 521 522 final String pwd = password; 523 if (pwd != null) { 524 connectionProperties.put("password", pwd); 525 } else { 526 log("DBCP DataSource configured without a 'password'"); 527 } 528 529 final ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driverToUse, url, 530 connectionProperties); 531 return driverConnectionFactory; 532 } 533 534 /** 535 * Creates a connection pool for this datasource. This method only exists so subclasses can replace the 536 * implementation class. 537 * <p> 538 * This implementation configures all pool properties other than timeBetweenEvictionRunsMillis. Setting that 539 * property is deferred to {@link #startPoolMaintenance()}, since setting timeBetweenEvictionRunsMillis to a 540 * positive value causes {@link GenericObjectPool}'s eviction timer to be started. 541 * </p> 542 * 543 * @param factory 544 * The factory to use to create new connections for this pool. 545 */ 546 protected void createConnectionPool(final PoolableConnectionFactory factory) { 547 // Create an object pool to contain our active connections 548 final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>(); 549 updateJmxName(config); 550 // Disable JMX on the underlying pool if the DS is not registered: 551 config.setJmxEnabled(registeredJmxObjectName != null); 552 final GenericObjectPool<PoolableConnection> gop = createObjectPool(factory, config, abandonedConfig); 553 gop.setMaxTotal(maxTotal); 554 gop.setMaxIdle(maxIdle); 555 gop.setMinIdle(minIdle); 556 gop.setMaxWaitMillis(maxWaitMillis); 557 gop.setTestOnCreate(testOnCreate); 558 gop.setTestOnBorrow(testOnBorrow); 559 gop.setTestOnReturn(testOnReturn); 560 gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); 561 gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 562 gop.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); 563 gop.setTestWhileIdle(testWhileIdle); 564 gop.setLifo(lifo); 565 gop.setSwallowedExceptionListener(new SwallowedExceptionLogger(log, logExpiredConnections)); 566 gop.setEvictionPolicyClassName(evictionPolicyClassName); 567 factory.setPool(gop); 568 connectionPool = gop; 569 } 570 571 /** 572 * <p> 573 * Creates (if necessary) and return the internal data source we are using to manage our connections. 574 * </p> 575 * 576 * @return The current internal DataSource or a newly created instance if it has not yet been created. 577 * @throws SQLException 578 * if the object pool cannot be created. 579 */ 580 protected DataSource createDataSource() throws SQLException { 581 if (closed) { 582 throw new SQLException("Data source is closed"); 583 } 584 585 // Return the pool if we have already created it 586 // This is double-checked locking. This is safe since dataSource is 587 // volatile and the code is targeted at Java 5 onwards. 588 if (dataSource != null) { 589 return dataSource; 590 } 591 synchronized (this) { 592 if (dataSource != null) { 593 return dataSource; 594 } 595 596 jmxRegister(); 597 598 // create factory which returns raw physical connections 599 final ConnectionFactory driverConnectionFactory = createConnectionFactory(); 600 601 // Set up the poolable connection factory 602 boolean success = false; 603 PoolableConnectionFactory poolableConnectionFactory; 604 try { 605 poolableConnectionFactory = createPoolableConnectionFactory(driverConnectionFactory); 606 poolableConnectionFactory.setPoolStatements(poolPreparedStatements); 607 poolableConnectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); 608 success = true; 609 } catch (final SQLException se) { 610 throw se; 611 } catch (final RuntimeException rte) { 612 throw rte; 613 } catch (final Exception ex) { 614 throw new SQLException("Error creating connection factory", ex); 615 } 616 617 if (success) { 618 // create a pool for our connections 619 createConnectionPool(poolableConnectionFactory); 620 } 621 622 // Create the pooling data source to manage connections 623 DataSource newDataSource; 624 success = false; 625 try { 626 newDataSource = createDataSourceInstance(); 627 newDataSource.setLogWriter(logWriter); 628 success = true; 629 } catch (final SQLException se) { 630 throw se; 631 } catch (final RuntimeException rte) { 632 throw rte; 633 } catch (final Exception ex) { 634 throw new SQLException("Error creating datasource", ex); 635 } finally { 636 if (!success) { 637 closeConnectionPool(); 638 } 639 } 640 641 // If initialSize > 0, preload the pool 642 try { 643 for (int i = 0; i < initialSize; i++) { 644 connectionPool.addObject(); 645 } 646 } catch (final Exception e) { 647 closeConnectionPool(); 648 throw new SQLException("Error preloading the connection pool", e); 649 } 650 651 // If timeBetweenEvictionRunsMillis > 0, start the pool's evictor task 652 startPoolMaintenance(); 653 654 dataSource = newDataSource; 655 return dataSource; 656 } 657 } 658 659 /** 660 * Creates the actual data source instance. This method only exists so that subclasses can replace the 661 * implementation class. 662 * 663 * @throws SQLException 664 * if unable to create a datasource instance 665 * 666 * @return A new DataSource instance 667 */ 668 protected DataSource createDataSourceInstance() throws SQLException { 669 final PoolingDataSource<PoolableConnection> pds = new PoolingDataSource<>(connectionPool); 670 pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); 671 return pds; 672 } 673 674 /** 675 * Creates an object pool used to provide pooling support for {@link Connection JDBC connections}. 676 * 677 * @param factory 678 * the object factory 679 * @param poolConfig 680 * the object pool configuration 681 * @param abandonedConfig 682 * the abandoned objects configuration 683 * @return a non-null instance 684 */ 685 protected GenericObjectPool<PoolableConnection> createObjectPool(final PoolableConnectionFactory factory, 686 final GenericObjectPoolConfig<PoolableConnection> poolConfig, final AbandonedConfig abandonedConfig) { 687 GenericObjectPool<PoolableConnection> gop; 688 if (abandonedConfig != null && (abandonedConfig.getRemoveAbandonedOnBorrow() 689 || abandonedConfig.getRemoveAbandonedOnMaintenance())) { 690 gop = new GenericObjectPool<>(factory, poolConfig, abandonedConfig); 691 } else { 692 gop = new GenericObjectPool<>(factory, poolConfig); 693 } 694 return gop; 695 } 696 697 /** 698 * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists so 699 * subclasses can replace the default implementation. 700 * 701 * @param driverConnectionFactory 702 * JDBC connection factory 703 * @throws SQLException 704 * if an error occurs creating the PoolableConnectionFactory 705 * 706 * @return A new PoolableConnectionFactory configured with the current configuration of this BasicDataSource 707 */ 708 protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory) 709 throws SQLException { 710 PoolableConnectionFactory connectionFactory = null; 711 try { 712 connectionFactory = new PoolableConnectionFactory(driverConnectionFactory, 713 ObjectNameWrapper.unwrap(registeredJmxObjectName)); 714 connectionFactory.setValidationQuery(validationQuery); 715 connectionFactory.setValidationQueryTimeout(validationQueryTimeoutSeconds); 716 connectionFactory.setConnectionInitSql(connectionInitSqls); 717 connectionFactory.setDefaultReadOnly(defaultReadOnly); 718 connectionFactory.setDefaultAutoCommit(defaultAutoCommit); 719 connectionFactory.setDefaultTransactionIsolation(defaultTransactionIsolation); 720 connectionFactory.setDefaultCatalog(defaultCatalog); 721 connectionFactory.setDefaultSchema(defaultSchema); 722 connectionFactory.setCacheState(cacheState); 723 connectionFactory.setPoolStatements(poolPreparedStatements); 724 connectionFactory.setMaxOpenPreparedStatements(maxOpenPreparedStatements); 725 connectionFactory.setMaxConnLifetimeMillis(maxConnLifetimeMillis); 726 connectionFactory.setRollbackOnReturn(getRollbackOnReturn()); 727 connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn()); 728 connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeout()); 729 connectionFactory.setFastFailValidation(fastFailValidation); 730 connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes); 731 validateConnectionFactory(connectionFactory); 732 } catch (final RuntimeException e) { 733 throw e; 734 } catch (final Exception e) { 735 throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); 736 } 737 return connectionFactory; 738 } 739 740 /** 741 * Gets the print writer used by this configuration to log information on abandoned objects. 742 * 743 * @return The print writer used by this configuration to log information on abandoned objects. 744 */ 745 public PrintWriter getAbandonedLogWriter() { 746 if (abandonedConfig != null) { 747 return abandonedConfig.getLogWriter(); 748 } 749 return null; 750 } 751 752 /** 753 * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, should the 754 * connection pool record a stack trace every time a method is called on a pooled connection and retain the most 755 * recent stack trace to aid debugging of abandoned connections? 756 * 757 * @return <code>true</code> if usage tracking is enabled 758 */ 759 @Override 760 public boolean getAbandonedUsageTracking() { 761 if (abandonedConfig != null) { 762 return abandonedConfig.getUseUsageTracking(); 763 } 764 return false; 765 } 766 767 /** 768 * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked 769 * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit 770 * setting is {@code false} when the connection is returned. It is <code>true</code> by default. 771 * 772 * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. 773 */ 774 public boolean getAutoCommitOnReturn() { 775 return autoCommitOnReturn; 776 } 777 778 /** 779 * Returns the state caching flag. 780 * 781 * @return the state caching flag 782 */ 783 @Override 784 public boolean getCacheState() { 785 return cacheState; 786 } 787 788 /** 789 * Creates (if necessary) and return a connection to the database. 790 * 791 * @throws SQLException 792 * if a database access error occurs 793 * @return a database connection 794 */ 795 @Override 796 public Connection getConnection() throws SQLException { 797 if (Utils.IS_SECURITY_ENABLED) { 798 final PrivilegedExceptionAction<Connection> action = new PaGetConnection(); 799 try { 800 return AccessController.doPrivileged(action); 801 } catch (final PrivilegedActionException e) { 802 final Throwable cause = e.getCause(); 803 if (cause instanceof SQLException) { 804 throw (SQLException) cause; 805 } 806 throw new SQLException(e); 807 } 808 } 809 return createDataSource().getConnection(); 810 } 811 812 /** 813 * <strong>BasicDataSource does NOT support this method.</strong> 814 * 815 * @param user 816 * Database user on whose behalf the Connection is being made 817 * @param pass 818 * The database user's password 819 * 820 * @throws UnsupportedOperationException 821 * always thrown. 822 * @throws SQLException 823 * if a database access error occurs 824 * @return nothing - always throws UnsupportedOperationException 825 */ 826 @Override 827 public Connection getConnection(final String user, final String pass) throws SQLException { 828 // This method isn't supported by the PoolingDataSource returned by the createDataSource 829 throw new UnsupportedOperationException("Not supported by BasicDataSource"); 830 } 831 832 /** 833 * Returns the list of SQL statements executed when a physical connection is first created. Returns an empty list if 834 * there are no initialization statements configured. 835 * 836 * @return initialization SQL statements 837 */ 838 public List<String> getConnectionInitSqls() { 839 final List<String> result = connectionInitSqls; 840 if (result == null) { 841 return Collections.emptyList(); 842 } 843 return result; 844 } 845 846 /** 847 * Provides the same data as {@link #getConnectionInitSqls()} but in an array so it is accessible via JMX. 848 */ 849 @Override 850 public String[] getConnectionInitSqlsAsArray() { 851 final Collection<String> result = getConnectionInitSqls(); 852 return result.toArray(new String[result.size()]); 853 } 854 855 protected GenericObjectPool<PoolableConnection> getConnectionPool() { 856 return connectionPool; 857 } 858 859 // For unit testing 860 Properties getConnectionProperties() { 861 return connectionProperties; 862 } 863 864 /** 865 * Returns the default auto-commit property. 866 * 867 * @return true if default auto-commit is enabled 868 */ 869 @Override 870 public Boolean getDefaultAutoCommit() { 871 return defaultAutoCommit; 872 } 873 874 /** 875 * Returns the default catalog. 876 * 877 * @return the default catalog 878 */ 879 @Override 880 public String getDefaultCatalog() { 881 return this.defaultCatalog; 882 } 883 884 /** 885 * Gets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this 886 * connection. <code>null</code> means that the driver default will be used. 887 * 888 * @return The default query timeout in seconds. 889 */ 890 public Integer getDefaultQueryTimeout() { 891 return defaultQueryTimeoutSeconds; 892 } 893 894 /** 895 * Returns the default readOnly property. 896 * 897 * @return true if connections are readOnly by default 898 */ 899 @Override 900 public Boolean getDefaultReadOnly() { 901 return defaultReadOnly; 902 } 903 904 /** 905 * Returns the default schema. 906 * 907 * @return the default schema. 908 * @since 2.5.0 909 */ 910 @Override 911 public String getDefaultSchema() { 912 return this.defaultSchema; 913 } 914 915 /** 916 * Returns the default transaction isolation state of returned connections. 917 * 918 * @return the default value for transaction isolation state 919 * @see Connection#getTransactionIsolation 920 */ 921 @Override 922 public int getDefaultTransactionIsolation() { 923 return this.defaultTransactionIsolation; 924 } 925 926 /** 927 * Returns the set of SQL_STATE codes considered to signal fatal conditions. 928 * 929 * @return fatal disconnection state codes 930 * @see #setDisconnectionSqlCodes(Collection) 931 * @since 2.1 932 */ 933 public Set<String> getDisconnectionSqlCodes() { 934 final Set<String> result = disconnectionSqlCodes; 935 if (result == null) { 936 return Collections.emptySet(); 937 } 938 return result; 939 } 940 941 /** 942 * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX. 943 * 944 * @since 2.1 945 */ 946 @Override 947 public String[] getDisconnectionSqlCodesAsArray() { 948 final Collection<String> result = getDisconnectionSqlCodes(); 949 return result.toArray(new String[result.size()]); 950 } 951 952 /** 953 * Returns the JDBC Driver that has been configured for use by this pool. 954 * <p> 955 * Note: This getter only returns the last value set by a call to {@link #setDriver(Driver)}. It does not return any 956 * driver instance that may have been created from the value set via {@link #setDriverClassName(String)}. 957 * </p> 958 * 959 * @return the JDBC Driver that has been configured for use by this pool 960 */ 961 public synchronized Driver getDriver() { 962 return driver; 963 } 964 965 /** 966 * Returns the class loader specified for loading the JDBC driver. Returns <code>null</code> if no class loader has 967 * been explicitly specified. 968 * <p> 969 * Note: This getter only returns the last value set by a call to {@link #setDriverClassLoader(ClassLoader)}. It 970 * does not return the class loader of any driver that may have been set via {@link #setDriver(Driver)}. 971 * </p> 972 * 973 * @return The class loader specified for loading the JDBC driver. 974 */ 975 public synchronized ClassLoader getDriverClassLoader() { 976 return this.driverClassLoader; 977 } 978 979 /** 980 * Returns the JDBC driver class name. 981 * <p> 982 * Note: This getter only returns the last value set by a call to {@link #setDriverClassName(String)}. It does not 983 * return the class name of any driver that may have been set via {@link #setDriver(Driver)}. 984 * </p> 985 * 986 * @return the JDBC driver class name 987 */ 988 @Override 989 public synchronized String getDriverClassName() { 990 return this.driverClassName; 991 } 992 993 /** 994 * Returns the value of the flag that controls whether or not connections being returned to the pool will be checked 995 * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit 996 * setting is {@code false} when the connection is returned. It is <code>true</code> by default. 997 * 998 * @return Whether or not connections being returned to the pool will be checked and configured with auto-commit. 999 * @deprecated Use {@link #getAutoCommitOnReturn()}. 1000 */ 1001 @Deprecated 1002 public boolean getEnableAutoCommitOnReturn() { 1003 return autoCommitOnReturn; 1004 } 1005 1006 /** 1007 * Gets the EvictionPolicy implementation in use with this connection pool. 1008 * 1009 * @return The EvictionPolicy implementation in use with this connection pool. 1010 */ 1011 public synchronized String getEvictionPolicyClassName() { 1012 return evictionPolicyClassName; 1013 } 1014 1015 /** 1016 * True means that validation will fail immediately for connections that have previously thrown SQLExceptions with 1017 * SQL_STATE indicating fatal disconnection errors. 1018 * 1019 * @return true if connections created by this datasource will fast fail validation. 1020 * @see #setDisconnectionSqlCodes(Collection) 1021 * @since 2.1 1022 */ 1023 @Override 1024 public boolean getFastFailValidation() { 1025 return fastFailValidation; 1026 } 1027 1028 /** 1029 * Returns the initial size of the connection pool. 1030 * 1031 * @return the number of connections created when the pool is initialized 1032 */ 1033 @Override 1034 public synchronized int getInitialSize() { 1035 return this.initialSize; 1036 } 1037 1038 /** 1039 * Returns the JMX name that has been requested for this DataSource. If the requested name is not valid, an 1040 * alternative may be chosen. 1041 * 1042 * @return The JMX name that has been requested for this DataSource. 1043 */ 1044 public String getJmxName() { 1045 return jmxName; 1046 } 1047 1048 /** 1049 * Returns the LIFO property. 1050 * 1051 * @return true if connection pool behaves as a LIFO queue. 1052 */ 1053 @Override 1054 public synchronized boolean getLifo() { 1055 return this.lifo; 1056 } 1057 1058 /** 1059 * <p> 1060 * Flag to log stack traces for application code which abandoned a Statement or Connection. 1061 * </p> 1062 * <p> 1063 * Defaults to false. 1064 * </p> 1065 * <p> 1066 * Logging of abandoned Statements and Connections adds overhead for every Connection open or new Statement because 1067 * a stack trace has to be generated. 1068 * </p> 1069 */ 1070 @Override 1071 public boolean getLogAbandoned() { 1072 if (abandonedConfig != null) { 1073 return abandonedConfig.getLogAbandoned(); 1074 } 1075 return false; 1076 } 1077 1078 /** 1079 * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or 1080 * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. 1081 * 1082 * @since 2.1 1083 */ 1084 @Override 1085 public boolean getLogExpiredConnections() { 1086 return logExpiredConnections; 1087 } 1088 1089 /** 1090 * <strong>BasicDataSource does NOT support this method.</strong> 1091 * 1092 * <p> 1093 * Returns the login timeout (in seconds) for connecting to the database. 1094 * </p> 1095 * <p> 1096 * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. 1097 * </p> 1098 * 1099 * @throws SQLException 1100 * if a database access error occurs 1101 * @throws UnsupportedOperationException 1102 * If the DataSource implementation does not support the login timeout feature. 1103 * @return login timeout in seconds 1104 */ 1105 @Override 1106 public int getLoginTimeout() throws SQLException { 1107 // This method isn't supported by the PoolingDataSource returned by the createDataSource 1108 throw new UnsupportedOperationException("Not supported by BasicDataSource"); 1109 } 1110 1111 /** 1112 * <p> 1113 * Returns the log writer being used by this data source. 1114 * </p> 1115 * <p> 1116 * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. 1117 * </p> 1118 * 1119 * @throws SQLException 1120 * if a database access error occurs 1121 * @return log writer in use 1122 */ 1123 @Override 1124 public PrintWriter getLogWriter() throws SQLException { 1125 return createDataSource().getLogWriter(); 1126 } 1127 1128 /** 1129 * Returns the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an 1130 * infinite lifetime. 1131 */ 1132 @Override 1133 public long getMaxConnLifetimeMillis() { 1134 return maxConnLifetimeMillis; 1135 } 1136 1137 /** 1138 * <p> 1139 * Returns the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed 1140 * on return to the pool. 1141 * </p> 1142 * <p> 1143 * A negative value indicates that there is no limit 1144 * </p> 1145 * 1146 * @return the maximum number of idle connections 1147 */ 1148 @Override 1149 public synchronized int getMaxIdle() { 1150 return this.maxIdle; 1151 } 1152 1153 /** 1154 * Gets the value of the <code>maxOpenPreparedStatements</code> property. 1155 * 1156 * @return the maximum number of open statements 1157 */ 1158 @Override 1159 public synchronized int getMaxOpenPreparedStatements() { 1160 return this.maxOpenPreparedStatements; 1161 } 1162 1163 /** 1164 * <p> 1165 * Returns the maximum number of active connections that can be allocated at the same time. 1166 * </p> 1167 * <p> 1168 * A negative number means that there is no limit. 1169 * </p> 1170 * 1171 * @return the maximum number of active connections 1172 */ 1173 @Override 1174 public synchronized int getMaxTotal() { 1175 return this.maxTotal; 1176 } 1177 1178 /** 1179 * Returns the maximum number of milliseconds that the pool will wait for a connection to be returned before 1180 * throwing an exception. A value less than or equal to zero means the pool is set to wait indefinitely. 1181 * 1182 * @return the maxWaitMillis property value 1183 */ 1184 @Override 1185 public synchronized long getMaxWaitMillis() { 1186 return this.maxWaitMillis; 1187 } 1188 1189 /** 1190 * Returns the {@link #minEvictableIdleTimeMillis} property. 1191 * 1192 * @return the value of the {@link #minEvictableIdleTimeMillis} property 1193 * @see #minEvictableIdleTimeMillis 1194 */ 1195 @Override 1196 public synchronized long getMinEvictableIdleTimeMillis() { 1197 return this.minEvictableIdleTimeMillis; 1198 } 1199 1200 /** 1201 * Returns the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections 1202 * are available when the idle object evictor runs. The value of this property has no effect unless 1203 * {@link #timeBetweenEvictionRunsMillis} has a positive value. 1204 * 1205 * @return the minimum number of idle connections 1206 * @see GenericObjectPool#getMinIdle() 1207 */ 1208 @Override 1209 public synchronized int getMinIdle() { 1210 return this.minIdle; 1211 } 1212 1213 /** 1214 * [Read Only] The current number of active connections that have been allocated from this data source. 1215 * 1216 * @return the current number of active connections 1217 */ 1218 @Override 1219 public int getNumActive() { 1220 // Copy reference to avoid NPE if close happens after null check 1221 final GenericObjectPool<PoolableConnection> pool = connectionPool; 1222 if (pool != null) { 1223 return pool.getNumActive(); 1224 } 1225 return 0; 1226 } 1227 1228 /** 1229 * [Read Only] The current number of idle connections that are waiting to be allocated from this data source. 1230 * 1231 * @return the current number of idle connections 1232 */ 1233 @Override 1234 public int getNumIdle() { 1235 // Copy reference to avoid NPE if close happens after null check 1236 final GenericObjectPool<PoolableConnection> pool = connectionPool; 1237 if (pool != null) { 1238 return pool.getNumIdle(); 1239 } 1240 return 0; 1241 } 1242 1243 /** 1244 * Returns the value of the {@link #numTestsPerEvictionRun} property. 1245 * 1246 * @return the number of objects to examine during idle object evictor runs 1247 * @see #numTestsPerEvictionRun 1248 */ 1249 @Override 1250 public synchronized int getNumTestsPerEvictionRun() { 1251 return this.numTestsPerEvictionRun; 1252 } 1253 1254 @Override 1255 public Logger getParentLogger() throws SQLFeatureNotSupportedException { 1256 throw new SQLFeatureNotSupportedException(); 1257 } 1258 1259 /** 1260 * Returns the password passed to the JDBC driver to establish connections. 1261 * 1262 * @return the connection password 1263 */ 1264 @Override 1265 public String getPassword() { 1266 return this.password; 1267 } 1268 1269 protected ObjectName getRegisteredJmxName() { 1270 return ObjectNameWrapper.unwrap(registeredJmxObjectName); 1271 } 1272 1273 /** 1274 * <p> 1275 * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout when borrowObject is invoked. 1276 * </p> 1277 * <p> 1278 * The default value is false. 1279 * </p> 1280 * <p> 1281 * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more 1282 * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds. 1283 * </p> 1284 * <p> 1285 * Abandoned connections are identified and removed when {@link #getConnection()} is invoked and all of the 1286 * following conditions hold: 1287 * </p> 1288 * <ul> 1289 * <li>{@link #getRemoveAbandonedOnBorrow()}</li> 1290 * <li>{@link #getNumActive()} > {@link #getMaxTotal()} - 3</li> 1291 * <li>{@link #getNumIdle()} < 2</li> 1292 * </ul> 1293 * 1294 * @see #getRemoveAbandonedTimeout() 1295 */ 1296 @Override 1297 public boolean getRemoveAbandonedOnBorrow() { 1298 if (abandonedConfig != null) { 1299 return abandonedConfig.getRemoveAbandonedOnBorrow(); 1300 } 1301 return false; 1302 } 1303 1304 /** 1305 * <p> 1306 * Flag to remove abandoned connections if they exceed the removeAbandonedTimeout during pool maintenance. 1307 * </p> 1308 * 1309 * <p> 1310 * The default value is false. 1311 * </p> 1312 * 1313 * <p> 1314 * If set to true a connection is considered abandoned and eligible for removal if it has not been used for more 1315 * than {@link #getRemoveAbandonedTimeout() removeAbandonedTimeout} seconds. 1316 * </p> 1317 * 1318 * @see #getRemoveAbandonedTimeout() 1319 */ 1320 @Override 1321 public boolean getRemoveAbandonedOnMaintenance() { 1322 if (abandonedConfig != null) { 1323 return abandonedConfig.getRemoveAbandonedOnMaintenance(); 1324 } 1325 return false; 1326 } 1327 1328 /** 1329 * <p> 1330 * Timeout in seconds before an abandoned connection can be removed. 1331 * </p> 1332 * <p> 1333 * Creating a Statement, PreparedStatement or CallableStatement or using one of these to execute a query (using one 1334 * of the execute methods) resets the lastUsed property of the parent connection. 1335 * </p> 1336 * <p> 1337 * Abandoned connection cleanup happens when: 1338 * </p> 1339 * <ul> 1340 * <li>{@link #getRemoveAbandonedOnBorrow()} or {@link #getRemoveAbandonedOnMaintenance()} = true</li> 1341 * <li>{@link #getNumIdle() numIdle} < 2</li> 1342 * <li>{@link #getNumActive() numActive} > {@link #getMaxTotal() maxTotal} - 3</li> 1343 * </ul> 1344 * <p> 1345 * The default value is 300 seconds. 1346 * </p> 1347 */ 1348 @Override 1349 public int getRemoveAbandonedTimeout() { 1350 if (abandonedConfig != null) { 1351 return abandonedConfig.getRemoveAbandonedTimeout(); 1352 } 1353 return 300; 1354 } 1355 1356 /** 1357 * Gets the current value of the flag that controls whether a connection will be rolled back when it is returned to 1358 * the pool if auto commit is not enabled and the connection is not read only. 1359 * 1360 * @return whether a connection will be rolled back when it is returned to the pool. 1361 */ 1362 public boolean getRollbackOnReturn() { 1363 return rollbackOnReturn; 1364 } 1365 1366 /** 1367 * <p> 1368 * Returns the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by 1369 * the idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. 1370 * </p> 1371 * 1372 * <p> 1373 * When {@link #getMinEvictableIdleTimeMillis() minEvictableIdleTimeMillis} is set to a positive value, 1374 * minEvictableIdleTimeMillis is examined first by the idle connection evictor - i.e. when idle connections are 1375 * visited by the evictor, idle time is first compared against {@code minEvictableIdleTimeMillis} (without 1376 * considering the number of idle connections in the pool) and then against {@code softMinEvictableIdleTimeMillis}, 1377 * including the {@code minIdle}, constraint. 1378 * </p> 1379 * 1380 * @return minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, assuming 1381 * there are minIdle idle connections in the pool 1382 */ 1383 @Override 1384 public synchronized long getSoftMinEvictableIdleTimeMillis() { 1385 return softMinEvictableIdleTimeMillis; 1386 } 1387 1388 /** 1389 * Returns the {@link #testOnBorrow} property. 1390 * 1391 * @return true if objects are validated before being borrowed from the pool 1392 * 1393 * @see #testOnBorrow 1394 */ 1395 @Override 1396 public synchronized boolean getTestOnBorrow() { 1397 return this.testOnBorrow; 1398 } 1399 1400 /** 1401 * Returns the {@link #testOnCreate} property. 1402 * 1403 * @return true if objects are validated immediately after they are created by the pool 1404 * @see #testOnCreate 1405 */ 1406 @Override 1407 public synchronized boolean getTestOnCreate() { 1408 return this.testOnCreate; 1409 } 1410 1411 /** 1412 * Returns the value of the {@link #testOnReturn} property. 1413 * 1414 * @return true if objects are validated before being returned to the pool 1415 * @see #testOnReturn 1416 */ 1417 public synchronized boolean getTestOnReturn() { 1418 return this.testOnReturn; 1419 } 1420 1421 /** 1422 * Returns the value of the {@link #testWhileIdle} property. 1423 * 1424 * @return true if objects examined by the idle object evictor are validated 1425 * @see #testWhileIdle 1426 */ 1427 @Override 1428 public synchronized boolean getTestWhileIdle() { 1429 return this.testWhileIdle; 1430 } 1431 1432 /** 1433 * Returns the value of the {@link #timeBetweenEvictionRunsMillis} property. 1434 * 1435 * @return the time (in milliseconds) between evictor runs 1436 * @see #timeBetweenEvictionRunsMillis 1437 */ 1438 @Override 1439 public synchronized long getTimeBetweenEvictionRunsMillis() { 1440 return this.timeBetweenEvictionRunsMillis; 1441 } 1442 1443 /** 1444 * Returns the JDBC connection {@link #url} property. 1445 * 1446 * @return the {@link #url} passed to the JDBC driver to establish connections 1447 */ 1448 @Override 1449 public synchronized String getUrl() { 1450 return this.url; 1451 } 1452 1453 /** 1454 * Returns the JDBC connection {@link #userName} property. 1455 * 1456 * @return the {@link #userName} passed to the JDBC driver to establish connections 1457 */ 1458 @Override 1459 public String getUsername() { 1460 return this.userName; 1461 } 1462 1463 /** 1464 * Returns the validation query used to validate connections before returning them. 1465 * 1466 * @return the SQL validation query 1467 * @see #validationQuery 1468 */ 1469 @Override 1470 public String getValidationQuery() { 1471 return this.validationQuery; 1472 } 1473 1474 /** 1475 * Returns the validation query timeout. 1476 * 1477 * @return the timeout in seconds before connection validation queries fail. 1478 */ 1479 @Override 1480 public int getValidationQueryTimeout() { 1481 return validationQueryTimeoutSeconds; 1482 } 1483 1484 /** 1485 * Manually invalidates a connection, effectively requesting the pool to try to close it, remove it from the pool 1486 * and reclaim pool capacity. 1487 * 1488 * @param connection 1489 * The Connection to invalidate. 1490 * 1491 * @throws IllegalStateException 1492 * if invalidating the connection failed. 1493 * @since 2.1 1494 */ 1495 public void invalidateConnection(final Connection connection) throws IllegalStateException { 1496 if (connection == null) { 1497 return; 1498 } 1499 if (connectionPool == null) { 1500 throw new IllegalStateException("Cannot invalidate connection: ConnectionPool is null."); 1501 } 1502 1503 final PoolableConnection poolableConnection; 1504 try { 1505 poolableConnection = connection.unwrap(PoolableConnection.class); 1506 if (poolableConnection == null) { 1507 throw new IllegalStateException( 1508 "Cannot invalidate connection: Connection is not a poolable connection."); 1509 } 1510 } catch (final SQLException e) { 1511 throw new IllegalStateException("Cannot invalidate connection: Unwrapping poolable connection failed.", e); 1512 } 1513 1514 try { 1515 connectionPool.invalidateObject(poolableConnection); 1516 } catch (final Exception e) { 1517 throw new IllegalStateException("Invalidating connection threw unexpected exception", e); 1518 } 1519 } 1520 1521 /** 1522 * Manually evicts idle connections 1523 */ 1524 public void evict() throws Exception { 1525 if (connectionPool != null) { 1526 connectionPool.evict(); 1527 } 1528 } 1529 1530 /** 1531 * Returns the value of the accessToUnderlyingConnectionAllowed property. 1532 * 1533 * @return true if access to the underlying connection is allowed, false otherwise. 1534 */ 1535 @Override 1536 public synchronized boolean isAccessToUnderlyingConnectionAllowed() { 1537 return this.accessToUnderlyingConnectionAllowed; 1538 } 1539 1540 /** 1541 * If true, this data source is closed and no more connections can be retrieved from this datasource. 1542 * 1543 * @return true, if the data source is closed; false otherwise 1544 */ 1545 @Override 1546 public synchronized boolean isClosed() { 1547 return closed; 1548 } 1549 1550 /** 1551 * Returns true if we are pooling statements. 1552 * 1553 * @return true if prepared and callable statements are pooled 1554 */ 1555 @Override 1556 public synchronized boolean isPoolPreparedStatements() { 1557 return this.poolPreparedStatements; 1558 } 1559 1560 @Override 1561 public boolean isWrapperFor(final Class<?> iface) throws SQLException { 1562 return false; 1563 } 1564 1565 private void jmxRegister() { 1566 // Return immediately if this DataSource has already been registered 1567 if (registeredJmxObjectName != null) { 1568 return; 1569 } 1570 // Return immediately if no JMX name has been specified 1571 final String requestedName = getJmxName(); 1572 if (requestedName == null) { 1573 return; 1574 } 1575 try { 1576 ObjectNameWrapper.wrap(requestedName).registerMBean(this); 1577 } catch (final MalformedObjectNameException e) { 1578 log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); 1579 } 1580 } 1581 1582 protected void log(final String message) { 1583 if (logWriter != null) { 1584 logWriter.println(message); 1585 } 1586 } 1587 1588 @Override 1589 public void postDeregister() { 1590 // NO-OP 1591 } 1592 1593 @Override 1594 public void postRegister(final Boolean registrationDone) { 1595 // NO-OP 1596 } 1597 1598 @Override 1599 public void preDeregister() throws Exception { 1600 // NO-OP 1601 } 1602 1603 @Override 1604 public ObjectName preRegister(final MBeanServer server, final ObjectName objectName) { 1605 final String requestedName = getJmxName(); 1606 if (requestedName != null) { 1607 try { 1608 registeredJmxObjectName = ObjectNameWrapper.wrap(requestedName); 1609 } catch (final MalformedObjectNameException e) { 1610 log.warn("The requested JMX name [" + requestedName + "] was not valid and will be ignored."); 1611 } 1612 } 1613 if (registeredJmxObjectName == null) { 1614 registeredJmxObjectName = ObjectNameWrapper.wrap(objectName); 1615 } 1616 return ObjectNameWrapper.unwrap(registeredJmxObjectName); 1617 } 1618 1619 /** 1620 * Removes a custom connection property. 1621 * 1622 * @param name 1623 * Name of the custom connection property to remove 1624 * @see #addConnectionProperty(String, String) 1625 */ 1626 public void removeConnectionProperty(final String name) { 1627 connectionProperties.remove(name); 1628 } 1629 1630 /** 1631 * Sets the print writer to be used by this configuration to log information on abandoned objects. 1632 * 1633 * @param logWriter 1634 * The new log writer 1635 */ 1636 public void setAbandonedLogWriter(final PrintWriter logWriter) { 1637 if (abandonedConfig == null) { 1638 abandonedConfig = new AbandonedConfig(); 1639 } 1640 abandonedConfig.setLogWriter(logWriter); 1641 final GenericObjectPool<?> gop = this.connectionPool; 1642 if (gop != null) { 1643 gop.setAbandonedConfig(abandonedConfig); 1644 } 1645 } 1646 1647 /** 1648 * If the connection pool implements {@link org.apache.commons.pool2.UsageTracking UsageTracking}, configure whether 1649 * the connection pool should record a stack trace every time a method is called on a pooled connection and retain 1650 * the most recent stack trace to aid debugging of abandoned connections. 1651 * 1652 * @param usageTracking 1653 * A value of <code>true</code> will enable the recording of a stack trace on every use of a pooled 1654 * connection 1655 */ 1656 public void setAbandonedUsageTracking(final boolean usageTracking) { 1657 if (abandonedConfig == null) { 1658 abandonedConfig = new AbandonedConfig(); 1659 } 1660 abandonedConfig.setUseUsageTracking(usageTracking); 1661 final GenericObjectPool<?> gop = this.connectionPool; 1662 if (gop != null) { 1663 gop.setAbandonedConfig(abandonedConfig); 1664 } 1665 } 1666 1667 /** 1668 * <p> 1669 * Sets the value of the accessToUnderlyingConnectionAllowed property. It controls if the PoolGuard allows access to 1670 * the underlying connection. (Default: false) 1671 * </p> 1672 * <p> 1673 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1674 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1675 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1676 * </p> 1677 * 1678 * @param allow 1679 * Access to the underlying connection is granted when true. 1680 */ 1681 public synchronized void setAccessToUnderlyingConnectionAllowed(final boolean allow) { 1682 this.accessToUnderlyingConnectionAllowed = allow; 1683 } 1684 1685 /** 1686 * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked 1687 * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit 1688 * setting is {@code false} when the connection is returned. It is <code>true</code> by default. 1689 * 1690 * @param autoCommitOnReturn 1691 * Whether or not connections being returned to the pool will be checked and configured with auto-commit. 1692 * @since 2.6.0 1693 */ 1694 public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) { 1695 this.autoCommitOnReturn = autoCommitOnReturn; 1696 } 1697 1698 /** 1699 * Sets the state caching flag. 1700 * 1701 * @param cacheState 1702 * The new value for the state caching flag 1703 */ 1704 public void setCacheState(final boolean cacheState) { 1705 this.cacheState = cacheState; 1706 } 1707 1708 /** 1709 * Sets the list of SQL statements to be executed when a physical connection is first created. 1710 * <p> 1711 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1712 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1713 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1714 * </p> 1715 * 1716 * @param connectionInitSqls 1717 * Collection of SQL statements to execute on connection creation 1718 */ 1719 public void setConnectionInitSqls(final Collection<String> connectionInitSqls) { 1720 if (connectionInitSqls != null && connectionInitSqls.size() > 0) { 1721 ArrayList<String> newVal = null; 1722 for (final String s : connectionInitSqls) { 1723 if (s != null && s.trim().length() > 0) { 1724 if (newVal == null) { 1725 newVal = new ArrayList<>(); 1726 } 1727 newVal.add(s); 1728 } 1729 } 1730 this.connectionInitSqls = newVal; 1731 } else { 1732 this.connectionInitSqls = null; 1733 } 1734 } 1735 1736 // ----------------------------------------------------- DataSource Methods 1737 1738 /** 1739 * Sets the connection properties passed to driver.connect(...). 1740 * <p> 1741 * Format of the string must be [propertyName=property;]* 1742 * </p> 1743 * <p> 1744 * NOTE - The "user" and "password" properties will be added explicitly, so they do not need to be included here. 1745 * </p> 1746 * 1747 * @param connectionProperties 1748 * the connection properties used to create new connections 1749 */ 1750 public void setConnectionProperties(final String connectionProperties) { 1751 Objects.requireNonNull(connectionProperties, "connectionProperties is null"); 1752 final String[] entries = connectionProperties.split(";"); 1753 final Properties properties = new Properties(); 1754 for (final String entry : entries) { 1755 if (entry.length() > 0) { 1756 final int index = entry.indexOf('='); 1757 if (index > 0) { 1758 final String name = entry.substring(0, index); 1759 final String value = entry.substring(index + 1); 1760 properties.setProperty(name, value); 1761 } else { 1762 // no value is empty string which is how java.util.Properties works 1763 properties.setProperty(entry, ""); 1764 } 1765 } 1766 } 1767 this.connectionProperties = properties; 1768 } 1769 1770 /** 1771 * <p> 1772 * Sets default auto-commit state of connections returned by this datasource. 1773 * </p> 1774 * <p> 1775 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1776 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1777 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1778 * </p> 1779 * 1780 * @param defaultAutoCommit 1781 * default auto-commit value 1782 */ 1783 public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { 1784 this.defaultAutoCommit = defaultAutoCommit; 1785 } 1786 1787 /** 1788 * <p> 1789 * Sets the default catalog. 1790 * </p> 1791 * <p> 1792 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1793 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1794 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1795 * </p> 1796 * 1797 * @param defaultCatalog 1798 * the default catalog 1799 */ 1800 public void setDefaultCatalog(final String defaultCatalog) { 1801 if (defaultCatalog != null && defaultCatalog.trim().length() > 0) { 1802 this.defaultCatalog = defaultCatalog; 1803 } else { 1804 this.defaultCatalog = null; 1805 } 1806 } 1807 1808 /** 1809 * Sets the default query timeout that will be used for {@link java.sql.Statement Statement}s created from this 1810 * connection. <code>null</code> means that the driver default will be used. 1811 * 1812 * @param defaultQueryTimeoutSeconds 1813 * The default query timeout in seconds. 1814 */ 1815 public void setDefaultQueryTimeout(final Integer defaultQueryTimeoutSeconds) { 1816 this.defaultQueryTimeoutSeconds = defaultQueryTimeoutSeconds; 1817 } 1818 1819 /** 1820 * <p> 1821 * Sets defaultReadonly property. 1822 * </p> 1823 * <p> 1824 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1825 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1826 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1827 * </p> 1828 * 1829 * @param defaultReadOnly 1830 * default read-only value 1831 */ 1832 public void setDefaultReadOnly(final Boolean defaultReadOnly) { 1833 this.defaultReadOnly = defaultReadOnly; 1834 } 1835 1836 /** 1837 * <p> 1838 * Sets the default schema. 1839 * </p> 1840 * <p> 1841 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1842 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1843 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1844 * </p> 1845 * 1846 * @param defaultSchema 1847 * the default catalog 1848 * @since 2.5.0 1849 */ 1850 public void setDefaultSchema(final String defaultSchema) { 1851 if (defaultSchema != null && defaultSchema.trim().length() > 0) { 1852 this.defaultSchema = defaultSchema; 1853 } else { 1854 this.defaultSchema = null; 1855 } 1856 } 1857 1858 /** 1859 * <p> 1860 * Sets the default transaction isolation state for returned connections. 1861 * </p> 1862 * <p> 1863 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1864 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1865 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1866 * </p> 1867 * 1868 * @param defaultTransactionIsolation 1869 * the default transaction isolation state 1870 * @see Connection#getTransactionIsolation 1871 */ 1872 public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { 1873 this.defaultTransactionIsolation = defaultTransactionIsolation; 1874 } 1875 1876 /** 1877 * Sets the SQL_STATE codes considered to signal fatal conditions. 1878 * <p> 1879 * Overrides the defaults in {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with 1880 * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()} 1881 * is {@code true}, whenever connections created by this datasource generate exceptions with SQL_STATE codes in this 1882 * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at 1883 * isValid or validation query). 1884 * </p> 1885 * <p> 1886 * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect. 1887 * </p> 1888 * <p> 1889 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1890 * time one of the following methods is invoked: {@code getConnection, setLogwriter, 1891 * setLoginTimeout, getLoginTimeout, getLogWriter}. 1892 * </p> 1893 * 1894 * @param disconnectionSqlCodes 1895 * SQL_STATE codes considered to signal fatal conditions 1896 * @since 2.1 1897 */ 1898 public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { 1899 if (disconnectionSqlCodes != null && disconnectionSqlCodes.size() > 0) { 1900 HashSet<String> newVal = null; 1901 for (final String s : disconnectionSqlCodes) { 1902 if (s != null && s.trim().length() > 0) { 1903 if (newVal == null) { 1904 newVal = new HashSet<>(); 1905 } 1906 newVal.add(s); 1907 } 1908 } 1909 this.disconnectionSqlCodes = newVal; 1910 } else { 1911 this.disconnectionSqlCodes = null; 1912 } 1913 } 1914 1915 /** 1916 * Sets the JDBC Driver instance to use for this pool. 1917 * <p> 1918 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1919 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1920 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1921 * </p> 1922 * 1923 * @param driver 1924 * The JDBC Driver instance to use for this pool. 1925 */ 1926 public synchronized void setDriver(final Driver driver) { 1927 this.driver = driver; 1928 } 1929 1930 /** 1931 * <p> 1932 * Sets the class loader to be used to load the JDBC driver. 1933 * </p> 1934 * <p> 1935 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1936 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1937 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1938 * </p> 1939 * 1940 * @param driverClassLoader 1941 * the class loader with which to load the JDBC driver 1942 */ 1943 public synchronized void setDriverClassLoader(final ClassLoader driverClassLoader) { 1944 this.driverClassLoader = driverClassLoader; 1945 } 1946 1947 /** 1948 * <p> 1949 * Sets the JDBC driver class name. 1950 * </p> 1951 * <p> 1952 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 1953 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 1954 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 1955 * </p> 1956 * 1957 * @param driverClassName 1958 * the class name of the JDBC driver 1959 */ 1960 public synchronized void setDriverClassName(final String driverClassName) { 1961 if (driverClassName != null && driverClassName.trim().length() > 0) { 1962 this.driverClassName = driverClassName; 1963 } else { 1964 this.driverClassName = null; 1965 } 1966 } 1967 1968 /** 1969 * Sets the value of the flag that controls whether or not connections being returned to the pool will be checked 1970 * and configured with {@link Connection#setAutoCommit(boolean) Connection.setAutoCommit(true)} if the auto commit 1971 * setting is {@code false} when the connection is returned. It is <code>true</code> by default. 1972 * 1973 * @param autoCommitOnReturn 1974 * Whether or not connections being returned to the pool will be checked and configured with auto-commit. 1975 * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. 1976 */ 1977 @Deprecated 1978 public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) { 1979 this.autoCommitOnReturn = autoCommitOnReturn; 1980 } 1981 1982 /** 1983 * Sets the EvictionPolicy implementation to use with this connection pool. 1984 * 1985 * @param evictionPolicyClassName 1986 * The fully qualified class name of the EvictionPolicy implementation 1987 */ 1988 public synchronized void setEvictionPolicyClassName(final String evictionPolicyClassName) { 1989 if (connectionPool != null) { 1990 connectionPool.setEvictionPolicyClassName(evictionPolicyClassName); 1991 } 1992 this.evictionPolicyClassName = evictionPolicyClassName; 1993 } 1994 1995 /** 1996 * @see #getFastFailValidation() 1997 * @param fastFailValidation 1998 * true means connections created by this factory will fast fail validation 1999 * @since 2.1 2000 */ 2001 public void setFastFailValidation(final boolean fastFailValidation) { 2002 this.fastFailValidation = fastFailValidation; 2003 } 2004 2005 /** 2006 * <p> 2007 * Sets the initial size of the connection pool. 2008 * </p> 2009 * <p> 2010 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2011 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2012 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2013 * </p> 2014 * 2015 * @param initialSize 2016 * the number of connections created when the pool is initialized 2017 */ 2018 public synchronized void setInitialSize(final int initialSize) { 2019 this.initialSize = initialSize; 2020 } 2021 2022 /** 2023 * Sets the JMX name that has been requested for this DataSource. If the requested name is not valid, an alternative 2024 * may be chosen. This DataSource will attempt to register itself using this name. If another component registers 2025 * this DataSource with JMX and this name is valid this name will be used in preference to any specified by the 2026 * other component. 2027 * 2028 * @param jmxName 2029 * The JMX name that has been requested for this DataSource 2030 */ 2031 public void setJmxName(final String jmxName) { 2032 this.jmxName = jmxName; 2033 } 2034 2035 /** 2036 * Sets the LIFO property. True means the pool behaves as a LIFO queue; false means FIFO. 2037 * 2038 * @param lifo 2039 * the new value for the LIFO property 2040 */ 2041 public synchronized void setLifo(final boolean lifo) { 2042 this.lifo = lifo; 2043 if (connectionPool != null) { 2044 connectionPool.setLifo(lifo); 2045 } 2046 } 2047 2048 /** 2049 * @param logAbandoned 2050 * new logAbandoned property value 2051 */ 2052 public void setLogAbandoned(final boolean logAbandoned) { 2053 if (abandonedConfig == null) { 2054 abandonedConfig = new AbandonedConfig(); 2055 } 2056 abandonedConfig.setLogAbandoned(logAbandoned); 2057 final GenericObjectPool<?> gop = this.connectionPool; 2058 if (gop != null) { 2059 gop.setAbandonedConfig(abandonedConfig); 2060 } 2061 } 2062 2063 /** 2064 * When {@link #getMaxConnLifetimeMillis()} is set to limit connection lifetime, this property determines whether or 2065 * not log messages are generated when the pool closes connections due to maximum lifetime exceeded. Set this 2066 * property to false to suppress log messages when connections expire. 2067 * 2068 * @param logExpiredConnections 2069 * Whether or not log messages are generated when the pool closes connections due to maximum lifetime 2070 * exceeded. 2071 */ 2072 public void setLogExpiredConnections(final boolean logExpiredConnections) { 2073 this.logExpiredConnections = logExpiredConnections; 2074 } 2075 2076 /** 2077 * <strong>BasicDataSource does NOT support this method. </strong> 2078 * 2079 * <p> 2080 * Set the login timeout (in seconds) for connecting to the database. 2081 * </p> 2082 * <p> 2083 * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. 2084 * </p> 2085 * 2086 * @param loginTimeout 2087 * The new login timeout, or zero for no timeout 2088 * @throws UnsupportedOperationException 2089 * If the DataSource implementation does not support the login timeout feature. 2090 * @throws SQLException 2091 * if a database access error occurs 2092 */ 2093 @Override 2094 public void setLoginTimeout(final int loginTimeout) throws SQLException { 2095 // This method isn't supported by the PoolingDataSource returned by the createDataSource 2096 throw new UnsupportedOperationException("Not supported by BasicDataSource"); 2097 } 2098 2099 /** 2100 * <p> 2101 * Sets the log writer being used by this data source. 2102 * </p> 2103 * <p> 2104 * Calls {@link #createDataSource()}, so has the side effect of initializing the connection pool. 2105 * </p> 2106 * 2107 * @param logWriter 2108 * The new log writer 2109 * @throws SQLException 2110 * if a database access error occurs 2111 */ 2112 @Override 2113 public void setLogWriter(final PrintWriter logWriter) throws SQLException { 2114 createDataSource().setLogWriter(logWriter); 2115 this.logWriter = logWriter; 2116 } 2117 2118 /** 2119 * <p> 2120 * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an 2121 * infinite lifetime. 2122 * </p> 2123 * <p> 2124 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2125 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2126 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2127 * </p> 2128 * 2129 * @param maxConnLifetimeMillis 2130 * The maximum permitted lifetime of a connection in milliseconds. 2131 */ 2132 public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { 2133 this.maxConnLifetimeMillis = maxConnLifetimeMillis; 2134 } 2135 2136 /** 2137 * Sets the maximum number of connections that can remain idle in the pool. Excess idle connections are destroyed on 2138 * return to the pool. 2139 * 2140 * @see #getMaxIdle() 2141 * @param maxIdle 2142 * the new value for maxIdle 2143 */ 2144 public synchronized void setMaxIdle(final int maxIdle) { 2145 this.maxIdle = maxIdle; 2146 if (connectionPool != null) { 2147 connectionPool.setMaxIdle(maxIdle); 2148 } 2149 } 2150 2151 /** 2152 * <p> 2153 * Sets the value of the <code>maxOpenPreparedStatements</code> property. 2154 * </p> 2155 * <p> 2156 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2157 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2158 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2159 * </p> 2160 * 2161 * @param maxOpenStatements 2162 * the new maximum number of prepared statements 2163 */ 2164 public synchronized void setMaxOpenPreparedStatements(final int maxOpenStatements) { 2165 this.maxOpenPreparedStatements = maxOpenStatements; 2166 } 2167 2168 /** 2169 * Sets the maximum total number of idle and borrows connections that can be active at the same time. Use a negative 2170 * value for no limit. 2171 * 2172 * @param maxTotal 2173 * the new value for maxTotal 2174 * @see #getMaxTotal() 2175 */ 2176 public synchronized void setMaxTotal(final int maxTotal) { 2177 this.maxTotal = maxTotal; 2178 if (connectionPool != null) { 2179 connectionPool.setMaxTotal(maxTotal); 2180 } 2181 } 2182 2183 /** 2184 * Sets the MaxWaitMillis property. Use -1 to make the pool wait indefinitely. 2185 * 2186 * @param maxWaitMillis 2187 * the new value for MaxWaitMillis 2188 * @see #getMaxWaitMillis() 2189 */ 2190 public synchronized void setMaxWaitMillis(final long maxWaitMillis) { 2191 this.maxWaitMillis = maxWaitMillis; 2192 if (connectionPool != null) { 2193 connectionPool.setMaxWaitMillis(maxWaitMillis); 2194 } 2195 } 2196 2197 /** 2198 * Sets the {@link #minEvictableIdleTimeMillis} property. 2199 * 2200 * @param minEvictableIdleTimeMillis 2201 * the minimum amount of time an object may sit idle in the pool 2202 * @see #minEvictableIdleTimeMillis 2203 */ 2204 public synchronized void setMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { 2205 this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 2206 if (connectionPool != null) { 2207 connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 2208 } 2209 } 2210 2211 /** 2212 * Sets the minimum number of idle connections in the pool. The pool attempts to ensure that minIdle connections are 2213 * available when the idle object evictor runs. The value of this property has no effect unless 2214 * {@link #timeBetweenEvictionRunsMillis} has a positive value. 2215 * 2216 * @param minIdle 2217 * the new value for minIdle 2218 * @see GenericObjectPool#setMinIdle(int) 2219 */ 2220 public synchronized void setMinIdle(final int minIdle) { 2221 this.minIdle = minIdle; 2222 if (connectionPool != null) { 2223 connectionPool.setMinIdle(minIdle); 2224 } 2225 } 2226 2227 /** 2228 * Sets the value of the {@link #numTestsPerEvictionRun} property. 2229 * 2230 * @param numTestsPerEvictionRun 2231 * the new {@link #numTestsPerEvictionRun} value 2232 * @see #numTestsPerEvictionRun 2233 */ 2234 public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { 2235 this.numTestsPerEvictionRun = numTestsPerEvictionRun; 2236 if (connectionPool != null) { 2237 connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); 2238 } 2239 } 2240 2241 // ------------------------------------------------------ Protected Methods 2242 2243 /** 2244 * <p> 2245 * Sets the {@link #password}. 2246 * </p> 2247 * <p> 2248 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2249 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2250 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2251 * </p> 2252 * 2253 * @param password 2254 * new value for the password 2255 */ 2256 public void setPassword(final String password) { 2257 this.password = password; 2258 } 2259 2260 /** 2261 * <p> 2262 * Sets whether to pool statements or not. 2263 * </p> 2264 * <p> 2265 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2266 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2267 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2268 * </p> 2269 * 2270 * @param poolingStatements 2271 * pooling on or off 2272 */ 2273 public synchronized void setPoolPreparedStatements(final boolean poolingStatements) { 2274 this.poolPreparedStatements = poolingStatements; 2275 } 2276 2277 /** 2278 * @param removeAbandonedOnBorrow 2279 * true means abandoned connections may be removed when connections are borrowed from the pool. 2280 * @see #getRemoveAbandonedOnBorrow() 2281 */ 2282 public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { 2283 if (abandonedConfig == null) { 2284 abandonedConfig = new AbandonedConfig(); 2285 } 2286 abandonedConfig.setRemoveAbandonedOnBorrow(removeAbandonedOnBorrow); 2287 final GenericObjectPool<?> gop = this.connectionPool; 2288 if (gop != null) { 2289 gop.setAbandonedConfig(abandonedConfig); 2290 } 2291 } 2292 2293 /** 2294 * @param removeAbandonedOnMaintenance 2295 * true means abandoned connections may be removed on pool maintenance. 2296 * @see #getRemoveAbandonedOnMaintenance() 2297 */ 2298 public void setRemoveAbandonedOnMaintenance(final boolean removeAbandonedOnMaintenance) { 2299 if (abandonedConfig == null) { 2300 abandonedConfig = new AbandonedConfig(); 2301 } 2302 abandonedConfig.setRemoveAbandonedOnMaintenance(removeAbandonedOnMaintenance); 2303 final GenericObjectPool<?> gop = this.connectionPool; 2304 if (gop != null) { 2305 gop.setAbandonedConfig(abandonedConfig); 2306 } 2307 } 2308 2309 /** 2310 * <p> 2311 * Sets the timeout in seconds before an abandoned connection can be removed. 2312 * </p> 2313 * 2314 * <p> 2315 * Setting this property has no effect if {@link #getRemoveAbandonedOnBorrow()} and 2316 * {@link #getRemoveAbandonedOnMaintenance()} are false. 2317 * </p> 2318 * 2319 * @param removeAbandonedTimeout 2320 * new abandoned timeout in seconds 2321 * @see #getRemoveAbandonedTimeout() 2322 * @see #getRemoveAbandonedOnBorrow() 2323 * @see #getRemoveAbandonedOnMaintenance() 2324 */ 2325 public void setRemoveAbandonedTimeout(final int removeAbandonedTimeout) { 2326 if (abandonedConfig == null) { 2327 abandonedConfig = new AbandonedConfig(); 2328 } 2329 abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout); 2330 final GenericObjectPool<?> gop = this.connectionPool; 2331 if (gop != null) { 2332 gop.setAbandonedConfig(abandonedConfig); 2333 } 2334 } 2335 2336 /** 2337 * Sets the flag that controls if a connection will be rolled back when it is returned to the pool if auto commit is 2338 * not enabled and the connection is not read only. 2339 * 2340 * @param rollbackOnReturn 2341 * whether a connection will be rolled back when it is returned to the pool. 2342 */ 2343 public void setRollbackOnReturn(final boolean rollbackOnReturn) { 2344 this.rollbackOnReturn = rollbackOnReturn; 2345 } 2346 2347 /** 2348 * Sets the minimum amount of time a connection may sit idle in the pool before it is eligible for eviction by the 2349 * idle object evictor, with the extra condition that at least "minIdle" connections remain in the pool. 2350 * 2351 * @param softMinEvictableIdleTimeMillis 2352 * minimum amount of time a connection may sit idle in the pool before it is eligible for eviction, 2353 * assuming there are minIdle idle connections in the pool. 2354 * @see #getSoftMinEvictableIdleTimeMillis 2355 */ 2356 public synchronized void setSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { 2357 this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; 2358 if (connectionPool != null) { 2359 connectionPool.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis); 2360 } 2361 } 2362 2363 /** 2364 * Sets the {@link #testOnBorrow} property. This property determines whether or not the pool will validate objects 2365 * before they are borrowed from the pool. 2366 * 2367 * @param testOnBorrow 2368 * new value for testOnBorrow property 2369 */ 2370 public synchronized void setTestOnBorrow(final boolean testOnBorrow) { 2371 this.testOnBorrow = testOnBorrow; 2372 if (connectionPool != null) { 2373 connectionPool.setTestOnBorrow(testOnBorrow); 2374 } 2375 } 2376 2377 /** 2378 * Sets the {@link #testOnCreate} property. This property determines whether or not the pool will validate objects 2379 * immediately after they are created by the pool 2380 * 2381 * @param testOnCreate 2382 * new value for testOnCreate property 2383 */ 2384 public synchronized void setTestOnCreate(final boolean testOnCreate) { 2385 this.testOnCreate = testOnCreate; 2386 if (connectionPool != null) { 2387 connectionPool.setTestOnCreate(testOnCreate); 2388 } 2389 } 2390 2391 /** 2392 * Sets the <code>testOnReturn</code> property. This property determines whether or not the pool will validate 2393 * objects before they are returned to the pool. 2394 * 2395 * @param testOnReturn 2396 * new value for testOnReturn property 2397 */ 2398 public synchronized void setTestOnReturn(final boolean testOnReturn) { 2399 this.testOnReturn = testOnReturn; 2400 if (connectionPool != null) { 2401 connectionPool.setTestOnReturn(testOnReturn); 2402 } 2403 } 2404 2405 /** 2406 * Sets the <code>testWhileIdle</code> property. This property determines whether or not the idle object evictor 2407 * will validate connections. 2408 * 2409 * @param testWhileIdle 2410 * new value for testWhileIdle property 2411 */ 2412 public synchronized void setTestWhileIdle(final boolean testWhileIdle) { 2413 this.testWhileIdle = testWhileIdle; 2414 if (connectionPool != null) { 2415 connectionPool.setTestWhileIdle(testWhileIdle); 2416 } 2417 } 2418 2419 /** 2420 * Sets the {@link #timeBetweenEvictionRunsMillis} property. 2421 * 2422 * @param timeBetweenEvictionRunsMillis 2423 * the new time between evictor runs 2424 * @see #timeBetweenEvictionRunsMillis 2425 */ 2426 public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { 2427 this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 2428 if (connectionPool != null) { 2429 connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 2430 } 2431 } 2432 2433 /** 2434 * <p> 2435 * Sets the {@link #url}. 2436 * </p> 2437 * <p> 2438 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2439 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2440 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2441 * </p> 2442 * 2443 * @param url 2444 * the new value for the JDBC connection url 2445 */ 2446 public synchronized void setUrl(final String url) { 2447 this.url = url; 2448 } 2449 2450 /** 2451 * <p> 2452 * Sets the {@link #userName}. 2453 * </p> 2454 * <p> 2455 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2456 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2457 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2458 * </p> 2459 * 2460 * @param userName 2461 * the new value for the JDBC connection user name 2462 */ 2463 public void setUsername(final String userName) { 2464 this.userName = userName; 2465 } 2466 2467 /** 2468 * <p> 2469 * Sets the {@link #validationQuery}. 2470 * </p> 2471 * <p> 2472 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2473 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2474 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2475 * </p> 2476 * 2477 * @param validationQuery 2478 * the new value for the validation query 2479 */ 2480 public void setValidationQuery(final String validationQuery) { 2481 if (validationQuery != null && validationQuery.trim().length() > 0) { 2482 this.validationQuery = validationQuery; 2483 } else { 2484 this.validationQuery = null; 2485 } 2486 } 2487 2488 /** 2489 * Sets the validation query timeout, the amount of time, in seconds, that connection validation will wait for a 2490 * response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout. 2491 * <p> 2492 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first 2493 * time one of the following methods is invoked: <code>getConnection, setLogwriter, 2494 * setLoginTimeout, getLoginTimeout, getLogWriter.</code> 2495 * </p> 2496 * 2497 * @param validationQueryTimeoutSeconds 2498 * new validation query timeout value in seconds 2499 */ 2500 public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { 2501 this.validationQueryTimeoutSeconds = validationQueryTimeoutSeconds; 2502 } 2503 2504 /** 2505 * Starts the connection pool maintenance task, if configured. 2506 */ 2507 protected void startPoolMaintenance() { 2508 if (connectionPool != null && timeBetweenEvictionRunsMillis > 0) { 2509 connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 2510 } 2511 } 2512 2513 @Override 2514 public <T> T unwrap(final Class<T> iface) throws SQLException { 2515 throw new SQLException("BasicDataSource is not a wrapper."); 2516 } 2517 2518 private void updateJmxName(final GenericObjectPoolConfig<?> config) { 2519 if (registeredJmxObjectName == null) { 2520 return; 2521 } 2522 final StringBuilder base = new StringBuilder(registeredJmxObjectName.toString()); 2523 base.append(Constants.JMX_CONNECTION_POOL_BASE_EXT); 2524 config.setJmxNameBase(base.toString()); 2525 config.setJmxNamePrefix(Constants.JMX_CONNECTION_POOL_PREFIX); 2526 } 2527}