1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.dbcp2.datasources;
18
19 import java.io.OutputStreamWriter;
20 import java.io.PrintWriter;
21 import java.io.Serializable;
22 import java.nio.charset.StandardCharsets;
23 import java.sql.Connection;
24 import java.sql.SQLException;
25 import java.sql.SQLFeatureNotSupportedException;
26 import java.time.Duration;
27 import java.util.Properties;
28 import java.util.logging.Logger;
29
30 import javax.naming.Context;
31 import javax.naming.InitialContext;
32 import javax.naming.Referenceable;
33 import javax.sql.ConnectionPoolDataSource;
34 import javax.sql.DataSource;
35 import javax.sql.PooledConnection;
36
37 import org.apache.commons.dbcp2.Utils;
38 import org.apache.commons.pool2.impl.BaseObjectPoolConfig;
39 import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
40 import org.apache.commons.pool2.impl.GenericObjectPool;
41
42 /**
43 * <p>
44 * The base class for {@link SharedPoolDataSource} and {@link PerUserPoolDataSource}. Many of the
45 * configuration properties are shared and defined here. This class is declared public in order to allow particular
46 * usage with commons-beanutils; do not make direct use of it outside of <em>commons-dbcp2</em>.
47 * </p>
48 *
49 * <p>
50 * A J2EE container will normally provide some method of initializing the {@link DataSource} whose attributes are
51 * presented as bean getters/setters and then deploying it via JNDI. It is then available to an application as a source
52 * of pooled logical connections to the database. The pool needs a source of physical connections. This source is in the
53 * form of a {@link ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used
54 * to lookup the source via JNDI.
55 * </p>
56 *
57 * <p>
58 * Although normally used within a JNDI environment, A DataSource can be instantiated and initialized as any bean. In
59 * this case the {@link ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class
60 * allows the physical source of connections to be attached directly to this pool using the
61 * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method.
62 * </p>
63 *
64 * <p>
65 * The dbcp package contains an adapter, {@link org.apache.commons.dbcp2.cpdsadapter.DriverAdapterCPDS}, that can be
66 * used to allow the use of {@link DataSource}'s based on this class with JDBC driver implementations that do not
67 * supply a {@link ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation.
68 * </p>
69 *
70 * <p>
71 * The <a href="package-summary.html">package documentation</a> contains an example using Apache Tomcat and JNDI and it
72 * also contains a non-JNDI example.
73 * </p>
74 *
75 * @since 2.0
76 */
77 public abstract class InstanceKeyDataSource implements DataSource, Referenceable, Serializable, AutoCloseable {
78
79 private static final long serialVersionUID = -6819270431752240878L;
80
81 private static final String GET_CONNECTION_CALLED = "A Connection was already requested from this source, "
82 + "further initialization is not allowed.";
83 private static final String BAD_TRANSACTION_ISOLATION = "The requested TransactionIsolation level is invalid.";
84
85 /**
86 * Internal constant to indicate the level is not set.
87 */
88 protected static final int UNKNOWN_TRANSACTIONISOLATION = -1;
89
90 /** Guards property setters - once true, setters throw IllegalStateException */
91 private volatile boolean getConnectionCalled;
92
93 /** Underlying source of PooledConnections */
94 private ConnectionPoolDataSource dataSource;
95
96 /** DataSource Name used to find the ConnectionPoolDataSource */
97 private String dataSourceName;
98
99 /** 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 }