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