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 * https://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.datasources; 018 019import java.io.OutputStreamWriter; 020import java.io.PrintWriter; 021import java.io.Serializable; 022import java.nio.charset.StandardCharsets; 023import java.sql.Connection; 024import java.sql.SQLException; 025import java.sql.SQLFeatureNotSupportedException; 026import java.time.Duration; 027import java.util.Properties; 028import java.util.logging.Logger; 029 030import javax.naming.Context; 031import javax.naming.InitialContext; 032import javax.naming.Referenceable; 033import javax.sql.ConnectionPoolDataSource; 034import javax.sql.DataSource; 035import javax.sql.PooledConnection; 036 037import org.apache.commons.dbcp2.Utils; 038import org.apache.commons.pool2.impl.BaseObjectPoolConfig; 039import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 040import org.apache.commons.pool2.impl.GenericObjectPool; 041 042/** 043 * <p> 044 * The base class for {@link SharedPoolDataSource} and {@link PerUserPoolDataSource}. Many of the 045 * configuration properties are shared and defined here. This class is declared public in order to allow particular 046 * usage with commons-beanutils; do not make direct use of it outside of <em>commons-dbcp2</em>. 047 * </p> 048 * 049 * <p> 050 * A J2EE container will normally provide some method of initializing the {@link DataSource} whose attributes are 051 * presented as bean getters/setters and then deploying it via JNDI. It is then available to an application as a source 052 * of pooled logical connections to the database. The pool needs a source of physical connections. This source is in the 053 * form of a {@link ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used 054 * to lookup the source via JNDI. 055 * </p> 056 * 057 * <p> 058 * Although normally used within a JNDI environment, A DataSource can be instantiated and initialized as any bean. In 059 * this case the {@link ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class 060 * allows the physical source of connections to be attached directly to this pool using the 061 * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method. 062 * </p> 063 * 064 * <p> 065 * The dbcp package contains an adapter, {@link org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS}, that can be 066 * used to allow the use of {@link DataSource}'s based on this class with JDBC driver implementations that do not 067 * supply a {@link ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation. 068 * </p> 069 * 070 * <p> 071 * The <a href="package-summary.html">package documentation</a> contains an example using Apache Tomcat and JNDI and it 072 * also contains a non-JNDI example. 073 * </p> 074 * 075 * @since 2.0 076 */ 077public abstract class InstanceKeyDataSource implements DataSource, Referenceable, Serializable, AutoCloseable { 078 079 private static final long serialVersionUID = -6819270431752240878L; 080 081 private static final String GET_CONNECTION_CALLED = "A Connection was already requested from this source, " 082 + "further initialization is not allowed."; 083 private static final String BAD_TRANSACTION_ISOLATION = "The requested TransactionIsolation level is invalid."; 084 085 /** 086 * Internal constant to indicate the level is not set. 087 */ 088 protected static final int UNKNOWN_TRANSACTIONISOLATION = -1; 089 090 /** Guards property setters - once true, setters throw IllegalStateException */ 091 private volatile boolean getConnectionCalled; 092 093 /** Underlying source of PooledConnections */ 094 private ConnectionPoolDataSource dataSource; 095 096 /** DataSource Name used to find the ConnectionPoolDataSource */ 097 private String dataSourceName; 098 099 /** Description */ 100 private String description; 101 102 /** Environment that may be used to set up a JNDI initial context. */ 103 private Properties jndiEnvironment; 104 105 /** Login Timeout */ 106 private Duration loginTimeoutDuration = Duration.ZERO; 107 108 /** Log stream */ 109 private PrintWriter logWriter; 110 111 /** Instance key */ 112 private String instanceKey; 113 114 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_BLOCK_WHEN_EXHAUSTED}. */ 115 private volatile boolean defaultBlockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; 116 117 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_EVICTION_POLICY_CLASS_NAME}. */ 118 private String defaultEvictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; 119 120 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_LIFO}. */ 121 private volatile boolean defaultLifo = BaseObjectPoolConfig.DEFAULT_LIFO; 122 123 /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_IDLE_PER_KEY}. */ 124 private volatile int defaultMaxIdle = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; 125 126 /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}. */ 127 private volatile int defaultMaxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; 128 129 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_MAX_WAIT}. */ 130 private Duration defaultMaxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT; 131 132 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_MIN_EVICTABLE_IDLE_DURATION}. */ 133 private Duration defaultMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; 134 135 /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MIN_IDLE_PER_KEY}. */ 136 private volatile int defaultMinIdle = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; 137 138 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_NUM_TESTS_PER_EVICTION_RUN}. */ 139 private volatile int defaultNumTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 140 141 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION}. */ 142 private Duration defaultSoftMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; 143 144 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_CREATE}. */ 145 private volatile boolean defaultTestOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE; 146 147 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_BORROW}. */ 148 private volatile boolean defaultTestOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; 149 150 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_RETURN}. */ 151 private volatile boolean defaultTestOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; 152 153 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_WHILE_IDLE}. */ 154 private volatile boolean defaultTestWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; 155 156 /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_DURATION_BETWEEN_EVICTION_RUNS}. */ 157 private Duration defaultDurationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; 158 159 /** Connection factory property defaults to null. */ 160 private String validationQuery; 161 162 /** Connection factory property defaults to -1 seconds. */ 163 private Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); 164 165 /** Connection factory property defaults to false. */ 166 private volatile boolean rollbackAfterValidation; 167 168 /** Connection factory property defaults to -1 milliseconds. */ 169 private Duration maxConnDuration = Duration.ofMillis(-1); 170 171 /** Connection property defaults to false. */ 172 private Boolean defaultAutoCommit; 173 174 /** Connection property defaults to {@link #UNKNOWN_TRANSACTIONISOLATION}. */ 175 private volatile int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; 176 177 /** Connection property defaults to false. */ 178 private Boolean defaultReadOnly; 179 180 /** 181 * Default no-arg constructor for Serialization. 182 */ 183 public InstanceKeyDataSource() { 184 } 185 186 /** 187 * Throws an IllegalStateException, if a PooledConnection has already been requested. 188 * 189 * @throws IllegalStateException Thrown if a PooledConnection has already been requested. 190 */ 191 protected void assertInitializationAllowed() throws IllegalStateException { 192 if (getConnectionCalled) { 193 throw new IllegalStateException(GET_CONNECTION_CALLED); 194 } 195 } 196 197 /** 198 * Closes the connection pool being maintained by this datasource. 199 */ 200 @Override 201 public abstract void close() throws SQLException; 202 203 private void closeDueToException(final PooledConnectionAndInfo info) { 204 if (info != null) { 205 try { 206 info.getPooledConnection().getConnection().close(); 207 } catch (final Exception e) { 208 // do not throw this exception because we are in the middle 209 // of handling another exception. But record it because 210 // it potentially leaks connections from the pool. 211 getLogWriter().println("[ERROR] Could not return connection to pool during exception handling. " + e.getMessage()); 212 } 213 } 214 } 215 216 /** 217 * Attempts to establish a database connection. 218 */ 219 @Override 220 public Connection getConnection() throws SQLException { 221 return getConnection(null, null); 222 } 223 224 /** 225 * Attempts to retrieve a database connection using {@link #getPooledConnectionAndInfo(String, String)} with the 226 * provided user name and password. The password on the {@code PooledConnectionAndInfo} instance returned by 227 * {@code getPooledConnectionAndInfo} is compared to the {@code password} parameter. If the comparison 228 * fails, a database connection using the supplied user name and password is attempted. If the connection attempt 229 * fails, an SQLException is thrown, indicating that the given password did not match the password used to create 230 * the pooled connection. If the connection attempt succeeds, this means that the database password has been 231 * changed. In this case, the {@code PooledConnectionAndInfo} instance retrieved with the old password is 232 * destroyed and the {@code getPooledConnectionAndInfo} is repeatedly invoked until a 233 * {@code PooledConnectionAndInfo} instance with the new password is returned. 234 */ 235 @Override 236 public Connection getConnection(final String userName, final String userPassword) throws SQLException { 237 if (instanceKey == null) { 238 throw new SQLException("Must set the ConnectionPoolDataSource " 239 + "through setDataSourceName or setConnectionPoolDataSource before calling getConnection."); 240 } 241 getConnectionCalled = true; 242 PooledConnectionAndInfo info = null; 243 try { 244 info = getPooledConnectionAndInfo(userName, userPassword); 245 } catch (final RuntimeException | SQLException e) { 246 closeDueToException(info); 247 throw e; 248 } catch (final Exception e) { 249 closeDueToException(info); 250 throw new SQLException("Cannot borrow connection from pool", e); 251 } 252 253 // Password on PooledConnectionAndInfo does not match 254 if (!(null == userPassword ? null == info.getPassword() : userPassword.equals(info.getPassword()))) { 255 try { // See if password has changed by attempting connection 256 testCPDS(userName, userPassword); 257 } catch (final SQLException ex) { 258 // Password has not changed, so refuse client, but return connection to the pool 259 closeDueToException(info); 260 throw new SQLException( 261 "Given password did not match password used to create the PooledConnection.", ex); 262 } catch (final javax.naming.NamingException ne) { 263 throw new SQLException("NamingException encountered connecting to database", ne); 264 } 265 /* 266 * Password must have changed -> destroy connection and keep retrying until we get a new, good one, 267 * destroying any idle connections with the old password as we pull them from the pool. 268 */ 269 final UserPassKey upkey = info.getUserPassKey(); 270 final PooledConnectionManager manager = getConnectionManager(upkey); 271 // Destroy and remove from pool 272 manager.invalidate(info.getPooledConnection()); 273 // Reset the password on the factory if using CPDSConnectionFactory 274 manager.setPassword(upkey.getPasswordCharArray()); 275 info = null; 276 for (int i = 0; i < 10; i++) { // Bound the number of retries - only needed if bad instances return 277 try { 278 info = getPooledConnectionAndInfo(userName, userPassword); 279 } catch (final RuntimeException | SQLException e) { 280 closeDueToException(info); 281 throw e; 282 } catch (final Exception e) { 283 closeDueToException(info); 284 throw new SQLException("Cannot borrow connection from pool", e); 285 } 286 if (info != null && userPassword != null && userPassword.equals(info.getPassword())) { 287 break; 288 } 289 if (info != null) { 290 manager.invalidate(info.getPooledConnection()); 291 } 292 info = null; 293 } 294 if (info == null) { 295 throw new SQLException("Cannot borrow connection from pool - password change failure."); 296 } 297 } 298 299 final Connection connection = info.getPooledConnection().getConnection(); 300 try { 301 setupDefaults(connection, userName); 302 connection.clearWarnings(); 303 return connection; 304 } catch (final SQLException ex) { 305 Utils.close(connection, e -> getLogWriter().println("ignoring exception during close: " + e)); 306 throw ex; 307 } 308 } 309 310 /** 311 * Gets the pooled connection manager for the given key. 312 * 313 * @param upkey the key. 314 * @return the pooled connection manager for the given key. 315 */ 316 protected abstract PooledConnectionManager getConnectionManager(UserPassKey upkey); 317 318 /** 319 * Gets the value of connectionPoolDataSource. This method will return null, if the backing data source is being 320 * accessed via JNDI. 321 * 322 * @return value of connectionPoolDataSource. 323 */ 324 public ConnectionPoolDataSource getConnectionPoolDataSource() { 325 return dataSource; 326 } 327 328 /** 329 * Gets the name of the ConnectionPoolDataSource which backs this pool. This name is used to look up the data source 330 * from a JNDI service provider. 331 * 332 * @return value of dataSourceName. 333 */ 334 public String getDataSourceName() { 335 return dataSourceName; 336 } 337 338 /** 339 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user pool. 340 * 341 * @return The default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user 342 * pool. 343 */ 344 public boolean getDefaultBlockWhenExhausted() { 345 return this.defaultBlockWhenExhausted; 346 } 347 348 /** 349 * Gets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. 350 * 351 * @return The default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. 352 * @since 2.10.0 353 */ 354 public Duration getDefaultDurationBetweenEvictionRuns() { 355 return this.defaultDurationBetweenEvictionRuns; 356 } 357 358 /** 359 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user 360 * pool. 361 * 362 * @return The default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user 363 * pool. 364 */ 365 public String getDefaultEvictionPolicyClassName() { 366 return this.defaultEvictionPolicyClassName; 367 } 368 369 /** 370 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. 371 * 372 * @return The default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. 373 */ 374 public boolean getDefaultLifo() { 375 return this.defaultLifo; 376 } 377 378 /** 379 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. 380 * 381 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. 382 */ 383 public int getDefaultMaxIdle() { 384 return this.defaultMaxIdle; 385 } 386 387 /** 388 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. 389 * 390 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. 391 */ 392 public int getDefaultMaxTotal() { 393 return this.defaultMaxTotal; 394 } 395 396 /** 397 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 398 * 399 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 400 * @since 2.9.0 401 */ 402 public Duration getDefaultMaxWait() { 403 return this.defaultMaxWaitDuration; 404 } 405 406 /** 407 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 408 * 409 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 410 * @deprecated Use {@link #getDefaultMaxWait()}. 411 */ 412 @Deprecated 413 public long getDefaultMaxWaitMillis() { 414 return getDefaultMaxWait().toMillis(); 415 } 416 417 /** 418 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user 419 * pool. 420 * 421 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per 422 * user pool. 423 * @since 2.10.0 424 */ 425 public Duration getDefaultMinEvictableIdleDuration() { 426 return this.defaultMinEvictableIdleDuration; 427 } 428 429 /** 430 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user 431 * pool. 432 * 433 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per 434 * user pool. 435 * @deprecated Use {@link #getDefaultMinEvictableIdleDuration()}. 436 */ 437 @Deprecated 438 public long getDefaultMinEvictableIdleTimeMillis() { 439 return this.defaultMinEvictableIdleDuration.toMillis(); 440 } 441 442 /** 443 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. 444 * 445 * @return The default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. 446 */ 447 public int getDefaultMinIdle() { 448 return this.defaultMinIdle; 449 } 450 451 /** 452 * Gets the default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user 453 * pool. 454 * 455 * @return The default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user 456 * pool. 457 */ 458 public int getDefaultNumTestsPerEvictionRun() { 459 return this.defaultNumTestsPerEvictionRun; 460 } 461 462 /** 463 * Gets the default value for {@link 464 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 465 * 466 * @return The default value for {@link 467 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 468 * @since 2.10.0 469 */ 470 public Duration getDefaultSoftMinEvictableIdleDuration() { 471 return this.defaultSoftMinEvictableIdleDuration; 472 } 473 474 /** 475 * Gets the default value for {@link 476 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 477 * 478 * @return The default value for {@link 479 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 480 * @deprecated Use {@link #getDefaultSoftMinEvictableIdleDuration()}. 481 */ 482 @Deprecated 483 public long getDefaultSoftMinEvictableIdleTimeMillis() { 484 return this.defaultSoftMinEvictableIdleDuration.toMillis(); 485 } 486 487 /** 488 * Gets the default value for {@link 489 * GenericObjectPool#getTestOnBorrow()} for each per user pool. 490 * 491 * @return The default value for {@link 492 * GenericObjectPool#getTestOnBorrow()} for each per user pool. 493 */ 494 public boolean getDefaultTestOnBorrow() { 495 return this.defaultTestOnBorrow; 496 } 497 498 /** 499 * Gets the default value for {@link 500 * GenericObjectPool#getTestOnCreate()} for each per user pool. 501 * 502 * @return The default value for {@link 503 * GenericObjectPool#getTestOnCreate()} for each per user pool. 504 */ 505 public boolean getDefaultTestOnCreate() { 506 return this.defaultTestOnCreate; 507 } 508 509 /** 510 * Gets the default value for {@link 511 * GenericObjectPool#getTestOnReturn()} for each per user pool. 512 * 513 * @return The default value for {@link 514 * GenericObjectPool#getTestOnReturn()} for each per user pool. 515 */ 516 public boolean getDefaultTestOnReturn() { 517 return this.defaultTestOnReturn; 518 } 519 520 /** 521 * Gets the default value for {@link 522 * GenericObjectPool#getTestWhileIdle()} for each per user pool. 523 * 524 * @return The default value for {@link 525 * GenericObjectPool#getTestWhileIdle()} for each per user pool. 526 */ 527 public boolean getDefaultTestWhileIdle() { 528 return this.defaultTestWhileIdle; 529 } 530 531 /** 532 * Gets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. 533 * 534 * @return The default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. 535 * @deprecated Use {@link #getDefaultDurationBetweenEvictionRuns()}. 536 */ 537 @Deprecated 538 public long getDefaultTimeBetweenEvictionRunsMillis() { 539 return this.defaultDurationBetweenEvictionRuns.toMillis(); 540 } 541 542 /** 543 * Gets the value of defaultTransactionIsolation, which defines the state of connections handed out from this pool. 544 * The value can be changed on the Connection using Connection.setTransactionIsolation(int). If this method returns 545 * -1, the default is JDBC driver dependent. 546 * 547 * @return value of defaultTransactionIsolation. 548 */ 549 public int getDefaultTransactionIsolation() { 550 return defaultTransactionIsolation; 551 } 552 553 /** 554 * Gets the description. This property is defined by JDBC as for use with GUI (or other) tools that might deploy the 555 * datasource. It serves no internal purpose. 556 * 557 * @return value of description. 558 */ 559 public String getDescription() { 560 return description; 561 } 562 563 /** 564 * Gets the instance key. 565 * 566 * @return the instance key. 567 */ 568 protected String getInstanceKey() { 569 return instanceKey; 570 } 571 572 /** 573 * Gets the value of jndiEnvironment which is used when instantiating a JNDI InitialContext. This InitialContext is 574 * used to locate the back end ConnectionPoolDataSource. 575 * 576 * @param key 577 * JNDI environment key. 578 * @return value of jndiEnvironment. 579 */ 580 public String getJndiEnvironment(final String key) { 581 String value = null; 582 if (jndiEnvironment != null) { 583 value = jndiEnvironment.getProperty(key); 584 } 585 return value; 586 } 587 588 /** 589 * Gets the value of loginTimeout. 590 * 591 * @return value of loginTimeout. 592 * @deprecated Use {@link #getLoginTimeoutDuration()}. 593 */ 594 @Deprecated 595 @Override 596 public int getLoginTimeout() { 597 return (int) loginTimeoutDuration.getSeconds(); 598 } 599 600 /** 601 * Gets the value of loginTimeout. 602 * 603 * @return value of loginTimeout. 604 * @since 2.10.0 605 */ 606 public Duration getLoginTimeoutDuration() { 607 return loginTimeoutDuration; 608 } 609 610 /** 611 * Gets the value of logWriter. 612 * 613 * @return value of logWriter. 614 */ 615 @Override 616 public PrintWriter getLogWriter() { 617 if (logWriter == null) { 618 logWriter = new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)); 619 } 620 return logWriter; 621 } 622 623 /** 624 * Gets the maximum permitted lifetime of a connection. A value of zero or less indicates an 625 * infinite lifetime. 626 * 627 * @return The maximum permitted lifetime of a connection. A value of zero or less indicates an 628 * infinite lifetime. 629 * @since 2.10.0 630 */ 631 public Duration getMaxConnDuration() { 632 return maxConnDuration; 633 } 634 635 /** 636 * Gets the maximum permitted lifetime of a connection. A value of zero or less indicates an 637 * infinite lifetime. 638 * 639 * @return The maximum permitted lifetime of a connection. A value of zero or less indicates an 640 * infinite lifetime. 641 * @deprecated Use {@link #getMaxConnDuration()}. 642 */ 643 @Deprecated 644 public Duration getMaxConnLifetime() { 645 return maxConnDuration; 646 } 647 648 /** 649 * Gets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an 650 * infinite lifetime. 651 * 652 * @return The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an 653 * infinite lifetime. 654 * @deprecated Use {@link #getMaxConnLifetime()}. 655 */ 656 @Deprecated 657 public long getMaxConnLifetimeMillis() { 658 return maxConnDuration.toMillis(); 659 } 660 661 @Override 662 public Logger getParentLogger() throws SQLFeatureNotSupportedException { 663 throw new SQLFeatureNotSupportedException(); 664 } 665 666 /** 667 * This method is protected but can only be implemented in this package because PooledConnectionAndInfo is a package 668 * private type. 669 * 670 * @param userName The user name. 671 * @param userPassword The user password. 672 * @return Matching PooledConnectionAndInfo. 673 * @throws SQLException Connection or registration failure. 674 */ 675 protected abstract PooledConnectionAndInfo getPooledConnectionAndInfo(String userName, String userPassword) 676 throws SQLException; 677 678 /** 679 * Gets the SQL query that will be used to validate connections from this pool before returning them to the caller. 680 * If specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not 681 * specified, {@link Connection#isValid(int)} will be used to validate connections. 682 * 683 * @return The SQL query that will be used to validate connections from this pool before returning them to the 684 * caller. 685 */ 686 public String getValidationQuery() { 687 return this.validationQuery; 688 } 689 690 /** 691 * Returns the timeout in seconds before the validation query fails. 692 * 693 * @return The timeout in seconds before the validation query fails. 694 * @deprecated Use {@link #getValidationQueryTimeoutDuration()}. 695 */ 696 @Deprecated 697 public int getValidationQueryTimeout() { 698 return (int) validationQueryTimeoutDuration.getSeconds(); 699 } 700 701 /** 702 * Returns the timeout Duration before the validation query fails. 703 * 704 * @return The timeout Duration before the validation query fails. 705 */ 706 public Duration getValidationQueryTimeoutDuration() { 707 return validationQueryTimeoutDuration; 708 } 709 710 /** 711 * Gets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value 712 * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which 713 * will use the default value for the driver. 714 * 715 * @return value of defaultAutoCommit. 716 */ 717 public Boolean isDefaultAutoCommit() { 718 return defaultAutoCommit; 719 } 720 721 /** 722 * Gets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value 723 * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which 724 * will use the default value for the driver. 725 * 726 * @return value of defaultReadOnly. 727 */ 728 public Boolean isDefaultReadOnly() { 729 return defaultReadOnly; 730 } 731 732 /** 733 * Tests whether a rollback will be issued after executing the SQL query that will be used to validate connections from 734 * this pool before returning them to the caller. 735 * 736 * @return true if a rollback will be issued after executing the validation query 737 */ 738 public boolean isRollbackAfterValidation() { 739 return this.rollbackAfterValidation; 740 } 741 742 @Override 743 public boolean isWrapperFor(final Class<?> iface) throws SQLException { 744 return iface.isInstance(this); 745 } 746 747 /** 748 * Sets the back end ConnectionPoolDataSource. This property should not be set if using JNDI to access the 749 * data source. 750 * 751 * @param dataSource 752 * Value to assign to connectionPoolDataSource. 753 */ 754 public void setConnectionPoolDataSource(final ConnectionPoolDataSource dataSource) { 755 assertInitializationAllowed(); 756 if (dataSourceName != null) { 757 throw new IllegalStateException("Cannot set the DataSource, if JNDI is used."); 758 } 759 if (this.dataSource != null) { 760 throw new IllegalStateException("The CPDS has already been set. It cannot be altered."); 761 } 762 this.dataSource = dataSource; 763 instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); 764 } 765 766 /** 767 * Sets the name of the ConnectionPoolDataSource which backs this pool. This name is used to look up the data source 768 * from a JNDI service provider. 769 * 770 * @param dataSourceName 771 * Value to assign to dataSourceName. 772 */ 773 public void setDataSourceName(final String dataSourceName) { 774 assertInitializationAllowed(); 775 if (dataSource != null) { 776 throw new IllegalStateException("Cannot set the JNDI name for the DataSource, if already " 777 + "set using setConnectionPoolDataSource."); 778 } 779 if (this.dataSourceName != null) { 780 throw new IllegalStateException("The DataSourceName has already been set. It cannot be altered."); 781 } 782 this.dataSourceName = dataSourceName; 783 instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); 784 } 785 786 /** 787 * Sets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value 788 * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which 789 * will use the default value for the driver. 790 * 791 * @param defaultAutoCommit 792 * Value to assign to defaultAutoCommit. 793 */ 794 public void setDefaultAutoCommit(final Boolean defaultAutoCommit) { 795 assertInitializationAllowed(); 796 this.defaultAutoCommit = defaultAutoCommit; 797 } 798 799 /** 800 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user pool. 801 * 802 * @param blockWhenExhausted 803 * The default value for {@link GenericKeyedObjectPoolConfig#getBlockWhenExhausted()} for each per user 804 * pool. 805 */ 806 public void setDefaultBlockWhenExhausted(final boolean blockWhenExhausted) { 807 assertInitializationAllowed(); 808 this.defaultBlockWhenExhausted = blockWhenExhausted; 809 } 810 811 /** 812 * Sets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. 813 * 814 * @param defaultDurationBetweenEvictionRuns The default value for 815 * {@link GenericObjectPool#getDurationBetweenEvictionRuns ()} for each per user pool. 816 * @since 2.10.0 817 */ 818 public void setDefaultDurationBetweenEvictionRuns(final Duration defaultDurationBetweenEvictionRuns) { 819 assertInitializationAllowed(); 820 this.defaultDurationBetweenEvictionRuns = defaultDurationBetweenEvictionRuns; 821 } 822 823 /** 824 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per user 825 * pool. 826 * 827 * @param evictionPolicyClassName 828 * The default value for {@link GenericKeyedObjectPoolConfig#getEvictionPolicyClassName()} for each per 829 * user pool. 830 */ 831 public void setDefaultEvictionPolicyClassName(final String evictionPolicyClassName) { 832 assertInitializationAllowed(); 833 this.defaultEvictionPolicyClassName = evictionPolicyClassName; 834 } 835 836 /** 837 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. 838 * 839 * @param lifo 840 * The default value for {@link GenericKeyedObjectPoolConfig#getLifo()} for each per user pool. 841 */ 842 public void setDefaultLifo(final boolean lifo) { 843 assertInitializationAllowed(); 844 this.defaultLifo = lifo; 845 } 846 847 /** 848 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. 849 * 850 * @param maxIdle 851 * The default value for {@link GenericKeyedObjectPoolConfig#getMaxIdlePerKey()} for each per user pool. 852 */ 853 public void setDefaultMaxIdle(final int maxIdle) { 854 assertInitializationAllowed(); 855 this.defaultMaxIdle = maxIdle; 856 } 857 858 /** 859 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. 860 * 861 * @param maxTotal 862 * The default value for {@link GenericKeyedObjectPoolConfig#getMaxTotalPerKey()} for each per user pool. 863 */ 864 public void setDefaultMaxTotal(final int maxTotal) { 865 assertInitializationAllowed(); 866 this.defaultMaxTotal = maxTotal; 867 } 868 869 /** 870 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 871 * 872 * @param maxWaitMillis 873 * The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitDuration()} for each per user pool. 874 * @since 2.9.0 875 */ 876 public void setDefaultMaxWait(final Duration maxWaitMillis) { 877 assertInitializationAllowed(); 878 this.defaultMaxWaitDuration = maxWaitMillis; 879 } 880 881 /** 882 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. 883 * 884 * @param maxWaitMillis 885 * The default value for {@link GenericKeyedObjectPoolConfig#getMaxWaitMillis()} for each per user pool. 886 * @deprecated Use {@link #setDefaultMaxWait(Duration)}. 887 */ 888 @Deprecated 889 public void setDefaultMaxWaitMillis(final long maxWaitMillis) { 890 setDefaultMaxWait(Duration.ofMillis(maxWaitMillis)); 891 } 892 893 /** 894 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user 895 * pool. 896 * 897 * @param defaultMinEvictableIdleDuration 898 * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each 899 * per user pool. 900 * @since 2.10.0 901 */ 902 public void setDefaultMinEvictableIdle(final Duration defaultMinEvictableIdleDuration) { 903 assertInitializationAllowed(); 904 this.defaultMinEvictableIdleDuration = defaultMinEvictableIdleDuration; 905 } 906 907 /** 908 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each per user 909 * pool. 910 * 911 * @param minEvictableIdleTimeMillis 912 * The default value for {@link GenericKeyedObjectPoolConfig#getMinEvictableIdleDuration()} for each 913 * per user pool. 914 * @deprecated Use {@link #setDefaultMinEvictableIdle(Duration)}. 915 */ 916 @Deprecated 917 public void setDefaultMinEvictableIdleTimeMillis(final long minEvictableIdleTimeMillis) { 918 assertInitializationAllowed(); 919 this.defaultMinEvictableIdleDuration = Duration.ofMillis(minEvictableIdleTimeMillis); 920 } 921 922 /** 923 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. 924 * 925 * @param minIdle 926 * The default value for {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} for each per user pool. 927 */ 928 public void setDefaultMinIdle(final int minIdle) { 929 assertInitializationAllowed(); 930 this.defaultMinIdle = minIdle; 931 } 932 933 /** 934 * Sets the default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per user 935 * pool. 936 * 937 * @param numTestsPerEvictionRun 938 * The default value for {@link GenericKeyedObjectPoolConfig#getNumTestsPerEvictionRun()} for each per 939 * user pool. 940 */ 941 public void setDefaultNumTestsPerEvictionRun(final int numTestsPerEvictionRun) { 942 assertInitializationAllowed(); 943 this.defaultNumTestsPerEvictionRun = numTestsPerEvictionRun; 944 } 945 946 /** 947 * Sets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value 948 * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which 949 * will use the default value for the driver. 950 * 951 * @param defaultReadOnly 952 * Value to assign to defaultReadOnly. 953 */ 954 public void setDefaultReadOnly(final Boolean defaultReadOnly) { 955 assertInitializationAllowed(); 956 this.defaultReadOnly = defaultReadOnly; 957 } 958 959 /** 960 * Sets the default value for {@link 961 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 962 * 963 * @param defaultSoftMinEvictableIdleDuration 964 * The default value for {@link 965 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 966 * @since 2.10.0 967 */ 968 public void setDefaultSoftMinEvictableIdle(final Duration defaultSoftMinEvictableIdleDuration) { 969 assertInitializationAllowed(); 970 this.defaultSoftMinEvictableIdleDuration = defaultSoftMinEvictableIdleDuration; 971 } 972 973 /** 974 * Sets the default value for {@link 975 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 976 * 977 * @param softMinEvictableIdleTimeMillis 978 * The default value for {@link 979 * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. 980 * @deprecated Use {@link #setDefaultSoftMinEvictableIdle(Duration)}. 981 */ 982 @Deprecated 983 public void setDefaultSoftMinEvictableIdleTimeMillis(final long softMinEvictableIdleTimeMillis) { 984 assertInitializationAllowed(); 985 this.defaultSoftMinEvictableIdleDuration = Duration.ofMillis(softMinEvictableIdleTimeMillis); 986 } 987 988 /** 989 * Sets the default value for {@link 990 * GenericObjectPool#getTestOnBorrow()} for each per user pool. 991 * 992 * @param testOnBorrow 993 * The default value for {@link 994 * GenericObjectPool#getTestOnBorrow()} for each per user pool. 995 */ 996 public void setDefaultTestOnBorrow(final boolean testOnBorrow) { 997 assertInitializationAllowed(); 998 this.defaultTestOnBorrow = testOnBorrow; 999 } 1000 1001 /** 1002 * Sets the default value for {@link 1003 * GenericObjectPool#getTestOnCreate()} for each per user pool. 1004 * 1005 * @param testOnCreate 1006 * The default value for {@link 1007 * GenericObjectPool#getTestOnCreate()} for each per user pool. 1008 */ 1009 public void setDefaultTestOnCreate(final boolean testOnCreate) { 1010 assertInitializationAllowed(); 1011 this.defaultTestOnCreate = testOnCreate; 1012 } 1013 1014 /** 1015 * Sets the default value for {@link 1016 * GenericObjectPool#getTestOnReturn()} for each per user pool. 1017 * 1018 * @param testOnReturn 1019 * The default value for {@link 1020 * GenericObjectPool#getTestOnReturn()} for each per user pool. 1021 */ 1022 public void setDefaultTestOnReturn(final boolean testOnReturn) { 1023 assertInitializationAllowed(); 1024 this.defaultTestOnReturn = testOnReturn; 1025 } 1026 1027 /** 1028 * Sets the default value for {@link 1029 * GenericObjectPool#getTestWhileIdle()} for each per user pool. 1030 * 1031 * @param testWhileIdle 1032 * The default value for {@link 1033 * GenericObjectPool#getTestWhileIdle()} for each per user pool. 1034 */ 1035 public void setDefaultTestWhileIdle(final boolean testWhileIdle) { 1036 assertInitializationAllowed(); 1037 this.defaultTestWhileIdle = testWhileIdle; 1038 } 1039 1040 /** 1041 * Sets the default value for {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. 1042 * 1043 * @param timeBetweenEvictionRunsMillis The default value for 1044 * {@link GenericObjectPool#getDurationBetweenEvictionRuns()} for each per user pool. 1045 * @deprecated Use {@link #setDefaultDurationBetweenEvictionRuns(Duration)}. 1046 */ 1047 @Deprecated 1048 public void setDefaultTimeBetweenEvictionRunsMillis(final long timeBetweenEvictionRunsMillis) { 1049 assertInitializationAllowed(); 1050 this.defaultDurationBetweenEvictionRuns = Duration.ofMillis(timeBetweenEvictionRunsMillis); 1051 } 1052 1053 /** 1054 * Sets the value of defaultTransactionIsolation, which defines the state of connections handed out from this pool. 1055 * The value can be changed on the Connection using Connection.setTransactionIsolation(int). The default is JDBC 1056 * driver dependent. 1057 * 1058 * @param defaultTransactionIsolation 1059 * Value to assign to defaultTransactionIsolation 1060 */ 1061 public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { 1062 assertInitializationAllowed(); 1063 switch (defaultTransactionIsolation) { 1064 case Connection.TRANSACTION_NONE: 1065 case Connection.TRANSACTION_READ_COMMITTED: 1066 case Connection.TRANSACTION_READ_UNCOMMITTED: 1067 case Connection.TRANSACTION_REPEATABLE_READ: 1068 case Connection.TRANSACTION_SERIALIZABLE: 1069 break; 1070 default: 1071 throw new IllegalArgumentException(BAD_TRANSACTION_ISOLATION); 1072 } 1073 this.defaultTransactionIsolation = defaultTransactionIsolation; 1074 } 1075 1076 /** 1077 * Sets the description. This property is defined by JDBC as for use with GUI (or other) tools that might deploy the 1078 * datasource. It serves no internal purpose. 1079 * 1080 * @param description 1081 * Value to assign to description. 1082 */ 1083 public void setDescription(final String description) { 1084 this.description = description; 1085 } 1086 1087 /** 1088 * Sets the JNDI environment to be used when instantiating a JNDI InitialContext. This InitialContext is used to 1089 * locate the back end ConnectionPoolDataSource. 1090 * 1091 * @param properties 1092 * the JNDI environment property to set which will overwrite any current settings 1093 */ 1094 void setJndiEnvironment(final Properties properties) { 1095 if (jndiEnvironment == null) { 1096 jndiEnvironment = new Properties(); 1097 } else { 1098 jndiEnvironment.clear(); 1099 } 1100 jndiEnvironment.putAll(properties); 1101 } 1102 1103 /** 1104 * Sets the value of the given JNDI environment property to be used when instantiating a JNDI InitialContext. This 1105 * InitialContext is used to locate the back end ConnectionPoolDataSource. 1106 * 1107 * @param key 1108 * the JNDI environment property to set. 1109 * @param value 1110 * the value assigned to specified JNDI environment property. 1111 */ 1112 public void setJndiEnvironment(final String key, final String value) { 1113 if (jndiEnvironment == null) { 1114 jndiEnvironment = new Properties(); 1115 } 1116 jndiEnvironment.setProperty(key, value); 1117 } 1118 1119 /** 1120 * Sets the value of loginTimeout. 1121 * 1122 * @param loginTimeout 1123 * Value to assign to loginTimeout. 1124 * @since 2.10.0 1125 */ 1126 public void setLoginTimeout(final Duration loginTimeout) { 1127 this.loginTimeoutDuration = loginTimeout; 1128 } 1129 1130 /** 1131 * Sets the value of loginTimeout. 1132 * 1133 * @param loginTimeout 1134 * Value to assign to loginTimeout. 1135 * @deprecated Use {@link #setLoginTimeout(Duration)}. 1136 */ 1137 @Deprecated 1138 @Override 1139 public void setLoginTimeout(final int loginTimeout) { 1140 this.loginTimeoutDuration = Duration.ofSeconds(loginTimeout); 1141 } 1142 1143 /** 1144 * Sets the value of logWriter. 1145 * 1146 * @param logWriter 1147 * Value to assign to logWriter. 1148 */ 1149 @Override 1150 public void setLogWriter(final PrintWriter logWriter) { 1151 this.logWriter = logWriter; 1152 } 1153 1154 /** 1155 * <p> 1156 * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime. 1157 * </p> 1158 * <p> 1159 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is 1160 * invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()}, 1161 * {@link #getLogWriter()}. 1162 * </p> 1163 * 1164 * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime. 1165 * @since 2.9.0 1166 */ 1167 public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { 1168 this.maxConnDuration = maxConnLifetimeMillis; 1169 } 1170 1171 /** 1172 * <p> 1173 * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime. 1174 * </p> 1175 * <p> 1176 * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first time one of the following methods is 1177 * invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()}, 1178 * {@link #getLogWriter()}. 1179 * </p> 1180 * 1181 * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime. 1182 * @deprecated Use {@link #setMaxConnLifetime(Duration)}. 1183 */ 1184 @Deprecated 1185 public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { 1186 setMaxConnLifetime(Duration.ofMillis(maxConnLifetimeMillis)); 1187 } 1188 1189 /** 1190 * Sets whether a rollback will be issued after executing the SQL query that will be used to validate connections from 1191 * this pool before returning them to the caller. Default behavior is NOT to issue a rollback. The setting will only 1192 * have an effect if a validation query is set 1193 * 1194 * @param rollbackAfterValidation 1195 * new property value 1196 */ 1197 public void setRollbackAfterValidation(final boolean rollbackAfterValidation) { 1198 assertInitializationAllowed(); 1199 this.rollbackAfterValidation = rollbackAfterValidation; 1200 } 1201 1202 /** 1203 * Sets up the defaults for a given connection. 1204 * 1205 * @param connection The target connection. 1206 * @param userName The user name for the connection. 1207 * @throws SQLException if a database access error occurs or this method is called on a closed connection 1208 */ 1209 protected abstract void setupDefaults(Connection connection, String userName) throws SQLException; 1210 1211 /** 1212 * Sets the SQL query that will be used to validate connections from this pool before returning them to the caller. 1213 * If specified, this query <strong>MUST</strong> be an SQL SELECT statement that returns at least one row. If not 1214 * specified, connections will be validated using {@link Connection#isValid(int)}. 1215 * 1216 * @param validationQuery 1217 * The SQL query that will be used to validate connections from this pool before returning them to the 1218 * caller. 1219 */ 1220 public void setValidationQuery(final String validationQuery) { 1221 assertInitializationAllowed(); 1222 this.validationQuery = validationQuery; 1223 } 1224 1225 /** 1226 * Sets the timeout duration before the validation query fails. 1227 * 1228 * @param validationQueryTimeoutDuration 1229 * The new timeout duration. 1230 */ 1231 public void setValidationQueryTimeout(final Duration validationQueryTimeoutDuration) { 1232 this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; 1233 } 1234 1235 /** 1236 * Sets the timeout in seconds before the validation query fails. 1237 * 1238 * @param validationQueryTimeoutSeconds 1239 * The new timeout in seconds 1240 * @deprecated Use {@link #setValidationQueryTimeout(Duration)}. 1241 */ 1242 @Deprecated 1243 public void setValidationQueryTimeout(final int validationQueryTimeoutSeconds) { 1244 this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); 1245 } 1246 1247 /** 1248 * Tests and returns whether a JNDI context can be created to lookup a ConnectionPoolDataSource to then access a PooledConnection connection. 1249 * 1250 * @param userName An optional user name, may be null. 1251 * @param userPassword An optional user user password, may be null. 1252 * @return A ConnectionPoolDataSource from a JNDI context. 1253 * @throws javax.naming.NamingException if a naming exception is encountered. 1254 * @throws SQLException if a ConnectionPoolDataSource or PooledConnection is not available. 1255 */ 1256 protected ConnectionPoolDataSource testCPDS(final String userName, final String userPassword) 1257 throws javax.naming.NamingException, SQLException { 1258 // The source of physical database connections 1259 ConnectionPoolDataSource cpds = this.dataSource; 1260 if (cpds == null) { 1261 Context ctx = null; 1262 if (jndiEnvironment == null) { 1263 ctx = new InitialContext(); 1264 } else { 1265 ctx = new InitialContext(jndiEnvironment); 1266 } 1267 final Object ds = ctx.lookup(dataSourceName); 1268 if (!(ds instanceof ConnectionPoolDataSource)) { 1269 throw new SQLException("Illegal configuration: DataSource " + dataSourceName + " (" 1270 + ds.getClass().getName() + ") doesn't implement javax.sql.ConnectionPoolDataSource"); 1271 } 1272 cpds = (ConnectionPoolDataSource) ds; 1273 } 1274 // try to get a connection with the supplied userName/password 1275 PooledConnection conn = null; 1276 try { 1277 if (userName != null) { 1278 conn = cpds.getPooledConnection(userName, userPassword); 1279 } else { 1280 conn = cpds.getPooledConnection(); 1281 } 1282 if (conn == null) { 1283 throw new SQLException("Cannot connect using the supplied userName/password"); 1284 } 1285 } finally { 1286 if (conn != null) { 1287 try { 1288 conn.close(); 1289 } catch (final SQLException ignored) { 1290 // at least we could connect 1291 } 1292 } 1293 } 1294 return cpds; 1295 } 1296 1297 /** 1298 * @since 2.6.0 1299 */ 1300 @Override 1301 public synchronized String toString() { 1302 final StringBuilder builder = new StringBuilder(super.toString()); 1303 builder.append('['); 1304 toStringFields(builder); 1305 builder.append(']'); 1306 return builder.toString(); 1307 } 1308 1309 /** 1310 * Appends this instance's fields to a string builder. 1311 * 1312 * @param builder the target string builder. 1313 */ 1314 protected void toStringFields(final StringBuilder builder) { 1315 builder.append("getConnectionCalled="); 1316 builder.append(getConnectionCalled); 1317 builder.append(", dataSource="); 1318 builder.append(dataSource); 1319 builder.append(", dataSourceName="); 1320 builder.append(dataSourceName); 1321 builder.append(", description="); 1322 builder.append(description); 1323 builder.append(", jndiEnvironment="); 1324 builder.append(jndiEnvironment); 1325 builder.append(", loginTimeoutDuration="); 1326 builder.append(loginTimeoutDuration); 1327 builder.append(", logWriter="); 1328 builder.append(logWriter); 1329 builder.append(", instanceKey="); 1330 builder.append(instanceKey); 1331 builder.append(", defaultBlockWhenExhausted="); 1332 builder.append(defaultBlockWhenExhausted); 1333 builder.append(", defaultEvictionPolicyClassName="); 1334 builder.append(defaultEvictionPolicyClassName); 1335 builder.append(", defaultLifo="); 1336 builder.append(defaultLifo); 1337 builder.append(", defaultMaxIdle="); 1338 builder.append(defaultMaxIdle); 1339 builder.append(", defaultMaxTotal="); 1340 builder.append(defaultMaxTotal); 1341 builder.append(", defaultMaxWaitDuration="); 1342 builder.append(defaultMaxWaitDuration); 1343 builder.append(", defaultMinEvictableIdleDuration="); 1344 builder.append(defaultMinEvictableIdleDuration); 1345 builder.append(", defaultMinIdle="); 1346 builder.append(defaultMinIdle); 1347 builder.append(", defaultNumTestsPerEvictionRun="); 1348 builder.append(defaultNumTestsPerEvictionRun); 1349 builder.append(", defaultSoftMinEvictableIdleDuration="); 1350 builder.append(defaultSoftMinEvictableIdleDuration); 1351 builder.append(", defaultTestOnCreate="); 1352 builder.append(defaultTestOnCreate); 1353 builder.append(", defaultTestOnBorrow="); 1354 builder.append(defaultTestOnBorrow); 1355 builder.append(", defaultTestOnReturn="); 1356 builder.append(defaultTestOnReturn); 1357 builder.append(", defaultTestWhileIdle="); 1358 builder.append(defaultTestWhileIdle); 1359 builder.append(", defaultDurationBetweenEvictionRuns="); 1360 builder.append(defaultDurationBetweenEvictionRuns); 1361 builder.append(", validationQuery="); 1362 builder.append(validationQuery); 1363 builder.append(", validationQueryTimeoutDuration="); 1364 builder.append(validationQueryTimeoutDuration); 1365 builder.append(", rollbackAfterValidation="); 1366 builder.append(rollbackAfterValidation); 1367 builder.append(", maxConnDuration="); 1368 builder.append(maxConnDuration); 1369 builder.append(", defaultAutoCommit="); 1370 builder.append(defaultAutoCommit); 1371 builder.append(", defaultTransactionIsolation="); 1372 builder.append(defaultTransactionIsolation); 1373 builder.append(", defaultReadOnly="); 1374 builder.append(defaultReadOnly); 1375 } 1376 1377 @Override 1378 @SuppressWarnings("unchecked") 1379 public <T> T unwrap(final Class<T> iface) throws SQLException { 1380 if (isWrapperFor(iface)) { 1381 return (T) this; 1382 } 1383 throw new SQLException(this + " is not a wrapper for " + iface); 1384 } 1385}