| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| BasicDataSource |
|
| 2.048780487804878;2.049 |
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | ||
| 18 | package org.apache.commons.dbcp; | |
| 19 | ||
| 20 | import java.io.PrintWriter; | |
| 21 | import java.util.Properties; | |
| 22 | import java.util.Collection; | |
| 23 | import java.util.List; | |
| 24 | import java.util.ArrayList; | |
| 25 | import java.util.Iterator; | |
| 26 | import java.util.Collections; | |
| 27 | import java.sql.Connection; | |
| 28 | import java.sql.Driver; | |
| 29 | import java.sql.DriverManager; | |
| 30 | import java.sql.SQLException; | |
| 31 | import javax.sql.DataSource; | |
| 32 | ||
| 33 | import org.apache.commons.pool.KeyedObjectPoolFactory; | |
| 34 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; | |
| 35 | import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; | |
| 36 | import org.apache.commons.pool.impl.GenericObjectPool; | |
| 37 | ||
| 38 | ||
| 39 | /** | |
| 40 | * <p>Basic implementation of <code>javax.sql.DataSource</code> that is | |
| 41 | * configured via JavaBeans properties. This is not the only way to | |
| 42 | * combine the <em>commons-dbcp</em> and <em>commons-pool</em> packages, | |
| 43 | * but provides a "one stop shopping" solution for basic requirements.</p> | |
| 44 | * | |
| 45 | * <p>Users extending this class should take care to use appropriate accessors | |
| 46 | * rather than accessing protected fields directly to ensure thread-safety.</p> | |
| 47 | * | |
| 48 | * @author Glenn L. Nielsen | |
| 49 | * @author Craig R. McClanahan | |
| 50 | * @author Dirk Verbeeck | |
| 51 | * @version $Revision: 1023401 $ $Date: 2010-10-16 21:54:24 -0400 (Sat, 16 Oct 2010) $ | |
| 52 | */ | |
| 53 | 398 | public class BasicDataSource implements DataSource { |
| 54 | ||
| 55 | static { | |
| 56 | // Attempt to prevent deadlocks - see DBCP - 272 | |
| 57 | 2 | DriverManager.getDrivers(); |
| 58 | 2 | } |
| 59 | ||
| 60 | // ------------------------------------------------------------- Properties | |
| 61 | ||
| 62 | /** | |
| 63 | * The default auto-commit state of connections created by this pool. | |
| 64 | */ | |
| 65 | 398 | protected volatile boolean defaultAutoCommit = true; |
| 66 | ||
| 67 | /** | |
| 68 | * Returns the default auto-commit property. | |
| 69 | * | |
| 70 | * @return true if default auto-commit is enabled | |
| 71 | */ | |
| 72 | public boolean getDefaultAutoCommit() { | |
| 73 | 2 | return this.defaultAutoCommit; |
| 74 | } | |
| 75 | ||
| 76 | /** | |
| 77 | * <p>Sets default auto-commit state of connections returned by this | |
| 78 | * datasource.</p> | |
| 79 | * <p> | |
| 80 | * Note: this method currently has no effect once the pool has been | |
| 81 | * initialized. The pool is initialized the first time one of the | |
| 82 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 83 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 84 | * | |
| 85 | * @param defaultAutoCommit default auto-commit value | |
| 86 | */ | |
| 87 | public void setDefaultAutoCommit(boolean defaultAutoCommit) { | |
| 88 | 408 | this.defaultAutoCommit = defaultAutoCommit; |
| 89 | 408 | this.restartNeeded = true; |
| 90 | 408 | } |
| 91 | ||
| 92 | ||
| 93 | /** | |
| 94 | * The default read-only state of connections created by this pool. | |
| 95 | */ | |
| 96 | 398 | protected transient Boolean defaultReadOnly = null; |
| 97 | ||
| 98 | /** | |
| 99 | * Returns the default readOnly property. | |
| 100 | * | |
| 101 | * @return true if connections are readOnly by default | |
| 102 | */ | |
| 103 | public boolean getDefaultReadOnly() { | |
| 104 | 2 | Boolean val = defaultReadOnly; |
| 105 | 2 | if (val != null) { |
| 106 | 2 | return val.booleanValue(); |
| 107 | } | |
| 108 | 0 | return false; |
| 109 | } | |
| 110 | ||
| 111 | /** | |
| 112 | * <p>Sets defaultReadonly property.</p> | |
| 113 | * <p> | |
| 114 | * Note: this method currently has no effect once the pool has been | |
| 115 | * initialized. The pool is initialized the first time one of the | |
| 116 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 117 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 118 | * | |
| 119 | * @param defaultReadOnly default read-only value | |
| 120 | */ | |
| 121 | public void setDefaultReadOnly(boolean defaultReadOnly) { | |
| 122 | 400 | this.defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE; |
| 123 | 400 | this.restartNeeded = true; |
| 124 | 400 | } |
| 125 | ||
| 126 | /** | |
| 127 | * The default TransactionIsolation state of connections created by this pool. | |
| 128 | */ | |
| 129 | 398 | protected volatile int defaultTransactionIsolation = |
| 130 | PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION; | |
| 131 | ||
| 132 | /** | |
| 133 | * Returns the default transaction isolation state of returned connections. | |
| 134 | * | |
| 135 | * @return the default value for transaction isolation state | |
| 136 | * @see Connection#getTransactionIsolation | |
| 137 | */ | |
| 138 | public int getDefaultTransactionIsolation() { | |
| 139 | 2 | return this.defaultTransactionIsolation; |
| 140 | } | |
| 141 | ||
| 142 | /** | |
| 143 | * <p>Sets the default transaction isolation state for returned | |
| 144 | * connections.</p> | |
| 145 | * <p> | |
| 146 | * Note: this method currently has no effect once the pool has been | |
| 147 | * initialized. The pool is initialized the first time one of the | |
| 148 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 149 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 150 | * | |
| 151 | * @param defaultTransactionIsolation the default transaction isolation | |
| 152 | * state | |
| 153 | * @see Connection#getTransactionIsolation | |
| 154 | */ | |
| 155 | public void setDefaultTransactionIsolation(int defaultTransactionIsolation) { | |
| 156 | 392 | this.defaultTransactionIsolation = defaultTransactionIsolation; |
| 157 | 392 | this.restartNeeded = true; |
| 158 | 392 | } |
| 159 | ||
| 160 | ||
| 161 | /** | |
| 162 | * The default "catalog" of connections created by this pool. | |
| 163 | */ | |
| 164 | 398 | protected volatile String defaultCatalog = null; |
| 165 | ||
| 166 | /** | |
| 167 | * Returns the default catalog. | |
| 168 | * | |
| 169 | * @return the default catalog | |
| 170 | */ | |
| 171 | public String getDefaultCatalog() { | |
| 172 | 2 | return this.defaultCatalog; |
| 173 | } | |
| 174 | ||
| 175 | /** | |
| 176 | * <p>Sets the default catalog.</p> | |
| 177 | * <p> | |
| 178 | * Note: this method currently has no effect once the pool has been | |
| 179 | * initialized. The pool is initialized the first time one of the | |
| 180 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 181 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 182 | * | |
| 183 | * @param defaultCatalog the default catalog | |
| 184 | */ | |
| 185 | public void setDefaultCatalog(String defaultCatalog) { | |
| 186 | 392 | if ((defaultCatalog != null) && (defaultCatalog.trim().length() > 0)) { |
| 187 | 392 | this.defaultCatalog = defaultCatalog; |
| 188 | } | |
| 189 | else { | |
| 190 | 0 | this.defaultCatalog = null; |
| 191 | } | |
| 192 | 392 | this.restartNeeded = true; |
| 193 | 392 | } |
| 194 | ||
| 195 | ||
| 196 | /** | |
| 197 | * The fully qualified Java class name of the JDBC driver to be used. | |
| 198 | */ | |
| 199 | 398 | protected String driverClassName = null; |
| 200 | ||
| 201 | /** | |
| 202 | * Returns the jdbc driver class name. | |
| 203 | * | |
| 204 | * @return the jdbc driver class name | |
| 205 | */ | |
| 206 | public synchronized String getDriverClassName() { | |
| 207 | 2 | return this.driverClassName; |
| 208 | } | |
| 209 | ||
| 210 | /** | |
| 211 | * <p>Sets the jdbc driver class name.</p> | |
| 212 | * <p> | |
| 213 | * Note: this method currently has no effect once the pool has been | |
| 214 | * initialized. The pool is initialized the first time one of the | |
| 215 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 216 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 217 | * | |
| 218 | * @param driverClassName the class name of the jdbc driver | |
| 219 | */ | |
| 220 | public synchronized void setDriverClassName(String driverClassName) { | |
| 221 | 394 | if ((driverClassName != null) && (driverClassName.trim().length() > 0)) { |
| 222 | 394 | this.driverClassName = driverClassName; |
| 223 | } | |
| 224 | else { | |
| 225 | 0 | this.driverClassName = null; |
| 226 | } | |
| 227 | 394 | this.restartNeeded = true; |
| 228 | 394 | } |
| 229 | ||
| 230 | /** | |
| 231 | * The class loader instance to use to load the JDBC driver. If not | |
| 232 | * specified, {@link Class#forName(String)} is used to load the JDBC driver. | |
| 233 | * If specified, {@link Class#forName(String, boolean, ClassLoader)} is | |
| 234 | * used. | |
| 235 | */ | |
| 236 | 398 | protected ClassLoader driverClassLoader = null; |
| 237 | ||
| 238 | /** | |
| 239 | * Returns the class loader specified for loading the JDBC driver. Returns | |
| 240 | * <code>null</code> if no class loader has been explicitly specified. | |
| 241 | */ | |
| 242 | public synchronized ClassLoader getDriverClassLoader() { | |
| 243 | 0 | return this.driverClassLoader; |
| 244 | } | |
| 245 | ||
| 246 | /** | |
| 247 | * <p>Sets the class loader to be used to load the JDBC driver.</p> | |
| 248 | * <p> | |
| 249 | * Note: this method currently has no effect once the pool has been | |
| 250 | * initialized. The pool is initialized the first time one of the | |
| 251 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 252 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 253 | * | |
| 254 | * @param driverClassLoader the class loader with which to load the JDBC | |
| 255 | * driver | |
| 256 | */ | |
| 257 | public synchronized void setDriverClassLoader( | |
| 258 | ClassLoader driverClassLoader) { | |
| 259 | 0 | this.driverClassLoader = driverClassLoader; |
| 260 | 0 | this.restartNeeded = true; |
| 261 | 0 | } |
| 262 | ||
| 263 | /** | |
| 264 | * The maximum number of active connections that can be allocated from | |
| 265 | * this pool at the same time, or negative for no limit. | |
| 266 | */ | |
| 267 | 398 | protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE; |
| 268 | ||
| 269 | /** | |
| 270 | * <p>Returns the maximum number of active connections that can be | |
| 271 | * allocated at the same time. | |
| 272 | * </p> | |
| 273 | * <p>A negative number means that there is no limit.</p> | |
| 274 | * | |
| 275 | * @return the maximum number of active connections | |
| 276 | */ | |
| 277 | public synchronized int getMaxActive() { | |
| 278 | 2 | return this.maxActive; |
| 279 | } | |
| 280 | ||
| 281 | /** | |
| 282 | * Sets the maximum number of active connections that can be | |
| 283 | * allocated at the same time. Use a negative value for no limit. | |
| 284 | * | |
| 285 | * @param maxActive the new value for maxActive | |
| 286 | * @see #getMaxActive() | |
| 287 | */ | |
| 288 | public synchronized void setMaxActive(int maxActive) { | |
| 289 | 422 | this.maxActive = maxActive; |
| 290 | 422 | if (connectionPool != null) { |
| 291 | 0 | connectionPool.setMaxActive(maxActive); |
| 292 | } | |
| 293 | 422 | } |
| 294 | ||
| 295 | /** | |
| 296 | * The maximum number of connections that can remain idle in the | |
| 297 | * pool, without extra ones being destroyed, or negative for no limit. | |
| 298 | * If maxIdle is set too low on heavily loaded systems it is possible you | |
| 299 | * will see connections being closed and almost immediately new connections | |
| 300 | * being opened. This is a result of the active threads momentarily closing | |
| 301 | * connections faster than they are opening them, causing the number of idle | |
| 302 | * connections to rise above maxIdle. The best value for maxIdle for heavily | |
| 303 | * loaded system will vary but the default is a good starting point. | |
| 304 | */ | |
| 305 | 398 | protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE; |
| 306 | ||
| 307 | /** | |
| 308 | * <p>Returns the maximum number of connections that can remain idle in the | |
| 309 | * pool. Excess idle connections are destroyed on return to the pool. | |
| 310 | * </p> | |
| 311 | * <p>A negative value indicates that there is no limit</p> | |
| 312 | * | |
| 313 | * @return the maximum number of idle connections | |
| 314 | */ | |
| 315 | public synchronized int getMaxIdle() { | |
| 316 | 2 | return this.maxIdle; |
| 317 | } | |
| 318 | ||
| 319 | /** | |
| 320 | * Sets the maximum number of connections that can remain idle in the | |
| 321 | * pool. Excess idle connections are destroyed on return to the pool. | |
| 322 | * | |
| 323 | * @see #getMaxIdle() | |
| 324 | * @param maxIdle the new value for maxIdle | |
| 325 | */ | |
| 326 | public synchronized void setMaxIdle(int maxIdle) { | |
| 327 | 16 | this.maxIdle = maxIdle; |
| 328 | 16 | if (connectionPool != null) { |
| 329 | 0 | connectionPool.setMaxIdle(maxIdle); |
| 330 | } | |
| 331 | 16 | } |
| 332 | ||
| 333 | /** | |
| 334 | * The minimum number of active connections that can remain idle in the | |
| 335 | * pool, without extra ones being created when the evictor runs, or 0 to create none. | |
| 336 | * The pool attempts to ensure that minIdle connections are available when the idle object evictor | |
| 337 | * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis} | |
| 338 | * has a positive value. | |
| 339 | */ | |
| 340 | 398 | protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE; |
| 341 | ||
| 342 | /** | |
| 343 | * Returns the minimum number of idle connections in the pool. The pool attempts | |
| 344 | * to ensure that minIdle connections are available when the idle object evictor | |
| 345 | * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis} | |
| 346 | * has a positive value. | |
| 347 | * | |
| 348 | * @return the minimum number of idle connections | |
| 349 | * @see GenericObjectPool#getMinIdle() | |
| 350 | */ | |
| 351 | public synchronized int getMinIdle() { | |
| 352 | 2 | return this.minIdle; |
| 353 | } | |
| 354 | ||
| 355 | /** | |
| 356 | * Sets the minimum number of idle connections in the pool. The pool attempts | |
| 357 | * to ensure that minIdle connections are available when the idle object evictor | |
| 358 | * runs. The value of this property has no effect unless {@link #timeBetweenEvictionRunsMillis} | |
| 359 | * has a positive value. | |
| 360 | * | |
| 361 | * @param minIdle the new value for minIdle | |
| 362 | * @see GenericObjectPool#setMinIdle(int) | |
| 363 | */ | |
| 364 | public synchronized void setMinIdle(int minIdle) { | |
| 365 | 2 | this.minIdle = minIdle; |
| 366 | 2 | if (connectionPool != null) { |
| 367 | 0 | connectionPool.setMinIdle(minIdle); |
| 368 | } | |
| 369 | 2 | } |
| 370 | ||
| 371 | /** | |
| 372 | * The initial number of connections that are created when the pool | |
| 373 | * is started. | |
| 374 | * | |
| 375 | * @since 1.2 | |
| 376 | */ | |
| 377 | 398 | protected int initialSize = 0; |
| 378 | ||
| 379 | /** | |
| 380 | * Returns the initial size of the connection pool. | |
| 381 | * | |
| 382 | * @return the number of connections created when the pool is initialized | |
| 383 | */ | |
| 384 | public synchronized int getInitialSize() { | |
| 385 | 6 | return this.initialSize; |
| 386 | } | |
| 387 | ||
| 388 | /** | |
| 389 | * <p>Sets the initial size of the connection pool.</p> | |
| 390 | * <p> | |
| 391 | * Note: this method currently has no effect once the pool has been | |
| 392 | * initialized. The pool is initialized the first time one of the | |
| 393 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 394 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 395 | * | |
| 396 | * @param initialSize the number of connections created when the pool | |
| 397 | * is initialized | |
| 398 | */ | |
| 399 | public synchronized void setInitialSize(int initialSize) { | |
| 400 | 10 | this.initialSize = initialSize; |
| 401 | 10 | this.restartNeeded = true; |
| 402 | 10 | } |
| 403 | ||
| 404 | /** | |
| 405 | * The maximum number of milliseconds that the pool will wait (when there | |
| 406 | * are no available connections) for a connection to be returned before | |
| 407 | * throwing an exception, or <= 0 to wait indefinitely. | |
| 408 | */ | |
| 409 | 398 | protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT; |
| 410 | ||
| 411 | /** | |
| 412 | * <p>Returns the maximum number of milliseconds that the pool will wait | |
| 413 | * for a connection to be returned before throwing an exception. | |
| 414 | * </p> | |
| 415 | * <p>A value less than or equal to zero means the pool is set to wait | |
| 416 | * indefinitely.</p> | |
| 417 | * | |
| 418 | * @return the maxWait property value | |
| 419 | */ | |
| 420 | public synchronized long getMaxWait() { | |
| 421 | 2 | return this.maxWait; |
| 422 | } | |
| 423 | ||
| 424 | /** | |
| 425 | * <p>Sets the maxWait property. | |
| 426 | * </p> | |
| 427 | * <p>Use -1 to make the pool wait indefinitely. | |
| 428 | * </p> | |
| 429 | * | |
| 430 | * @param maxWait the new value for maxWait | |
| 431 | * @see #getMaxWait() | |
| 432 | */ | |
| 433 | public synchronized void setMaxWait(long maxWait) { | |
| 434 | 392 | this.maxWait = maxWait; |
| 435 | 392 | if (connectionPool != null) { |
| 436 | 0 | connectionPool.setMaxWait(maxWait); |
| 437 | } | |
| 438 | 392 | } |
| 439 | ||
| 440 | /** | |
| 441 | * Prepared statement pooling for this pool. When this property is set to <code>true</code> | |
| 442 | * both PreparedStatements and CallableStatements are pooled. | |
| 443 | */ | |
| 444 | 398 | protected boolean poolPreparedStatements = false; |
| 445 | ||
| 446 | /** | |
| 447 | * Returns true if we are pooling statements. | |
| 448 | * | |
| 449 | * @return true if prepared and callable statements are pooled | |
| 450 | */ | |
| 451 | public synchronized boolean isPoolPreparedStatements() { | |
| 452 | 424 | return this.poolPreparedStatements; |
| 453 | } | |
| 454 | ||
| 455 | /** | |
| 456 | * <p>Sets whether to pool statements or not.</p> | |
| 457 | * <p> | |
| 458 | * Note: this method currently has no effect once the pool has been | |
| 459 | * initialized. The pool is initialized the first time one of the | |
| 460 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 461 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 462 | * | |
| 463 | * @param poolingStatements pooling on or off | |
| 464 | */ | |
| 465 | public synchronized void setPoolPreparedStatements(boolean poolingStatements) { | |
| 466 | 102 | this.poolPreparedStatements = poolingStatements; |
| 467 | 102 | this.restartNeeded = true; |
| 468 | 102 | } |
| 469 | ||
| 470 | /** | |
| 471 | * <p>The maximum number of open statements that can be allocated from | |
| 472 | * the statement pool at the same time, or non-positive for no limit. Since | |
| 473 | * a connection usually only uses one or two statements at a time, this is | |
| 474 | * mostly used to help detect resource leaks.</p> | |
| 475 | * | |
| 476 | * <p>Note: As of version 1.3, CallableStatements (those produced by {@link Connection#prepareCall}) | |
| 477 | * are pooled along with PreparedStatements (produced by {@link Connection#prepareStatement}) | |
| 478 | * and <code>maxOpenPreparedStatements</code> limits the total number of prepared or callable statements | |
| 479 | * that may be in use at a given time.</p> | |
| 480 | */ | |
| 481 | 398 | protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL; |
| 482 | ||
| 483 | /** | |
| 484 | * Gets the value of the {@link #maxOpenPreparedStatements} property. | |
| 485 | * | |
| 486 | * @return the maximum number of open statements | |
| 487 | * @see #maxOpenPreparedStatements | |
| 488 | */ | |
| 489 | public synchronized int getMaxOpenPreparedStatements() { | |
| 490 | 2 | return this.maxOpenPreparedStatements; |
| 491 | } | |
| 492 | ||
| 493 | /** | |
| 494 | * <p>Sets the value of the {@link #maxOpenPreparedStatements} | |
| 495 | * property.</p> | |
| 496 | * <p> | |
| 497 | * Note: this method currently has no effect once the pool has been | |
| 498 | * initialized. The pool is initialized the first time one of the | |
| 499 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 500 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 501 | * | |
| 502 | * @param maxOpenStatements the new maximum number of prepared statements | |
| 503 | * @see #maxOpenPreparedStatements | |
| 504 | */ | |
| 505 | public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) { | |
| 506 | 104 | this.maxOpenPreparedStatements = maxOpenStatements; |
| 507 | 104 | this.restartNeeded = true; |
| 508 | 104 | } |
| 509 | ||
| 510 | /** | |
| 511 | * The indication of whether objects will be validated before being | |
| 512 | * borrowed from the pool. If the object fails to validate, it will be | |
| 513 | * dropped from the pool, and we will attempt to borrow another. | |
| 514 | */ | |
| 515 | 398 | protected boolean testOnBorrow = true; |
| 516 | ||
| 517 | /** | |
| 518 | * Returns the {@link #testOnBorrow} property. | |
| 519 | * | |
| 520 | * @return true if objects are validated before being borrowed from the | |
| 521 | * pool | |
| 522 | * | |
| 523 | * @see #testOnBorrow | |
| 524 | */ | |
| 525 | public synchronized boolean getTestOnBorrow() { | |
| 526 | 34 | return this.testOnBorrow; |
| 527 | } | |
| 528 | ||
| 529 | /** | |
| 530 | * Sets the {@link #testOnBorrow} property. This property determines | |
| 531 | * whether or not the pool will validate objects before they are borrowed | |
| 532 | * from the pool. For a <code>true</code> value to have any effect, the | |
| 533 | * <code>validationQuery</code> property must be set to a non-null string. | |
| 534 | * | |
| 535 | * @param testOnBorrow new value for testOnBorrow property | |
| 536 | */ | |
| 537 | public synchronized void setTestOnBorrow(boolean testOnBorrow) { | |
| 538 | 76 | this.testOnBorrow = testOnBorrow; |
| 539 | 76 | if (connectionPool != null) { |
| 540 | 0 | connectionPool.setTestOnBorrow(testOnBorrow); |
| 541 | } | |
| 542 | 76 | } |
| 543 | ||
| 544 | /** | |
| 545 | * The indication of whether objects will be validated before being | |
| 546 | * returned to the pool. | |
| 547 | */ | |
| 548 | 398 | protected boolean testOnReturn = false; |
| 549 | ||
| 550 | /** | |
| 551 | * Returns the value of the {@link #testOnReturn} property. | |
| 552 | * | |
| 553 | * @return true if objects are validated before being returned to the | |
| 554 | * pool | |
| 555 | * @see #testOnReturn | |
| 556 | */ | |
| 557 | public synchronized boolean getTestOnReturn() { | |
| 558 | 34 | return this.testOnReturn; |
| 559 | } | |
| 560 | ||
| 561 | /** | |
| 562 | * Sets the <code>testOnReturn</code> property. This property determines | |
| 563 | * whether or not the pool will validate objects before they are returned | |
| 564 | * to the pool. For a <code>true</code> value to have any effect, the | |
| 565 | * <code>validationQuery</code> property must be set to a non-null string. | |
| 566 | * | |
| 567 | * @param testOnReturn new value for testOnReturn property | |
| 568 | */ | |
| 569 | public synchronized void setTestOnReturn(boolean testOnReturn) { | |
| 570 | 68 | this.testOnReturn = testOnReturn; |
| 571 | 68 | if (connectionPool != null) { |
| 572 | 0 | connectionPool.setTestOnReturn(testOnReturn); |
| 573 | } | |
| 574 | 68 | } |
| 575 | ||
| 576 | /** | |
| 577 | * The number of milliseconds to sleep between runs of the idle object | |
| 578 | * evictor thread. When non-positive, no idle object evictor thread will | |
| 579 | * be run. | |
| 580 | */ | |
| 581 | 398 | protected long timeBetweenEvictionRunsMillis = |
| 582 | GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; | |
| 583 | ||
| 584 | /** | |
| 585 | * Returns the value of the {@link #timeBetweenEvictionRunsMillis} | |
| 586 | * property. | |
| 587 | * | |
| 588 | * @return the time (in miliseconds) between evictor runs | |
| 589 | * @see #timeBetweenEvictionRunsMillis | |
| 590 | */ | |
| 591 | public synchronized long getTimeBetweenEvictionRunsMillis() { | |
| 592 | 2 | return this.timeBetweenEvictionRunsMillis; |
| 593 | } | |
| 594 | ||
| 595 | /** | |
| 596 | * Sets the {@link #timeBetweenEvictionRunsMillis} property. | |
| 597 | * | |
| 598 | * @param timeBetweenEvictionRunsMillis the new time between evictor runs | |
| 599 | * @see #timeBetweenEvictionRunsMillis | |
| 600 | */ | |
| 601 | public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { | |
| 602 | 10 | this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; |
| 603 | 10 | if (connectionPool != null) { |
| 604 | 0 | connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); |
| 605 | } | |
| 606 | 10 | } |
| 607 | ||
| 608 | /** | |
| 609 | * The number of objects to examine during each run of the idle object | |
| 610 | * evictor thread (if any). | |
| 611 | */ | |
| 612 | 398 | protected int numTestsPerEvictionRun = |
| 613 | GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; | |
| 614 | ||
| 615 | /** | |
| 616 | * Returns the value of the {@link #numTestsPerEvictionRun} property. | |
| 617 | * | |
| 618 | * @return the number of objects to examine during idle object evictor | |
| 619 | * runs | |
| 620 | * @see #numTestsPerEvictionRun | |
| 621 | */ | |
| 622 | public synchronized int getNumTestsPerEvictionRun() { | |
| 623 | 2 | return this.numTestsPerEvictionRun; |
| 624 | } | |
| 625 | ||
| 626 | /** | |
| 627 | * Sets the value of the {@link #numTestsPerEvictionRun} property. | |
| 628 | * | |
| 629 | * @param numTestsPerEvictionRun the new {@link #numTestsPerEvictionRun} | |
| 630 | * value | |
| 631 | * @see #numTestsPerEvictionRun | |
| 632 | */ | |
| 633 | public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { | |
| 634 | 2 | this.numTestsPerEvictionRun = numTestsPerEvictionRun; |
| 635 | 2 | if (connectionPool != null) { |
| 636 | 0 | connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); |
| 637 | } | |
| 638 | 2 | } |
| 639 | ||
| 640 | /** | |
| 641 | * The minimum amount of time an object may sit idle in the pool before it | |
| 642 | * is eligible for eviction by the idle object evictor (if any). | |
| 643 | */ | |
| 644 | 398 | protected long minEvictableIdleTimeMillis = |
| 645 | GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; | |
| 646 | ||
| 647 | /** | |
| 648 | * Returns the {@link #minEvictableIdleTimeMillis} property. | |
| 649 | * | |
| 650 | * @return the value of the {@link #minEvictableIdleTimeMillis} property | |
| 651 | * @see #minEvictableIdleTimeMillis | |
| 652 | */ | |
| 653 | public synchronized long getMinEvictableIdleTimeMillis() { | |
| 654 | 2 | return this.minEvictableIdleTimeMillis; |
| 655 | } | |
| 656 | ||
| 657 | /** | |
| 658 | * Sets the {@link #minEvictableIdleTimeMillis} property. | |
| 659 | * | |
| 660 | * @param minEvictableIdleTimeMillis the minimum amount of time an object | |
| 661 | * may sit idle in the pool | |
| 662 | * @see #minEvictableIdleTimeMillis | |
| 663 | */ | |
| 664 | public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { | |
| 665 | 2 | this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; |
| 666 | 2 | if (connectionPool != null) { |
| 667 | 0 | connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); |
| 668 | } | |
| 669 | 2 | } |
| 670 | ||
| 671 | /** | |
| 672 | * The indication of whether objects will be validated by the idle object | |
| 673 | * evictor (if any). If an object fails to validate, it will be dropped | |
| 674 | * from the pool. | |
| 675 | */ | |
| 676 | 398 | protected boolean testWhileIdle = false; |
| 677 | ||
| 678 | /** | |
| 679 | * Returns the value of the {@link #testWhileIdle} property. | |
| 680 | * | |
| 681 | * @return true if objects examined by the idle object evictor are | |
| 682 | * validated | |
| 683 | * @see #testWhileIdle | |
| 684 | */ | |
| 685 | public synchronized boolean getTestWhileIdle() { | |
| 686 | 34 | return this.testWhileIdle; |
| 687 | } | |
| 688 | ||
| 689 | /** | |
| 690 | * Sets the <code>testWhileIdle</code> property. This property determines | |
| 691 | * whether or not the idle object evictor will validate connections. For a | |
| 692 | * <code>true</code> value to have any effect, the | |
| 693 | * <code>validationQuery</code> property must be set to a non-null string. | |
| 694 | * | |
| 695 | * @param testWhileIdle new value for testWhileIdle property | |
| 696 | */ | |
| 697 | public synchronized void setTestWhileIdle(boolean testWhileIdle) { | |
| 698 | 44 | this.testWhileIdle = testWhileIdle; |
| 699 | 44 | if (connectionPool != null) { |
| 700 | 0 | connectionPool.setTestWhileIdle(testWhileIdle); |
| 701 | } | |
| 702 | 44 | } |
| 703 | ||
| 704 | /** | |
| 705 | * [Read Only] The current number of active connections that have been | |
| 706 | * allocated from this data source. | |
| 707 | * | |
| 708 | * @return the current number of active connections | |
| 709 | */ | |
| 710 | public synchronized int getNumActive() { | |
| 711 | 50 | if (connectionPool != null) { |
| 712 | 50 | return connectionPool.getNumActive(); |
| 713 | } else { | |
| 714 | 0 | return 0; |
| 715 | } | |
| 716 | } | |
| 717 | ||
| 718 | ||
| 719 | /** | |
| 720 | * [Read Only] The current number of idle connections that are waiting | |
| 721 | * to be allocated from this data source. | |
| 722 | * | |
| 723 | * @return the current number of idle connections | |
| 724 | */ | |
| 725 | public synchronized int getNumIdle() { | |
| 726 | 20 | if (connectionPool != null) { |
| 727 | 20 | return connectionPool.getNumIdle(); |
| 728 | } else { | |
| 729 | 0 | return 0; |
| 730 | } | |
| 731 | } | |
| 732 | ||
| 733 | /** | |
| 734 | * The connection password to be passed to our JDBC driver to establish | |
| 735 | * a connection. | |
| 736 | */ | |
| 737 | 398 | protected volatile String password = null; |
| 738 | ||
| 739 | /** | |
| 740 | * Returns the password passed to the JDBC driver to establish connections. | |
| 741 | * | |
| 742 | * @return the connection password | |
| 743 | */ | |
| 744 | public String getPassword() { | |
| 745 | 2 | return this.password; |
| 746 | } | |
| 747 | ||
| 748 | /** | |
| 749 | * <p>Sets the {@link #password}.</p> | |
| 750 | * <p> | |
| 751 | * Note: this method currently has no effect once the pool has been | |
| 752 | * initialized. The pool is initialized the first time one of the | |
| 753 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 754 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 755 | * | |
| 756 | * @param password new value for the password | |
| 757 | */ | |
| 758 | public void setPassword(String password) { | |
| 759 | 394 | this.password = password; |
| 760 | 394 | this.restartNeeded = true; |
| 761 | 394 | } |
| 762 | ||
| 763 | /** | |
| 764 | * The connection URL to be passed to our JDBC driver to establish | |
| 765 | * a connection. | |
| 766 | */ | |
| 767 | 398 | protected String url = null; |
| 768 | ||
| 769 | /** | |
| 770 | * Returns the JDBC connection {@link #url} property. | |
| 771 | * | |
| 772 | * @return the {@link #url} passed to the JDBC driver to establish | |
| 773 | * connections | |
| 774 | */ | |
| 775 | public synchronized String getUrl() { | |
| 776 | 2 | return this.url; |
| 777 | } | |
| 778 | ||
| 779 | /** | |
| 780 | * <p>Sets the {@link #url}.</p> | |
| 781 | * <p> | |
| 782 | * Note: this method currently has no effect once the pool has been | |
| 783 | * initialized. The pool is initialized the first time one of the | |
| 784 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 785 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 786 | * | |
| 787 | * @param url the new value for the JDBC connection url | |
| 788 | */ | |
| 789 | public synchronized void setUrl(String url) { | |
| 790 | 394 | this.url = url; |
| 791 | 394 | this.restartNeeded = true; |
| 792 | 394 | } |
| 793 | ||
| 794 | /** | |
| 795 | * The connection username to be passed to our JDBC driver to | |
| 796 | * establish a connection. | |
| 797 | */ | |
| 798 | 398 | protected String username = null; |
| 799 | ||
| 800 | /** | |
| 801 | * Returns the JDBC connection {@link #username} property. | |
| 802 | * | |
| 803 | * @return the {@link #username} passed to the JDBC driver to establish | |
| 804 | * connections | |
| 805 | */ | |
| 806 | public String getUsername() { | |
| 807 | 2 | return this.username; |
| 808 | } | |
| 809 | ||
| 810 | /** | |
| 811 | * <p>Sets the {@link #username}.</p> | |
| 812 | * <p> | |
| 813 | * Note: this method currently has no effect once the pool has been | |
| 814 | * initialized. The pool is initialized the first time one of the | |
| 815 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 816 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 817 | * | |
| 818 | * @param username the new value for the JDBC connection username | |
| 819 | */ | |
| 820 | public void setUsername(String username) { | |
| 821 | 394 | this.username = username; |
| 822 | 394 | this.restartNeeded = true; |
| 823 | 394 | } |
| 824 | ||
| 825 | /** | |
| 826 | * The SQL query that will be used to validate connections from this pool | |
| 827 | * before returning them to the caller. If specified, this query | |
| 828 | * <strong>MUST</strong> be an SQL SELECT statement that returns at least | |
| 829 | * one row. | |
| 830 | */ | |
| 831 | 398 | protected volatile String validationQuery = null; |
| 832 | ||
| 833 | /** | |
| 834 | * Returns the validation query used to validate connections before | |
| 835 | * returning them. | |
| 836 | * | |
| 837 | * @return the SQL validation query | |
| 838 | * @see #validationQuery | |
| 839 | */ | |
| 840 | public String getValidationQuery() { | |
| 841 | 26 | return this.validationQuery; |
| 842 | } | |
| 843 | ||
| 844 | /** | |
| 845 | * <p>Sets the {@link #validationQuery}.</p> | |
| 846 | * <p> | |
| 847 | * Note: this method currently has no effect once the pool has been | |
| 848 | * initialized. The pool is initialized the first time one of the | |
| 849 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 850 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 851 | * | |
| 852 | * @param validationQuery the new value for the validation query | |
| 853 | */ | |
| 854 | public void setValidationQuery(String validationQuery) { | |
| 855 | 432 | if ((validationQuery != null) && (validationQuery.trim().length() > 0)) { |
| 856 | 408 | this.validationQuery = validationQuery; |
| 857 | } else { | |
| 858 | 24 | this.validationQuery = null; |
| 859 | } | |
| 860 | 432 | this.restartNeeded = true; |
| 861 | 432 | } |
| 862 | ||
| 863 | /** | |
| 864 | * Timeout in seconds before connection validation queries fail. | |
| 865 | * | |
| 866 | * @since 1.3 | |
| 867 | */ | |
| 868 | 398 | protected volatile int validationQueryTimeout = -1; |
| 869 | ||
| 870 | /** | |
| 871 | * Returns the validation query timeout. | |
| 872 | * | |
| 873 | * @return the timeout in seconds before connection validation queries fail. | |
| 874 | * @since 1.3 | |
| 875 | */ | |
| 876 | public int getValidationQueryTimeout() { | |
| 877 | 2 | return validationQueryTimeout; |
| 878 | } | |
| 879 | ||
| 880 | /** | |
| 881 | * Sets the validation query timeout, the amount of time, in seconds, that | |
| 882 | * connection validation will wait for a response from the database when | |
| 883 | * executing a validation query. Use a value less than or equal to 0 for | |
| 884 | * no timeout. | |
| 885 | * <p> | |
| 886 | * Note: this method currently has no effect once the pool has been | |
| 887 | * initialized. The pool is initialized the first time one of the | |
| 888 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 889 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 890 | * | |
| 891 | * @param timeout new validation query timeout value in seconds | |
| 892 | * @since 1.3 | |
| 893 | */ | |
| 894 | public void setValidationQueryTimeout(int timeout) { | |
| 895 | 34 | this.validationQueryTimeout = timeout; |
| 896 | 34 | restartNeeded = true; |
| 897 | 34 | } |
| 898 | ||
| 899 | /** | |
| 900 | * These SQL statements run once after a Connection is created. | |
| 901 | * <p> | |
| 902 | * This property can be used for example to run ALTER SESSION SET | |
| 903 | * NLS_SORT=XCYECH in an Oracle Database only once after connection | |
| 904 | * creation. | |
| 905 | * </p> | |
| 906 | * | |
| 907 | * @since 1.3 | |
| 908 | */ | |
| 909 | protected volatile List connectionInitSqls; | |
| 910 | ||
| 911 | /** | |
| 912 | * Returns the list of SQL statements executed when a physical connection | |
| 913 | * is first created. Returns an empty list if there are no initialization | |
| 914 | * statements configured. | |
| 915 | * | |
| 916 | * @return initialization SQL statements | |
| 917 | * @since 1.3 | |
| 918 | */ | |
| 919 | public Collection getConnectionInitSqls() { | |
| 920 | 32 | Collection result = connectionInitSqls; |
| 921 | 32 | if (result == null) { |
| 922 | 32 | return Collections.EMPTY_LIST; |
| 923 | } | |
| 924 | 0 | return result; |
| 925 | } | |
| 926 | ||
| 927 | /** | |
| 928 | * Sets the list of SQL statements to be executed when a physical | |
| 929 | * connection is first created. | |
| 930 | * <p> | |
| 931 | * Note: this method currently has no effect once the pool has been | |
| 932 | * initialized. The pool is initialized the first time one of the | |
| 933 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 934 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 935 | * | |
| 936 | * @param connectionInitSqls Collection of SQL statements to execute | |
| 937 | * on connection creation | |
| 938 | */ | |
| 939 | public void setConnectionInitSqls(Collection connectionInitSqls) { | |
| 940 | 408 | if ((connectionInitSqls != null) && (connectionInitSqls.size() > 0)) { |
| 941 | 400 | ArrayList newVal = null; |
| 942 | 400 | for (Iterator iterator = connectionInitSqls.iterator(); |
| 943 | 1200 | iterator.hasNext();) { |
| 944 | 800 | Object o = iterator.next(); |
| 945 | 800 | if (o != null) { |
| 946 | 800 | String s = o.toString(); |
| 947 | 800 | if (s.trim().length() > 0) { |
| 948 | 784 | if (newVal == null) { |
| 949 | 392 | newVal = new ArrayList(); |
| 950 | } | |
| 951 | 784 | newVal.add(s); |
| 952 | } | |
| 953 | } | |
| 954 | 800 | } |
| 955 | 400 | this.connectionInitSqls = newVal; |
| 956 | 400 | } else { |
| 957 | 8 | this.connectionInitSqls = null; |
| 958 | } | |
| 959 | 408 | this.restartNeeded = true; |
| 960 | 408 | } |
| 961 | ||
| 962 | ||
| 963 | /** | |
| 964 | * Controls access to the underlying connection. | |
| 965 | */ | |
| 966 | 398 | private boolean accessToUnderlyingConnectionAllowed = false; |
| 967 | ||
| 968 | /** | |
| 969 | * Returns the value of the accessToUnderlyingConnectionAllowed property. | |
| 970 | * | |
| 971 | * @return true if access to the underlying connection is allowed, false | |
| 972 | * otherwise. | |
| 973 | */ | |
| 974 | public synchronized boolean isAccessToUnderlyingConnectionAllowed() { | |
| 975 | 336 | return this.accessToUnderlyingConnectionAllowed; |
| 976 | } | |
| 977 | ||
| 978 | /** | |
| 979 | * <p>Sets the value of the accessToUnderlyingConnectionAllowed property. | |
| 980 | * It controls if the PoolGuard allows access to the underlying connection. | |
| 981 | * (Default: false)</p> | |
| 982 | * <p> | |
| 983 | * Note: this method currently has no effect once the pool has been | |
| 984 | * initialized. The pool is initialized the first time one of the | |
| 985 | * following methods is invoked: <code>getConnection, setLogwriter, | |
| 986 | * setLoginTimeout, getLoginTimeout, getLogWriter.</code></p> | |
| 987 | * | |
| 988 | * @param allow Access to the underlying connection is granted when true. | |
| 989 | */ | |
| 990 | public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) { | |
| 991 | 50 | this.accessToUnderlyingConnectionAllowed = allow; |
| 992 | 50 | this.restartNeeded = true; |
| 993 | 50 | } |
| 994 | ||
| 995 | // ----------------------------------------------------- Instance Variables | |
| 996 | ||
| 997 | // TODO: review & make isRestartNeeded() public, restartNeeded protected | |
| 998 | ||
| 999 | /** | |
| 1000 | * A property setter has been invoked that will require the connection | |
| 1001 | * pool to be re-initialized. Currently, restart is not triggered, so | |
| 1002 | * this property has no effect. | |
| 1003 | */ | |
| 1004 | 398 | private volatile boolean restartNeeded = false; |
| 1005 | ||
| 1006 | /** | |
| 1007 | * Returns whether or not a restart is needed. | |
| 1008 | * | |
| 1009 | * Note: restart is not currently triggered by property changes. | |
| 1010 | * | |
| 1011 | * @return true if a restart is needed | |
| 1012 | */ | |
| 1013 | private boolean isRestartNeeded() { | |
| 1014 | 0 | return restartNeeded; |
| 1015 | } | |
| 1016 | ||
| 1017 | /** | |
| 1018 | * The object pool that internally manages our connections. | |
| 1019 | */ | |
| 1020 | 398 | protected volatile GenericObjectPool connectionPool = null; |
| 1021 | ||
| 1022 | /** | |
| 1023 | * The connection properties that will be sent to our JDBC driver when | |
| 1024 | * establishing new connections. <strong>NOTE</strong> - The "user" and | |
| 1025 | * "password" properties will be passed explicitly, so they do not need | |
| 1026 | * to be included here. | |
| 1027 | */ | |
| 1028 | 398 | protected Properties connectionProperties = new Properties(); |
| 1029 | ||
| 1030 | /** | |
| 1031 | * The data source we will use to manage connections. This object should | |
| 1032 | * be acquired <strong>ONLY</strong> by calls to the | |
| 1033 | * <code>createDataSource()</code> method. | |
| 1034 | */ | |
| 1035 | 398 | protected volatile DataSource dataSource = null; |
| 1036 | ||
| 1037 | /** | |
| 1038 | * The PrintWriter to which log messages should be directed. | |
| 1039 | */ | |
| 1040 | 398 | protected PrintWriter logWriter = new PrintWriter(System.out); |
| 1041 | ||
| 1042 | ||
| 1043 | // ----------------------------------------------------- DataSource Methods | |
| 1044 | ||
| 1045 | ||
| 1046 | /** | |
| 1047 | * Create (if necessary) and return a connection to the database. | |
| 1048 | * | |
| 1049 | * @throws SQLException if a database access error occurs | |
| 1050 | * @return a database connection | |
| 1051 | */ | |
| 1052 | public Connection getConnection() throws SQLException { | |
| 1053 | 6278 | return createDataSource().getConnection(); |
| 1054 | } | |
| 1055 | ||
| 1056 | ||
| 1057 | /** | |
| 1058 | * <strong>BasicDataSource does NOT support this method. </strong> | |
| 1059 | * | |
| 1060 | * @param user Database user on whose behalf the Connection | |
| 1061 | * is being made | |
| 1062 | * @param pass The database user's password | |
| 1063 | * | |
| 1064 | * @throws UnsupportedOperationException | |
| 1065 | * @throws SQLException if a database access error occurs | |
| 1066 | * @return nothing - always throws UnsupportedOperationException | |
| 1067 | */ | |
| 1068 | public Connection getConnection(String user, String pass) throws SQLException { | |
| 1069 | // This method isn't supported by the PoolingDataSource returned by | |
| 1070 | // the createDataSource | |
| 1071 | 0 | throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| 1072 | // return createDataSource().getConnection(username, password); | |
| 1073 | } | |
| 1074 | ||
| 1075 | ||
| 1076 | /** | |
| 1077 | * <strong>BasicDataSource does NOT support this method. </strong> | |
| 1078 | * | |
| 1079 | * <p>Returns the login timeout (in seconds) for connecting to the database. | |
| 1080 | * </p> | |
| 1081 | * <p>Calls {@link #createDataSource()}, so has the side effect | |
| 1082 | * of initializing the connection pool.</p> | |
| 1083 | * | |
| 1084 | * @throws SQLException if a database access error occurs | |
| 1085 | * @throws UnsupportedOperationException If the DataSource implementation | |
| 1086 | * does not support the login timeout feature. | |
| 1087 | * @return login timeout in seconds | |
| 1088 | */ | |
| 1089 | public int getLoginTimeout() throws SQLException { | |
| 1090 | // This method isn't supported by the PoolingDataSource returned by | |
| 1091 | // the createDataSource | |
| 1092 | 0 | throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| 1093 | //return createDataSource().getLoginTimeout(); | |
| 1094 | } | |
| 1095 | ||
| 1096 | ||
| 1097 | /** | |
| 1098 | * <p>Returns the log writer being used by this data source.</p> | |
| 1099 | * <p> | |
| 1100 | * Calls {@link #createDataSource()}, so has the side effect | |
| 1101 | * of initializing the connection pool.</p> | |
| 1102 | * | |
| 1103 | * @throws SQLException if a database access error occurs | |
| 1104 | * @return log writer in use | |
| 1105 | */ | |
| 1106 | public PrintWriter getLogWriter() throws SQLException { | |
| 1107 | 2 | return createDataSource().getLogWriter(); |
| 1108 | } | |
| 1109 | ||
| 1110 | ||
| 1111 | /** | |
| 1112 | * <strong>BasicDataSource does NOT support this method. </strong> | |
| 1113 | * | |
| 1114 | * <p>Set the login timeout (in seconds) for connecting to the | |
| 1115 | * database.</p> | |
| 1116 | * <p> | |
| 1117 | * Calls {@link #createDataSource()}, so has the side effect | |
| 1118 | * of initializing the connection pool.</p> | |
| 1119 | * | |
| 1120 | * @param loginTimeout The new login timeout, or zero for no timeout | |
| 1121 | * @throws UnsupportedOperationException If the DataSource implementation | |
| 1122 | * does not support the login timeout feature. | |
| 1123 | * @throws SQLException if a database access error occurs | |
| 1124 | */ | |
| 1125 | public void setLoginTimeout(int loginTimeout) throws SQLException { | |
| 1126 | // This method isn't supported by the PoolingDataSource returned by | |
| 1127 | // the createDataSource | |
| 1128 | 0 | throw new UnsupportedOperationException("Not supported by BasicDataSource"); |
| 1129 | //createDataSource().setLoginTimeout(loginTimeout); | |
| 1130 | } | |
| 1131 | ||
| 1132 | ||
| 1133 | /** | |
| 1134 | * <p>Sets the log writer being used by this data source.</p> | |
| 1135 | * <p> | |
| 1136 | * Calls {@link #createDataSource()}, so has the side effect | |
| 1137 | * of initializing the connection pool.</p> | |
| 1138 | * | |
| 1139 | * @param logWriter The new log writer | |
| 1140 | * @throws SQLException if a database access error occurs | |
| 1141 | */ | |
| 1142 | public void setLogWriter(PrintWriter logWriter) throws SQLException { | |
| 1143 | 0 | createDataSource().setLogWriter(logWriter); |
| 1144 | 0 | this.logWriter = logWriter; |
| 1145 | 0 | } |
| 1146 | ||
| 1147 | private AbandonedConfig abandonedConfig; | |
| 1148 | ||
| 1149 | /** | |
| 1150 | * Flag to remove abandoned connections if they exceed the | |
| 1151 | * removeAbandonedTimout. | |
| 1152 | * | |
| 1153 | * Set to true or false, default false. | |
| 1154 | * If set to true a connection is considered abandoned and eligible | |
| 1155 | * for removal if it has been idle longer than the removeAbandonedTimeout. | |
| 1156 | * Setting this to true can recover db connections from poorly written | |
| 1157 | * applications which fail to close a connection. | |
| 1158 | * <p> | |
| 1159 | * Abandonded connections are identified and removed when | |
| 1160 | * {@link #getConnection()} is invoked and the following conditions hold | |
| 1161 | * <ul><li>{@link #getRemoveAbandoned()} = true </li> | |
| 1162 | * <li>{@link #getNumActive()} > {@link #getMaxActive()} - 3 </li> | |
| 1163 | * <li>{@link #getNumIdle()} < 2 </li></ul></p> | |
| 1164 | */ | |
| 1165 | public boolean getRemoveAbandoned() { | |
| 1166 | 2 | if (abandonedConfig != null) { |
| 1167 | 2 | return abandonedConfig.getRemoveAbandoned(); |
| 1168 | } | |
| 1169 | 0 | return false; |
| 1170 | } | |
| 1171 | ||
| 1172 | /** | |
| 1173 | * @param removeAbandoned new removeAbandoned property value | |
| 1174 | * @see #getRemoveAbandoned() | |
| 1175 | */ | |
| 1176 | public void setRemoveAbandoned(boolean removeAbandoned) { | |
| 1177 | 102 | if (abandonedConfig == null) { |
| 1178 | 2 | abandonedConfig = new AbandonedConfig(); |
| 1179 | } | |
| 1180 | 102 | abandonedConfig.setRemoveAbandoned(removeAbandoned); |
| 1181 | 102 | this.restartNeeded = true; |
| 1182 | 102 | } |
| 1183 | ||
| 1184 | /** | |
| 1185 | * Timeout in seconds before an abandoned connection can be removed. | |
| 1186 | * | |
| 1187 | * Defaults to 300 seconds. | |
| 1188 | * @return abandoned connection timeout | |
| 1189 | */ | |
| 1190 | public int getRemoveAbandonedTimeout() { | |
| 1191 | 2 | if (abandonedConfig != null) { |
| 1192 | 2 | return abandonedConfig.getRemoveAbandonedTimeout(); |
| 1193 | } | |
| 1194 | 0 | return 300; |
| 1195 | } | |
| 1196 | ||
| 1197 | /** | |
| 1198 | * @param removeAbandonedTimeout new removeAbandonedTimeout value | |
| 1199 | */ | |
| 1200 | public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) { | |
| 1201 | 112 | if (abandonedConfig == null) { |
| 1202 | 0 | abandonedConfig = new AbandonedConfig(); |
| 1203 | } | |
| 1204 | 112 | abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout); |
| 1205 | 112 | this.restartNeeded = true; |
| 1206 | 112 | } |
| 1207 | ||
| 1208 | /** | |
| 1209 | * <p>Flag to log stack traces for application code which abandoned | |
| 1210 | * a Statement or Connection. | |
| 1211 | * </p> | |
| 1212 | * <p>Defaults to false. | |
| 1213 | * </p> | |
| 1214 | * <p>Logging of abandoned Statements and Connections adds overhead | |
| 1215 | * for every Connection open or new Statement because a stack | |
| 1216 | * trace has to be generated. </p> | |
| 1217 | */ | |
| 1218 | public boolean getLogAbandoned() { | |
| 1219 | 2 | if (abandonedConfig != null) { |
| 1220 | 2 | return abandonedConfig.getLogAbandoned(); |
| 1221 | } | |
| 1222 | 0 | return false; |
| 1223 | } | |
| 1224 | ||
| 1225 | /** | |
| 1226 | * @param logAbandoned new logAbandoned property value | |
| 1227 | */ | |
| 1228 | public void setLogAbandoned(boolean logAbandoned) { | |
| 1229 | 102 | if (abandonedConfig == null) { |
| 1230 | 100 | abandonedConfig = new AbandonedConfig(); |
| 1231 | } | |
| 1232 | 102 | abandonedConfig.setLogAbandoned(logAbandoned); |
| 1233 | 102 | this.restartNeeded = true; |
| 1234 | 102 | } |
| 1235 | ||
| 1236 | // --------------------------------------------------------- Public Methods | |
| 1237 | ||
| 1238 | /** | |
| 1239 | * Add a custom connection property to the set that will be passed to our | |
| 1240 | * JDBC driver. This <strong>MUST</strong> be called before the first | |
| 1241 | * connection is retrieved (along with all the other configuration | |
| 1242 | * property setters). Calls to this method after the connection pool | |
| 1243 | * has been initialized have no effect. | |
| 1244 | * | |
| 1245 | * @param name Name of the custom connection property | |
| 1246 | * @param value Value of the custom connection property | |
| 1247 | */ | |
| 1248 | public void addConnectionProperty(String name, String value) { | |
| 1249 | 0 | connectionProperties.put(name, value); |
| 1250 | 0 | this.restartNeeded = true; |
| 1251 | 0 | } |
| 1252 | ||
| 1253 | /** | |
| 1254 | * Remove a custom connection property. | |
| 1255 | * | |
| 1256 | * @param name Name of the custom connection property to remove | |
| 1257 | * @see #addConnectionProperty(String, String) | |
| 1258 | */ | |
| 1259 | public void removeConnectionProperty(String name) { | |
| 1260 | 0 | connectionProperties.remove(name); |
| 1261 | 0 | this.restartNeeded = true; |
| 1262 | 0 | } |
| 1263 | ||
| 1264 | /** | |
| 1265 | * Sets the connection properties passed to driver.connect(...). | |
| 1266 | * | |
| 1267 | * Format of the string must be [propertyName=property;]* | |
| 1268 | * | |
| 1269 | * NOTE - The "user" and "password" properties will be added | |
| 1270 | * explicitly, so they do not need to be included here. | |
| 1271 | * | |
| 1272 | * @param connectionProperties the connection properties used to | |
| 1273 | * create new connections | |
| 1274 | */ | |
| 1275 | public void setConnectionProperties(String connectionProperties) { | |
| 1276 | 64 | if (connectionProperties == null) throw new NullPointerException("connectionProperties is null"); |
| 1277 | ||
| 1278 | 56 | String[] entries = connectionProperties.split(";"); |
| 1279 | 56 | Properties properties = new Properties(); |
| 1280 | 152 | for (int i = 0; i < entries.length; i++) { |
| 1281 | 96 | String entry = entries[i]; |
| 1282 | 96 | if (entry.length() > 0) { |
| 1283 | 96 | int index = entry.indexOf('='); |
| 1284 | 96 | if (index > 0) { |
| 1285 | 80 | String name = entry.substring(0, index); |
| 1286 | 80 | String value = entry.substring(index + 1); |
| 1287 | 80 | properties.setProperty(name, value); |
| 1288 | 80 | } else { |
| 1289 | // no value is empty string which is how java.util.Properties works | |
| 1290 | 16 | properties.setProperty(entry, ""); |
| 1291 | } | |
| 1292 | } | |
| 1293 | } | |
| 1294 | 56 | this.connectionProperties = properties; |
| 1295 | 56 | this.restartNeeded = true; |
| 1296 | 56 | } |
| 1297 | ||
| 1298 | protected boolean closed; | |
| 1299 | ||
| 1300 | /** | |
| 1301 | * <p>Closes and releases all idle connections that are currently stored in the connection pool | |
| 1302 | * associated with this data source.</p> | |
| 1303 | * | |
| 1304 | * <p>Connections that are checked out to clients when this method is invoked are not affected. | |
| 1305 | * When client applications subsequently invoke {@link Connection#close()} to return | |
| 1306 | * these connections to the pool, the underlying JDBC connections are closed.</p> | |
| 1307 | * | |
| 1308 | * <p>Attempts to acquire connections using {@link #getConnection()} after this method has been | |
| 1309 | * invoked result in SQLExceptions.<p> | |
| 1310 | * | |
| 1311 | * <p>This method is idempotent - i.e., closing an already closed BasicDataSource has no effect | |
| 1312 | * and does not generate exceptions.</p> | |
| 1313 | * | |
| 1314 | * @throws SQLException if an error occurs closing idle connections | |
| 1315 | */ | |
| 1316 | public synchronized void close() throws SQLException { | |
| 1317 | 408 | closed = true; |
| 1318 | 408 | GenericObjectPool oldpool = connectionPool; |
| 1319 | 408 | connectionPool = null; |
| 1320 | 408 | dataSource = null; |
| 1321 | try { | |
| 1322 | 408 | if (oldpool != null) { |
| 1323 | 348 | oldpool.close(); |
| 1324 | } | |
| 1325 | 0 | } catch(SQLException e) { |
| 1326 | 0 | throw e; |
| 1327 | 0 | } catch(RuntimeException e) { |
| 1328 | 0 | throw e; |
| 1329 | 0 | } catch(Exception e) { |
| 1330 | 0 | throw new SQLNestedException("Cannot close connection pool", e); |
| 1331 | 408 | } |
| 1332 | 408 | } |
| 1333 | ||
| 1334 | /** | |
| 1335 | * If true, this data source is closed and no more connections can be retrieved from this datasource. | |
| 1336 | * @return true, if the data source is closed; false otherwise | |
| 1337 | */ | |
| 1338 | public synchronized boolean isClosed() { | |
| 1339 | 0 | return closed; |
| 1340 | } | |
| 1341 | ||
| 1342 | /* JDBC_4_ANT_KEY_BEGIN */ | |
| 1343 | public boolean isWrapperFor(Class<?> iface) throws SQLException { | |
| 1344 | 0 | return false; |
| 1345 | } | |
| 1346 | ||
| 1347 | public <T> T unwrap(Class<T> iface) throws SQLException { | |
| 1348 | 0 | throw new SQLException("BasicDataSource is not a wrapper."); |
| 1349 | } | |
| 1350 | /* JDBC_4_ANT_KEY_END */ | |
| 1351 | ||
| 1352 | ||
| 1353 | // ------------------------------------------------------ Protected Methods | |
| 1354 | ||
| 1355 | ||
| 1356 | /** | |
| 1357 | * <p>Create (if necessary) and return the internal data source we are | |
| 1358 | * using to manage our connections.</p> | |
| 1359 | * | |
| 1360 | * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the | |
| 1361 | * "double checked locking" idiom in an attempt to avoid synchronizing | |
| 1362 | * on every single call to this method. However, this idiom fails to | |
| 1363 | * work correctly in the face of some optimizations that are legal for | |
| 1364 | * a JVM to perform.</p> | |
| 1365 | * | |
| 1366 | * @throws SQLException if the object pool cannot be created. | |
| 1367 | */ | |
| 1368 | protected synchronized DataSource createDataSource() | |
| 1369 | throws SQLException { | |
| 1370 | 6280 | if (closed) { |
| 1371 | 8 | throw new SQLException("Data source is closed"); |
| 1372 | } | |
| 1373 | ||
| 1374 | // Return the pool if we have already created it | |
| 1375 | 6272 | if (dataSource != null) { |
| 1376 | 5850 | return (dataSource); |
| 1377 | } | |
| 1378 | ||
| 1379 | // create factory which returns raw physical connections | |
| 1380 | 422 | ConnectionFactory driverConnectionFactory = createConnectionFactory(); |
| 1381 | ||
| 1382 | // create a pool for our connections | |
| 1383 | 422 | createConnectionPool(); |
| 1384 | ||
| 1385 | // Set up statement pool, if desired | |
| 1386 | 422 | GenericKeyedObjectPoolFactory statementPoolFactory = null; |
| 1387 | 422 | if (isPoolPreparedStatements()) { |
| 1388 | 92 | statementPoolFactory = new GenericKeyedObjectPoolFactory(null, |
| 1389 | -1, // unlimited maxActive (per key) | |
| 1390 | GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL, | |
| 1391 | 0, // maxWait | |
| 1392 | 1, // maxIdle (per key) | |
| 1393 | maxOpenPreparedStatements); | |
| 1394 | } | |
| 1395 | ||
| 1396 | // Set up the poolable connection factory | |
| 1397 | 422 | createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig); |
| 1398 | ||
| 1399 | // Create and return the pooling data source to manage the connections | |
| 1400 | 318 | createDataSourceInstance(); |
| 1401 | ||
| 1402 | try { | |
| 1403 | 408 | for (int i = 0 ; i < initialSize ; i++) { |
| 1404 | 90 | connectionPool.addObject(); |
| 1405 | } | |
| 1406 | 0 | } catch (Exception e) { |
| 1407 | 0 | throw new SQLNestedException("Error preloading the connection pool", e); |
| 1408 | 318 | } |
| 1409 | ||
| 1410 | 318 | return dataSource; |
| 1411 | } | |
| 1412 | ||
| 1413 | /** | |
| 1414 | * Creates a JDBC connection factory for this datasource. This method only | |
| 1415 | * exists so subclasses can replace the implementation class. | |
| 1416 | */ | |
| 1417 | protected ConnectionFactory createConnectionFactory() throws SQLException { | |
| 1418 | // Load the JDBC driver class | |
| 1419 | 422 | Class driverFromCCL = null; |
| 1420 | 422 | if (driverClassName != null) { |
| 1421 | try { | |
| 1422 | try { | |
| 1423 | 422 | if (driverClassLoader == null) { |
| 1424 | 422 | Class.forName(driverClassName); |
| 1425 | } else { | |
| 1426 | 0 | Class.forName(driverClassName, true, driverClassLoader); |
| 1427 | } | |
| 1428 | 0 | } catch (ClassNotFoundException cnfe) { |
| 1429 | 0 | driverFromCCL = Thread.currentThread( |
| 1430 | ).getContextClassLoader().loadClass( | |
| 1431 | driverClassName); | |
| 1432 | 422 | } |
| 1433 | 0 | } catch (Throwable t) { |
| 1434 | 0 | String message = "Cannot load JDBC driver class '" + |
| 1435 | driverClassName + "'"; | |
| 1436 | 0 | logWriter.println(message); |
| 1437 | 0 | t.printStackTrace(logWriter); |
| 1438 | 0 | throw new SQLNestedException(message, t); |
| 1439 | 422 | } |
| 1440 | } | |
| 1441 | ||
| 1442 | // Create a JDBC driver instance | |
| 1443 | 422 | Driver driver = null; |
| 1444 | try { | |
| 1445 | 422 | if (driverFromCCL == null) { |
| 1446 | 422 | driver = DriverManager.getDriver(url); |
| 1447 | } else { | |
| 1448 | // Usage of DriverManager is not possible, as it does not | |
| 1449 | // respect the ContextClassLoader | |
| 1450 | 0 | driver = (Driver) driverFromCCL.newInstance(); |
| 1451 | 0 | if (!driver.acceptsURL(url)) { |
| 1452 | 0 | throw new SQLException("No suitable driver", "08001"); |
| 1453 | } | |
| 1454 | } | |
| 1455 | 0 | } catch (Throwable t) { |
| 1456 | 0 | String message = "Cannot create JDBC driver of class '" + |
| 1457 | (driverClassName != null ? driverClassName : "") + | |
| 1458 | "' for connect URL '" + url + "'"; | |
| 1459 | 0 | logWriter.println(message); |
| 1460 | 0 | t.printStackTrace(logWriter); |
| 1461 | 0 | throw new SQLNestedException(message, t); |
| 1462 | 422 | } |
| 1463 | ||
| 1464 | // Can't test without a validationQuery | |
| 1465 | 422 | if (validationQuery == null) { |
| 1466 | 10 | setTestOnBorrow(false); |
| 1467 | 10 | setTestOnReturn(false); |
| 1468 | 10 | setTestWhileIdle(false); |
| 1469 | } | |
| 1470 | ||
| 1471 | // Set up the driver connection factory we will use | |
| 1472 | 422 | String user = username; |
| 1473 | 422 | if (user != null) { |
| 1474 | 422 | connectionProperties.put("user", user); |
| 1475 | } else { | |
| 1476 | 0 | log("DBCP DataSource configured without a 'username'"); |
| 1477 | } | |
| 1478 | ||
| 1479 | 422 | String pwd = password; |
| 1480 | 422 | if (pwd != null) { |
| 1481 | 422 | connectionProperties.put("password", pwd); |
| 1482 | } else { | |
| 1483 | 0 | log("DBCP DataSource configured without a 'password'"); |
| 1484 | } | |
| 1485 | ||
| 1486 | 422 | ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driver, url, connectionProperties); |
| 1487 | 422 | return driverConnectionFactory; |
| 1488 | } | |
| 1489 | ||
| 1490 | /** | |
| 1491 | * Creates a connection pool for this datasource. This method only exists | |
| 1492 | * so subclasses can replace the implementation class. | |
| 1493 | */ | |
| 1494 | protected void createConnectionPool() { | |
| 1495 | // Create an object pool to contain our active connections | |
| 1496 | GenericObjectPool gop; | |
| 1497 | 422 | if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned())) { |
| 1498 | 92 | gop = new AbandonedObjectPool(null,abandonedConfig); |
| 1499 | } | |
| 1500 | else { | |
| 1501 | 330 | gop = new GenericObjectPool(); |
| 1502 | } | |
| 1503 | 422 | gop.setMaxActive(maxActive); |
| 1504 | 422 | gop.setMaxIdle(maxIdle); |
| 1505 | 422 | gop.setMinIdle(minIdle); |
| 1506 | 422 | gop.setMaxWait(maxWait); |
| 1507 | 422 | gop.setTestOnBorrow(testOnBorrow); |
| 1508 | 422 | gop.setTestOnReturn(testOnReturn); |
| 1509 | 422 | gop.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); |
| 1510 | 422 | gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun); |
| 1511 | 422 | gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); |
| 1512 | 422 | gop.setTestWhileIdle(testWhileIdle); |
| 1513 | 422 | connectionPool = gop; |
| 1514 | 422 | } |
| 1515 | ||
| 1516 | /** | |
| 1517 | * Creates the actual data source instance. This method only exists so | |
| 1518 | * subclasses can replace the implementation class. | |
| 1519 | * | |
| 1520 | * @throws SQLException if unable to create a datasource instance | |
| 1521 | */ | |
| 1522 | protected void createDataSourceInstance() throws SQLException { | |
| 1523 | 244 | PoolingDataSource pds = new PoolingDataSource(connectionPool); |
| 1524 | 244 | pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed()); |
| 1525 | 244 | pds.setLogWriter(logWriter); |
| 1526 | 244 | dataSource = pds; |
| 1527 | 244 | } |
| 1528 | ||
| 1529 | /** | |
| 1530 | * Creates the PoolableConnectionFactory and attaches it to the connection pool. This method only exists | |
| 1531 | * so subclasses can replace the default implementation. | |
| 1532 | * | |
| 1533 | * @param driverConnectionFactory JDBC connection factory | |
| 1534 | * @param statementPoolFactory statement pool factory (null if statement pooling is turned off) | |
| 1535 | * @param configuration abandoned connection tracking configuration (null if no tracking) | |
| 1536 | * @throws SQLException if an error occurs creating the PoolableConnectionFactory | |
| 1537 | */ | |
| 1538 | protected void createPoolableConnectionFactory(ConnectionFactory driverConnectionFactory, | |
| 1539 | KeyedObjectPoolFactory statementPoolFactory, AbandonedConfig configuration) throws SQLException { | |
| 1540 | 322 | PoolableConnectionFactory connectionFactory = null; |
| 1541 | try { | |
| 1542 | 322 | connectionFactory = |
| 1543 | new PoolableConnectionFactory(driverConnectionFactory, | |
| 1544 | connectionPool, | |
| 1545 | statementPoolFactory, | |
| 1546 | validationQuery, | |
| 1547 | validationQueryTimeout, | |
| 1548 | connectionInitSqls, | |
| 1549 | defaultReadOnly, | |
| 1550 | defaultAutoCommit, | |
| 1551 | defaultTransactionIsolation, | |
| 1552 | defaultCatalog, | |
| 1553 | configuration); | |
| 1554 | 322 | validateConnectionFactory(connectionFactory); |
| 1555 | 0 | } catch (RuntimeException e) { |
| 1556 | 0 | throw e; |
| 1557 | 78 | } catch (Exception e) { |
| 1558 | 78 | throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e); |
| 1559 | 244 | } |
| 1560 | 244 | } |
| 1561 | ||
| 1562 | protected static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception { | |
| 1563 | 422 | Connection conn = null; |
| 1564 | try { | |
| 1565 | 422 | conn = (Connection) connectionFactory.makeObject(); |
| 1566 | 334 | connectionFactory.activateObject(conn); |
| 1567 | 334 | connectionFactory.validateConnection(conn); |
| 1568 | 318 | connectionFactory.passivateObject(conn); |
| 1569 | } | |
| 1570 | finally { | |
| 1571 | 422 | connectionFactory.destroyObject(conn); |
| 1572 | 318 | } |
| 1573 | 318 | } |
| 1574 | ||
| 1575 | /** | |
| 1576 | * Not used currently | |
| 1577 | */ | |
| 1578 | private void restart() { | |
| 1579 | try { | |
| 1580 | 0 | close(); |
| 1581 | 0 | } catch (SQLException e) { |
| 1582 | 0 | log("Could not restart DataSource, cause: " + e.getMessage()); |
| 1583 | 0 | } |
| 1584 | 0 | } |
| 1585 | ||
| 1586 | protected void log(String message) { | |
| 1587 | 0 | if (logWriter != null) { |
| 1588 | 0 | logWriter.println(message); |
| 1589 | } | |
| 1590 | 0 | } |
| 1591 | } |