001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbcp2.datasources; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.sql.Connection; 022import java.sql.SQLException; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.NoSuchElementException; 026 027import javax.naming.NamingException; 028import javax.naming.Reference; 029import javax.naming.StringRefAddr; 030import javax.sql.ConnectionPoolDataSource; 031 032import org.apache.commons.dbcp2.SwallowedExceptionLogger; 033import org.apache.commons.logging.Log; 034import org.apache.commons.logging.LogFactory; 035import org.apache.commons.pool2.ObjectPool; 036import org.apache.commons.pool2.impl.GenericObjectPool; 037 038/** 039 * <p> 040 * A pooling <code>DataSource</code> appropriate for deployment within J2EE environment. There are many configuration 041 * options, most of which are defined in the parent class. This datasource uses individual pools per user, and some 042 * properties can be set specifically for a given user, if the deployment environment can support initialization of 043 * mapped properties. So for example, a pool of admin or write-access Connections can be guaranteed a certain number of 044 * connections, separate from a maximum set for users with read-only connections. 045 * </p> 046 * 047 * <p> 048 * User passwords can be changed without re-initializing the datasource. When a 049 * <code>getConnection(userName, password)</code> request is processed with a password that is different from those used 050 * to create connections in the pool associated with <code>userName</code>, an attempt is made to create a new 051 * connection using the supplied password and if this succeeds, the existing pool is cleared and a new pool is created 052 * for connections using the new password. 053 * </p> 054 * 055 * @since 2.0 056 */ 057public class PerUserPoolDataSource extends InstanceKeyDataSource { 058 059 private static final long serialVersionUID = 7872747993848065028L; 060 061 private static final Log log = LogFactory.getLog(PerUserPoolDataSource.class); 062 063 // Per user pool properties 064 private Map<String, Boolean> perUserBlockWhenExhausted; 065 private Map<String, String> perUserEvictionPolicyClassName; 066 private Map<String, Boolean> perUserLifo; 067 private Map<String, Integer> perUserMaxIdle; 068 private Map<String, Integer> perUserMaxTotal; 069 private Map<String, Long> perUserMaxWaitMillis; 070 private Map<String, Long> perUserMinEvictableIdleTimeMillis; 071 private Map<String, Integer> perUserMinIdle; 072 private Map<String, Integer> perUserNumTestsPerEvictionRun; 073 private Map<String, Long> perUserSoftMinEvictableIdleTimeMillis; 074 private Map<String, Boolean> perUserTestOnCreate; 075 private Map<String, Boolean> perUserTestOnBorrow; 076 private Map<String, Boolean> perUserTestOnReturn; 077 private Map<String, Boolean> perUserTestWhileIdle; 078 private Map<String, Long> perUserTimeBetweenEvictionRunsMillis; 079 080 // Per user connection properties 081 private Map<String, Boolean> perUserDefaultAutoCommit; 082 private Map<String, Integer> perUserDefaultTransactionIsolation; 083 private Map<String, Boolean> perUserDefaultReadOnly; 084 085 /** 086 * Map to keep track of Pools for a given user. 087 */ 088 private transient Map<PoolKey, PooledConnectionManager> managers = new HashMap<>(); 089 090 /** 091 * Default no-arg constructor for Serialization. 092 */ 093 public PerUserPoolDataSource() { 094 } 095 096 /** 097 * Clears pool(s) maintained by this data source. 098 * 099 * @see org.apache.commons.pool2.ObjectPool#clear() 100 * @since 2.3.0 101 */ 102 public void clear() { 103 for (final PooledConnectionManager manager : managers.values()) { 104 try { 105 getCPDSConnectionFactoryPool(manager).clear(); 106 } catch (final Exception closePoolException) { 107 // ignore and try to close others. 108 } 109 } 110 InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); 111 } 112 113 /** 114 * Closes pool(s) maintained by this data source. 115 * 116 * @see org.apache.commons.pool2.ObjectPool#close() 117 */ 118 @Override 119 public void close() { 120 for (final PooledConnectionManager manager : managers.values()) { 121 try { 122 getCPDSConnectionFactoryPool(manager).close(); 123 } catch (final Exception closePoolException) { 124 // ignore and try to close others. 125 } 126 } 127 InstanceKeyDataSourceFactory.removeInstance(getInstanceKey()); 128 } 129 130 private HashMap<String, Boolean> createMap() { 131 // Should there be a default size different than what this ctor provides? 132 return new HashMap<>(); 133 } 134 135 @Override 136 protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) { 137 return managers.get(getPoolKey(upKey.getUsername())); 138 } 139 140 private ObjectPool<PooledConnectionAndInfo> getCPDSConnectionFactoryPool(final PooledConnectionManager manager) { 141 return ((CPDSConnectionFactory) manager).getPool(); 142 } 143 144 /** 145 * Gets the number of active connections in the default pool. 146 * 147 * @return The number of active connections in the default pool. 148 */ 149 public int getNumActive() { 150 return getNumActive(null); 151 } 152 153 /** 154 * Gets the number of active connections in the pool for a given user. 155 * 156 * @param userName 157 * The user name key. 158 * @return The user specific value. 159 */ 160 @SuppressWarnings("resource") 161 public int getNumActive(final String userName) { 162 final ObjectPool<PooledConnectionAndInfo> pool = getPool(getPoolKey(userName)); 163 return pool == null ? 0 : pool.getNumActive(); 164 } 165 166 /** 167 * Gets the number of idle connections in the default pool. 168 * 169 * @return The number of idle connections in the default pool. 170 */ 171 public int getNumIdle() { 172 return getNumIdle(null); 173 } 174 175 /** 176 * Gets the number of idle connections in the pool for a given user. 177 * 178 * @param userName 179 * The user name key. 180 * @return The user specific value. 181 */ 182 @SuppressWarnings("resource") 183 public int getNumIdle(final String userName) { 184 final ObjectPool<PooledConnectionAndInfo> pool = getPool(getPoolKey(userName)); 185 return pool == null ? 0 : pool.getNumIdle(); 186 } 187 188 /** 189 * Gets the user specific value for {@link GenericObjectPool#getBlockWhenExhausted()} for the specified user's pool 190 * or the default if no user specific value is defined. 191 * 192 * @param userName 193 * The user name key. 194 * @return The user specific value. 195 */ 196 public boolean getPerUserBlockWhenExhausted(final String userName) { 197 Boolean value = null; 198 if (perUserBlockWhenExhausted != null) { 199 value = perUserBlockWhenExhausted.get(userName); 200 } 201 if (value == null) { 202 return getDefaultBlockWhenExhausted(); 203 } 204 return value.booleanValue(); 205 } 206 207 /** 208 * Gets the user specific default value for {@link Connection#setAutoCommit(boolean)} for the specified user's pool. 209 * 210 * @param userName 211 * The user name key. 212 * @return The user specific value. 213 */ 214 public Boolean getPerUserDefaultAutoCommit(final String userName) { 215 Boolean value = null; 216 if (perUserDefaultAutoCommit != null) { 217 value = perUserDefaultAutoCommit.get(userName); 218 } 219 return value; 220 } 221 222 /** 223 * Gets the user specific default value for {@link Connection#setReadOnly(boolean)} for the specified user's pool. 224 * 225 * @param userName 226 * The user name key. 227 * @return The user specific value. 228 */ 229 public Boolean getPerUserDefaultReadOnly(final String userName) { 230 Boolean value = null; 231 if (perUserDefaultReadOnly != null) { 232 value = perUserDefaultReadOnly.get(userName); 233 } 234 return value; 235 } 236 237 /** 238 * Gets the user specific default value for {@link Connection#setTransactionIsolation(int)} for the specified user's 239 * pool. 240 * 241 * @param userName 242 * The user name key. 243 * @return The user specific value. 244 */ 245 public Integer getPerUserDefaultTransactionIsolation(final String userName) { 246 Integer value = null; 247 if (perUserDefaultTransactionIsolation != null) { 248 value = perUserDefaultTransactionIsolation.get(userName); 249 } 250 return value; 251 } 252 253 /** 254 * Gets the user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's 255 * pool or the default if no user specific value is defined. 256 * 257 * @param userName 258 * The user name key. 259 * @return The user specific value. 260 */ 261 public String getPerUserEvictionPolicyClassName(final String userName) { 262 String value = null; 263 if (perUserEvictionPolicyClassName != null) { 264 value = perUserEvictionPolicyClassName.get(userName); 265 } 266 if (value == null) { 267 return getDefaultEvictionPolicyClassName(); 268 } 269 return value; 270 } 271 272 /** 273 * Gets the user specific value for {@link GenericObjectPool#getLifo()} for the specified user's pool or the default 274 * if no user specific value is defined. 275 * 276 * @param userName 277 * The user name key. 278 * @return The user specific value. 279 */ 280 public boolean getPerUserLifo(final String userName) { 281 Boolean value = null; 282 if (perUserLifo != null) { 283 value = perUserLifo.get(userName); 284 } 285 if (value == null) { 286 return getDefaultLifo(); 287 } 288 return value.booleanValue(); 289 } 290 291 /** 292 * Gets the user specific value for {@link GenericObjectPool#getMaxIdle()} for the specified user's pool or the 293 * default if no user specific value is defined. 294 * 295 * @param userName 296 * The user name key. 297 * @return The user specific value. 298 */ 299 public int getPerUserMaxIdle(final String userName) { 300 Integer value = null; 301 if (perUserMaxIdle != null) { 302 value = perUserMaxIdle.get(userName); 303 } 304 if (value == null) { 305 return getDefaultMaxIdle(); 306 } 307 return value.intValue(); 308 } 309 310 /** 311 * Gets the user specific value for {@link GenericObjectPool#getMaxTotal()} for the specified user's pool or the 312 * default if no user specific value is defined. 313 * 314 * @param userName 315 * The user name key. 316 * @return The user specific value. 317 */ 318 public int getPerUserMaxTotal(final String userName) { 319 Integer value = null; 320 if (perUserMaxTotal != null) { 321 value = perUserMaxTotal.get(userName); 322 } 323 if (value == null) { 324 return getDefaultMaxTotal(); 325 } 326 return value.intValue(); 327 } 328 329 /** 330 * Gets the user specific value for {@link GenericObjectPool#getMaxWaitMillis()} for the specified user's pool or 331 * the default if no user specific value is defined. 332 * 333 * @param userName 334 * The user name key. 335 * @return The user specific value. 336 */ 337 public long getPerUserMaxWaitMillis(final String userName) { 338 Long value = null; 339 if (perUserMaxWaitMillis != null) { 340 value = perUserMaxWaitMillis.get(userName); 341 } 342 if (value == null) { 343 return getDefaultMaxWaitMillis(); 344 } 345 return value.longValue(); 346 } 347 348 /** 349 * Gets the user specific value for {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} for the specified 350 * user's pool or the default if no user specific value is defined. 351 * 352 * @param userName 353 * The user name key. 354 * @return The user specific value. 355 */ 356 public long getPerUserMinEvictableIdleTimeMillis(final String userName) { 357 Long value = null; 358 if (perUserMinEvictableIdleTimeMillis != null) { 359 value = perUserMinEvictableIdleTimeMillis.get(userName); 360 } 361 if (value == null) { 362 return getDefaultMinEvictableIdleTimeMillis(); 363 } 364 return value.longValue(); 365 } 366 367 /** 368 * Gets the user specific value for {@link GenericObjectPool#getMinIdle()} for the specified user's pool or the 369 * default if no user specific value is defined. 370 * 371 * @param userName 372 * The user name key. 373 * @return The user specific value. 374 */ 375 public int getPerUserMinIdle(final String userName) { 376 Integer value = null; 377 if (perUserMinIdle != null) { 378 value = perUserMinIdle.get(userName); 379 } 380 if (value == null) { 381 return getDefaultMinIdle(); 382 } 383 return value.intValue(); 384 } 385 386 /** 387 * Gets the user specific value for {@link GenericObjectPool#getNumTestsPerEvictionRun()} for the specified user's 388 * pool or the default if no user specific value is defined. 389 * 390 * @param userName 391 * The user name key. 392 * @return The user specific value. 393 */ 394 public int getPerUserNumTestsPerEvictionRun(final String userName) { 395 Integer value = null; 396 if (perUserNumTestsPerEvictionRun != null) { 397 value = perUserNumTestsPerEvictionRun.get(userName); 398 } 399 if (value == null) { 400 return getDefaultNumTestsPerEvictionRun(); 401 } 402 return value.intValue(); 403 } 404 405 /** 406 * Gets the user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for the specified 407 * user's pool or the default if no user specific value is defined. 408 * 409 * @param userName 410 * The user name key. 411 * @return The user specific value. 412 */ 413 public long getPerUserSoftMinEvictableIdleTimeMillis(final String userName) { 414 Long value = null; 415 if (perUserSoftMinEvictableIdleTimeMillis != null) { 416 value = perUserSoftMinEvictableIdleTimeMillis.get(userName); 417 } 418 if (value == null) { 419 return getDefaultSoftMinEvictableIdleTimeMillis(); 420 } 421 return value.longValue(); 422 } 423 424 /** 425 * Gets the user specific value for {@link GenericObjectPool#getTestOnBorrow()} for the specified user's pool or the 426 * default if no user specific value is defined. 427 * 428 * @param userName 429 * The user name key. 430 * @return The user specific value. 431 */ 432 public boolean getPerUserTestOnBorrow(final String userName) { 433 Boolean value = null; 434 if (perUserTestOnBorrow != null) { 435 value = perUserTestOnBorrow.get(userName); 436 } 437 if (value == null) { 438 return getDefaultTestOnBorrow(); 439 } 440 return value.booleanValue(); 441 } 442 443 /** 444 * Gets the user specific value for {@link GenericObjectPool#getTestOnCreate()} for the specified user's pool or the 445 * default if no user specific value is defined. 446 * 447 * @param userName 448 * The user name key. 449 * @return The user specific value. 450 */ 451 public boolean getPerUserTestOnCreate(final String userName) { 452 Boolean value = null; 453 if (perUserTestOnCreate != null) { 454 value = perUserTestOnCreate.get(userName); 455 } 456 if (value == null) { 457 return getDefaultTestOnCreate(); 458 } 459 return value.booleanValue(); 460 } 461 462 /** 463 * Gets the user specific value for {@link GenericObjectPool#getTestOnReturn()} for the specified user's pool or the 464 * default if no user specific value is defined. 465 * 466 * @param userName 467 * The user name key. 468 * @return The user specific value. 469 */ 470 public boolean getPerUserTestOnReturn(final String userName) { 471 Boolean value = null; 472 if (perUserTestOnReturn != null) { 473 value = perUserTestOnReturn.get(userName); 474 } 475 if (value == null) { 476 return getDefaultTestOnReturn(); 477 } 478 return value.booleanValue(); 479 } 480 481 /** 482 * Gets the user specific value for {@link GenericObjectPool#getTestWhileIdle()} for the specified user's pool or 483 * the default if no user specific value is defined. 484 * 485 * @param userName 486 * The user name key. 487 * @return The user specific value. 488 */ 489 public boolean getPerUserTestWhileIdle(final String userName) { 490 Boolean value = null; 491 if (perUserTestWhileIdle != null) { 492 value = perUserTestWhileIdle.get(userName); 493 } 494 if (value == null) { 495 return getDefaultTestWhileIdle(); 496 } 497 return value.booleanValue(); 498 } 499 500 /** 501 * Gets the user specific value for {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis()} for the specified 502 * user's pool or the default if no user specific value is defined. 503 * 504 * @param userName 505 * The user name key. 506 * @return The user specific value. 507 */ 508 public long getPerUserTimeBetweenEvictionRunsMillis(final String userName) { 509 Long value = null; 510 if (perUserTimeBetweenEvictionRunsMillis != null) { 511 value = perUserTimeBetweenEvictionRunsMillis.get(userName); 512 } 513 if (value == null) { 514 return getDefaultTimeBetweenEvictionRunsMillis(); 515 } 516 return value.longValue(); 517 } 518 519 /** 520 * Returns the object pool associated with the given PoolKey. 521 * 522 * @param poolKey 523 * PoolKey identifying the pool 524 * @return the GenericObjectPool pooling connections for the userName and datasource specified by the PoolKey 525 */ 526 private ObjectPool<PooledConnectionAndInfo> getPool(final PoolKey poolKey) { 527 final CPDSConnectionFactory mgr = (CPDSConnectionFactory) managers.get(poolKey); 528 return mgr == null ? null : mgr.getPool(); 529 } 530 531 @Override 532 protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password) 533 throws SQLException { 534 535 final PoolKey key = getPoolKey(userName); 536 ObjectPool<PooledConnectionAndInfo> pool; 537 PooledConnectionManager manager; 538 synchronized (this) { 539 manager = managers.get(key); 540 if (manager == null) { 541 try { 542 registerPool(userName, password); 543 manager = managers.get(key); 544 } catch (final NamingException e) { 545 throw new SQLException("RegisterPool failed", e); 546 } 547 } 548 pool = getCPDSConnectionFactoryPool(manager); 549 } 550 551 PooledConnectionAndInfo info = null; 552 try { 553 info = pool.borrowObject(); 554 } catch (final NoSuchElementException ex) { 555 throw new SQLException("Could not retrieve connection info from pool", ex); 556 } catch (final Exception e) { 557 // See if failure is due to CPDSConnectionFactory authentication failure 558 try { 559 testCPDS(userName, password); 560 } catch (final Exception ex) { 561 throw new SQLException("Could not retrieve connection info from pool", ex); 562 } 563 // New password works, so kill the old pool, create a new one, and borrow 564 manager.closePool(userName); 565 synchronized (this) { 566 managers.remove(key); 567 } 568 try { 569 registerPool(userName, password); 570 pool = getPool(key); 571 } catch (final NamingException ne) { 572 throw new SQLException("RegisterPool failed", ne); 573 } 574 try { 575 info = pool.borrowObject(); 576 } catch (final Exception ex) { 577 throw new SQLException("Could not retrieve connection info from pool", ex); 578 } 579 } 580 return info; 581 } 582 583 /** 584 * Creates a pool key from the provided parameters. 585 * 586 * @param userName 587 * User name 588 * @return The pool key 589 */ 590 private PoolKey getPoolKey(final String userName) { 591 return new PoolKey(getDataSourceName(), userName); 592 } 593 594 /** 595 * Returns a <code>PerUserPoolDataSource</code> {@link Reference}. 596 */ 597 @Override 598 public Reference getReference() throws NamingException { 599 final Reference ref = new Reference(getClass().getName(), PerUserPoolDataSourceFactory.class.getName(), null); 600 ref.add(new StringRefAddr("instanceKey", getInstanceKey())); 601 return ref; 602 } 603 604 /** 605 * Supports Serialization interface. 606 * 607 * @param in 608 * a <code>java.io.ObjectInputStream</code> value 609 * @throws IOException 610 * if an error occurs 611 * @throws ClassNotFoundException 612 * if an error occurs 613 */ 614 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { 615 try { 616 in.defaultReadObject(); 617 final PerUserPoolDataSource oldDS = (PerUserPoolDataSource) new PerUserPoolDataSourceFactory() 618 .getObjectInstance(getReference(), null, null, null); 619 this.managers = oldDS.managers; 620 } catch (final NamingException e) { 621 throw new IOException("NamingException: " + e); 622 } 623 } 624 625 private synchronized void registerPool(final String userName, final String password) 626 throws NamingException, SQLException { 627 628 final ConnectionPoolDataSource cpds = testCPDS(userName, password); 629 630 // Set up the factory we will use (passing the pool associates 631 // the factory with the pool, so we do not have to do so 632 // explicitly) 633 final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, getValidationQuery(), 634 getValidationQueryTimeout(), isRollbackAfterValidation(), userName, password); 635 factory.setMaxConnLifetimeMillis(getMaxConnLifetimeMillis()); 636 637 // Create an object pool to contain our PooledConnections 638 final GenericObjectPool<PooledConnectionAndInfo> pool = new GenericObjectPool<>(factory); 639 factory.setPool(pool); 640 pool.setBlockWhenExhausted(getPerUserBlockWhenExhausted(userName)); 641 pool.setEvictionPolicyClassName(getPerUserEvictionPolicyClassName(userName)); 642 pool.setLifo(getPerUserLifo(userName)); 643 pool.setMaxIdle(getPerUserMaxIdle(userName)); 644 pool.setMaxTotal(getPerUserMaxTotal(userName)); 645 pool.setMaxWaitMillis(getPerUserMaxWaitMillis(userName)); 646 pool.setMinEvictableIdleTimeMillis(getPerUserMinEvictableIdleTimeMillis(userName)); 647 pool.setMinIdle(getPerUserMinIdle(userName)); 648 pool.setNumTestsPerEvictionRun(getPerUserNumTestsPerEvictionRun(userName)); 649 pool.setSoftMinEvictableIdleTimeMillis(getPerUserSoftMinEvictableIdleTimeMillis(userName)); 650 pool.setTestOnCreate(getPerUserTestOnCreate(userName)); 651 pool.setTestOnBorrow(getPerUserTestOnBorrow(userName)); 652 pool.setTestOnReturn(getPerUserTestOnReturn(userName)); 653 pool.setTestWhileIdle(getPerUserTestWhileIdle(userName)); 654 pool.setTimeBetweenEvictionRunsMillis(getPerUserTimeBetweenEvictionRunsMillis(userName)); 655 656 pool.setSwallowedExceptionListener(new SwallowedExceptionLogger(log)); 657 658 final Object old = managers.put(getPoolKey(userName), factory); 659 if (old != null) { 660 throw new IllegalStateException("Pool already contains an entry for this user/password: " + userName); 661 } 662 } 663 664 void setPerUserBlockWhenExhausted(final Map<String, Boolean> userDefaultBlockWhenExhausted) { 665 assertInitializationAllowed(); 666 if (perUserBlockWhenExhausted == null) { 667 perUserBlockWhenExhausted = createMap(); 668 } else { 669 perUserBlockWhenExhausted.clear(); 670 } 671 perUserBlockWhenExhausted.putAll(userDefaultBlockWhenExhausted); 672 } 673 674 /** 675 * Sets a user specific value for {@link GenericObjectPool#getBlockWhenExhausted()} for the specified user's pool. 676 * 677 * @param userName 678 * The user name key. 679 * @param value 680 * The user specific value. 681 */ 682 public void setPerUserBlockWhenExhausted(final String userName, final Boolean value) { 683 assertInitializationAllowed(); 684 if (perUserBlockWhenExhausted == null) { 685 perUserBlockWhenExhausted = createMap(); 686 } 687 perUserBlockWhenExhausted.put(userName, value); 688 } 689 690 void setPerUserDefaultAutoCommit(final Map<String, Boolean> userDefaultAutoCommit) { 691 assertInitializationAllowed(); 692 if (perUserDefaultAutoCommit == null) { 693 perUserDefaultAutoCommit = createMap(); 694 } else { 695 perUserDefaultAutoCommit.clear(); 696 } 697 perUserDefaultAutoCommit.putAll(userDefaultAutoCommit); 698 } 699 700 /** 701 * Sets a user specific default value for {@link Connection#setAutoCommit(boolean)} for the specified user's pool. 702 * 703 * @param userName 704 * The user name key. 705 * @param value 706 * The user specific value. 707 */ 708 public void setPerUserDefaultAutoCommit(final String userName, final Boolean value) { 709 assertInitializationAllowed(); 710 if (perUserDefaultAutoCommit == null) { 711 perUserDefaultAutoCommit = createMap(); 712 } 713 perUserDefaultAutoCommit.put(userName, value); 714 } 715 716 void setPerUserDefaultReadOnly(final Map<String, Boolean> userDefaultReadOnly) { 717 assertInitializationAllowed(); 718 if (perUserDefaultReadOnly == null) { 719 perUserDefaultReadOnly = createMap(); 720 } else { 721 perUserDefaultReadOnly.clear(); 722 } 723 perUserDefaultReadOnly.putAll(userDefaultReadOnly); 724 } 725 726 /** 727 * Sets a user specific default value for {@link Connection#setReadOnly(boolean)} for the specified user's pool. 728 * 729 * @param userName 730 * The user name key. 731 * @param value 732 * The user specific value. 733 */ 734 public void setPerUserDefaultReadOnly(final String userName, final Boolean value) { 735 assertInitializationAllowed(); 736 if (perUserDefaultReadOnly == null) { 737 perUserDefaultReadOnly = createMap(); 738 } 739 perUserDefaultReadOnly.put(userName, value); 740 } 741 742 void setPerUserDefaultTransactionIsolation(final Map<String, Integer> userDefaultTransactionIsolation) { 743 assertInitializationAllowed(); 744 if (perUserDefaultTransactionIsolation == null) { 745 perUserDefaultTransactionIsolation = new HashMap<>(); 746 } else { 747 perUserDefaultTransactionIsolation.clear(); 748 } 749 perUserDefaultTransactionIsolation.putAll(userDefaultTransactionIsolation); 750 } 751 752 /** 753 * Sets a user specific default value for {@link Connection#setTransactionIsolation(int)} for the specified user's 754 * pool. 755 * 756 * @param userName 757 * The user name key. 758 * @param value 759 * The user specific value. 760 */ 761 public void setPerUserDefaultTransactionIsolation(final String userName, final Integer value) { 762 assertInitializationAllowed(); 763 if (perUserDefaultTransactionIsolation == null) { 764 perUserDefaultTransactionIsolation = new HashMap<>(); 765 } 766 perUserDefaultTransactionIsolation.put(userName, value); 767 } 768 769 void setPerUserEvictionPolicyClassName(final Map<String, String> userDefaultEvictionPolicyClassName) { 770 assertInitializationAllowed(); 771 if (perUserEvictionPolicyClassName == null) { 772 perUserEvictionPolicyClassName = new HashMap<>(); 773 } else { 774 perUserEvictionPolicyClassName.clear(); 775 } 776 perUserEvictionPolicyClassName.putAll(userDefaultEvictionPolicyClassName); 777 } 778 779 /** 780 * Sets a user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's 781 * pool. 782 * 783 * @param userName 784 * The user name key. 785 * @param value 786 * The user specific value. 787 */ 788 public void setPerUserEvictionPolicyClassName(final String userName, final String value) { 789 assertInitializationAllowed(); 790 if (perUserEvictionPolicyClassName == null) { 791 perUserEvictionPolicyClassName = new HashMap<>(); 792 } 793 perUserEvictionPolicyClassName.put(userName, value); 794 } 795 796 void setPerUserLifo(final Map<String, Boolean> userDefaultLifo) { 797 assertInitializationAllowed(); 798 if (perUserLifo == null) { 799 perUserLifo = createMap(); 800 } else { 801 perUserLifo.clear(); 802 } 803 perUserLifo.putAll(userDefaultLifo); 804 } 805 806 /** 807 * Sets a user specific value for {@link GenericObjectPool#getLifo()} for the specified user's pool. 808 * 809 * @param userName 810 * The user name key. 811 * @param value 812 * The user specific value. 813 */ 814 public void setPerUserLifo(final String userName, final Boolean value) { 815 assertInitializationAllowed(); 816 if (perUserLifo == null) { 817 perUserLifo = createMap(); 818 } 819 perUserLifo.put(userName, value); 820 } 821 822 void setPerUserMaxIdle(final Map<String, Integer> userDefaultMaxIdle) { 823 assertInitializationAllowed(); 824 if (perUserMaxIdle == null) { 825 perUserMaxIdle = new HashMap<>(); 826 } else { 827 perUserMaxIdle.clear(); 828 } 829 perUserMaxIdle.putAll(userDefaultMaxIdle); 830 } 831 832 /** 833 * Sets a user specific value for {@link GenericObjectPool#getMaxIdle()} for the specified user's pool. 834 * 835 * @param userName 836 * The user name key. 837 * @param value 838 * The user specific value. 839 */ 840 public void setPerUserMaxIdle(final String userName, final Integer value) { 841 assertInitializationAllowed(); 842 if (perUserMaxIdle == null) { 843 perUserMaxIdle = new HashMap<>(); 844 } 845 perUserMaxIdle.put(userName, value); 846 } 847 848 void setPerUserMaxTotal(final Map<String, Integer> userDefaultMaxTotal) { 849 assertInitializationAllowed(); 850 if (perUserMaxTotal == null) { 851 perUserMaxTotal = new HashMap<>(); 852 } else { 853 perUserMaxTotal.clear(); 854 } 855 perUserMaxTotal.putAll(userDefaultMaxTotal); 856 } 857 858 /** 859 * Sets a user specific value for {@link GenericObjectPool#getMaxTotal()} for the specified user's pool. 860 * 861 * @param userName 862 * The user name key. 863 * @param value 864 * The user specific value. 865 */ 866 public void setPerUserMaxTotal(final String userName, final Integer value) { 867 assertInitializationAllowed(); 868 if (perUserMaxTotal == null) { 869 perUserMaxTotal = new HashMap<>(); 870 } 871 perUserMaxTotal.put(userName, value); 872 } 873 874 void setPerUserMaxWaitMillis(final Map<String, Long> userDefaultMaxWaitMillis) { 875 assertInitializationAllowed(); 876 if (perUserMaxWaitMillis == null) { 877 perUserMaxWaitMillis = new HashMap<>(); 878 } else { 879 perUserMaxWaitMillis.clear(); 880 } 881 perUserMaxWaitMillis.putAll(userDefaultMaxWaitMillis); 882 } 883 884 /** 885 * Sets a user specific value for {@link GenericObjectPool#getMaxWaitMillis()} for the specified user's pool. 886 * 887 * @param userName 888 * The user name key. 889 * @param value 890 * The user specific value. 891 */ 892 public void setPerUserMaxWaitMillis(final String userName, final Long value) { 893 assertInitializationAllowed(); 894 if (perUserMaxWaitMillis == null) { 895 perUserMaxWaitMillis = new HashMap<>(); 896 } 897 perUserMaxWaitMillis.put(userName, value); 898 } 899 900 void setPerUserMinEvictableIdleTimeMillis(final Map<String, Long> userDefaultMinEvictableIdleTimeMillis) { 901 assertInitializationAllowed(); 902 if (perUserMinEvictableIdleTimeMillis == null) { 903 perUserMinEvictableIdleTimeMillis = new HashMap<>(); 904 } else { 905 perUserMinEvictableIdleTimeMillis.clear(); 906 } 907 perUserMinEvictableIdleTimeMillis.putAll(userDefaultMinEvictableIdleTimeMillis); 908 } 909 910 /** 911 * Sets a user specific value for {@link GenericObjectPool#getMinEvictableIdleTimeMillis()} for the specified user's 912 * pool. 913 * 914 * @param userName 915 * The user name key. 916 * @param value 917 * The user specific value. 918 */ 919 public void setPerUserMinEvictableIdleTimeMillis(final String userName, final Long value) { 920 assertInitializationAllowed(); 921 if (perUserMinEvictableIdleTimeMillis == null) { 922 perUserMinEvictableIdleTimeMillis = new HashMap<>(); 923 } 924 perUserMinEvictableIdleTimeMillis.put(userName, value); 925 } 926 927 void setPerUserMinIdle(final Map<String, Integer> userDefaultMinIdle) { 928 assertInitializationAllowed(); 929 if (perUserMinIdle == null) { 930 perUserMinIdle = new HashMap<>(); 931 } else { 932 perUserMinIdle.clear(); 933 } 934 perUserMinIdle.putAll(userDefaultMinIdle); 935 } 936 937 /** 938 * Sets a user specific value for {@link GenericObjectPool#getMinIdle()} for the specified user's pool. 939 * 940 * @param userName 941 * The user name key. 942 * @param value 943 * The user specific value. 944 */ 945 public void setPerUserMinIdle(final String userName, final Integer value) { 946 assertInitializationAllowed(); 947 if (perUserMinIdle == null) { 948 perUserMinIdle = new HashMap<>(); 949 } 950 perUserMinIdle.put(userName, value); 951 } 952 953 void setPerUserNumTestsPerEvictionRun(final Map<String, Integer> userDefaultNumTestsPerEvictionRun) { 954 assertInitializationAllowed(); 955 if (perUserNumTestsPerEvictionRun == null) { 956 perUserNumTestsPerEvictionRun = new HashMap<>(); 957 } else { 958 perUserNumTestsPerEvictionRun.clear(); 959 } 960 perUserNumTestsPerEvictionRun.putAll(userDefaultNumTestsPerEvictionRun); 961 } 962 963 /** 964 * Sets a user specific value for {@link GenericObjectPool#getNumTestsPerEvictionRun()} for the specified user's 965 * pool. 966 * 967 * @param userName 968 * The user name key. 969 * @param value 970 * The user specific value. 971 */ 972 public void setPerUserNumTestsPerEvictionRun(final String userName, final Integer value) { 973 assertInitializationAllowed(); 974 if (perUserNumTestsPerEvictionRun == null) { 975 perUserNumTestsPerEvictionRun = new HashMap<>(); 976 } 977 perUserNumTestsPerEvictionRun.put(userName, value); 978 } 979 980 void setPerUserSoftMinEvictableIdleTimeMillis(final Map<String, Long> userDefaultSoftMinEvictableIdleTimeMillis) { 981 assertInitializationAllowed(); 982 if (perUserSoftMinEvictableIdleTimeMillis == null) { 983 perUserSoftMinEvictableIdleTimeMillis = new HashMap<>(); 984 } else { 985 perUserSoftMinEvictableIdleTimeMillis.clear(); 986 } 987 perUserSoftMinEvictableIdleTimeMillis.putAll(userDefaultSoftMinEvictableIdleTimeMillis); 988 } 989 990 /** 991 * Sets a user specific value for {@link GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for the specified 992 * user's pool. 993 * 994 * @param userName 995 * The user name key. 996 * @param value 997 * The user specific value. 998 */ 999 public void setPerUserSoftMinEvictableIdleTimeMillis(final String userName, final Long value) { 1000 assertInitializationAllowed(); 1001 if (perUserSoftMinEvictableIdleTimeMillis == null) { 1002 perUserSoftMinEvictableIdleTimeMillis = new HashMap<>(); 1003 } 1004 perUserSoftMinEvictableIdleTimeMillis.put(userName, value); 1005 } 1006 1007 void setPerUserTestOnBorrow(final Map<String, Boolean> userDefaultTestOnBorrow) { 1008 assertInitializationAllowed(); 1009 if (perUserTestOnBorrow == null) { 1010 perUserTestOnBorrow = createMap(); 1011 } else { 1012 perUserTestOnBorrow.clear(); 1013 } 1014 perUserTestOnBorrow.putAll(userDefaultTestOnBorrow); 1015 } 1016 1017 /** 1018 * Sets a user specific value for {@link GenericObjectPool#getTestOnBorrow()} for the specified user's pool. 1019 * 1020 * @param userName 1021 * The user name key. 1022 * @param value 1023 * The user specific value. 1024 */ 1025 public void setPerUserTestOnBorrow(final String userName, final Boolean value) { 1026 assertInitializationAllowed(); 1027 if (perUserTestOnBorrow == null) { 1028 perUserTestOnBorrow = createMap(); 1029 } 1030 perUserTestOnBorrow.put(userName, value); 1031 } 1032 1033 void setPerUserTestOnCreate(final Map<String, Boolean> userDefaultTestOnCreate) { 1034 assertInitializationAllowed(); 1035 if (perUserTestOnCreate == null) { 1036 perUserTestOnCreate = createMap(); 1037 } else { 1038 perUserTestOnCreate.clear(); 1039 } 1040 perUserTestOnCreate.putAll(userDefaultTestOnCreate); 1041 } 1042 1043 /** 1044 * Sets a user specific value for {@link GenericObjectPool#getTestOnCreate()} for the specified user's pool. 1045 * 1046 * @param userName 1047 * The user name key. 1048 * @param value 1049 * The user specific value. 1050 */ 1051 public void setPerUserTestOnCreate(final String userName, final Boolean value) { 1052 assertInitializationAllowed(); 1053 if (perUserTestOnCreate == null) { 1054 perUserTestOnCreate = createMap(); 1055 } 1056 perUserTestOnCreate.put(userName, value); 1057 } 1058 1059 void setPerUserTestOnReturn(final Map<String, Boolean> userDefaultTestOnReturn) { 1060 assertInitializationAllowed(); 1061 if (perUserTestOnReturn == null) { 1062 perUserTestOnReturn = createMap(); 1063 } else { 1064 perUserTestOnReturn.clear(); 1065 } 1066 perUserTestOnReturn.putAll(userDefaultTestOnReturn); 1067 } 1068 1069 /** 1070 * Sets a user specific value for {@link GenericObjectPool#getTestOnReturn()} for the specified user's pool. 1071 * 1072 * @param userName 1073 * The user name key. 1074 * @param value 1075 * The user specific value. 1076 */ 1077 public void setPerUserTestOnReturn(final String userName, final Boolean value) { 1078 assertInitializationAllowed(); 1079 if (perUserTestOnReturn == null) { 1080 perUserTestOnReturn = createMap(); 1081 } 1082 perUserTestOnReturn.put(userName, value); 1083 } 1084 1085 void setPerUserTestWhileIdle(final Map<String, Boolean> userDefaultTestWhileIdle) { 1086 assertInitializationAllowed(); 1087 if (perUserTestWhileIdle == null) { 1088 perUserTestWhileIdle = createMap(); 1089 } else { 1090 perUserTestWhileIdle.clear(); 1091 } 1092 perUserTestWhileIdle.putAll(userDefaultTestWhileIdle); 1093 } 1094 1095 /** 1096 * Sets a user specific value for {@link GenericObjectPool#getTestWhileIdle()} for the specified user's pool. 1097 * 1098 * @param userName 1099 * The user name key. 1100 * @param value 1101 * The user specific value. 1102 */ 1103 public void setPerUserTestWhileIdle(final String userName, final Boolean value) { 1104 assertInitializationAllowed(); 1105 if (perUserTestWhileIdle == null) { 1106 perUserTestWhileIdle = createMap(); 1107 } 1108 perUserTestWhileIdle.put(userName, value); 1109 } 1110 1111 void setPerUserTimeBetweenEvictionRunsMillis(final Map<String, Long> userDefaultTimeBetweenEvictionRunsMillis) { 1112 assertInitializationAllowed(); 1113 if (perUserTimeBetweenEvictionRunsMillis == null) { 1114 perUserTimeBetweenEvictionRunsMillis = new HashMap<>(); 1115 } else { 1116 perUserTimeBetweenEvictionRunsMillis.clear(); 1117 } 1118 perUserTimeBetweenEvictionRunsMillis.putAll(userDefaultTimeBetweenEvictionRunsMillis); 1119 } 1120 1121 /** 1122 * Sets a user specific value for {@link GenericObjectPool#getTimeBetweenEvictionRunsMillis ()} for the specified 1123 * user's pool. 1124 * 1125 * @param userName 1126 * The user name key. 1127 * @param value 1128 * The user specific value. 1129 */ 1130 public void setPerUserTimeBetweenEvictionRunsMillis(final String userName, final Long value) { 1131 assertInitializationAllowed(); 1132 if (perUserTimeBetweenEvictionRunsMillis == null) { 1133 perUserTimeBetweenEvictionRunsMillis = new HashMap<>(); 1134 } 1135 perUserTimeBetweenEvictionRunsMillis.put(userName, value); 1136 } 1137 1138 @Override 1139 protected void setupDefaults(final Connection con, final String userName) throws SQLException { 1140 Boolean defaultAutoCommit = isDefaultAutoCommit(); 1141 if (userName != null) { 1142 final Boolean userMax = getPerUserDefaultAutoCommit(userName); 1143 if (userMax != null) { 1144 defaultAutoCommit = userMax; 1145 } 1146 } 1147 1148 Boolean defaultReadOnly = isDefaultReadOnly(); 1149 if (userName != null) { 1150 final Boolean userMax = getPerUserDefaultReadOnly(userName); 1151 if (userMax != null) { 1152 defaultReadOnly = userMax; 1153 } 1154 } 1155 1156 int defaultTransactionIsolation = getDefaultTransactionIsolation(); 1157 if (userName != null) { 1158 final Integer userMax = getPerUserDefaultTransactionIsolation(userName); 1159 if (userMax != null) { 1160 defaultTransactionIsolation = userMax.intValue(); 1161 } 1162 } 1163 1164 if (defaultAutoCommit != null && con.getAutoCommit() != defaultAutoCommit.booleanValue()) { 1165 con.setAutoCommit(defaultAutoCommit.booleanValue()); 1166 } 1167 1168 if (defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) { 1169 con.setTransactionIsolation(defaultTransactionIsolation); 1170 } 1171 1172 if (defaultReadOnly != null && con.isReadOnly() != defaultReadOnly.booleanValue()) { 1173 con.setReadOnly(defaultReadOnly.booleanValue()); 1174 } 1175 } 1176}