1 16 17 package org.apache.commons.dbcp.datasources; 18 19 import java.io.Serializable ; 20 import java.io.PrintWriter ; 21 import java.sql.Connection ; 22 import java.sql.SQLException ; 23 import java.util.NoSuchElementException ; 24 import java.util.Properties ; 25 26 import javax.naming.Context ; 27 import javax.naming.InitialContext ; 28 import javax.naming.NamingException ; 29 import javax.naming.Reference ; 30 import javax.naming.StringRefAddr ; 31 import javax.naming.Referenceable ; 32 import javax.sql.ConnectionPoolDataSource ; 33 import javax.sql.DataSource ; 34 import javax.sql.PooledConnection ; 35 36 import org.apache.commons.dbcp.SQLNestedException; 37 import org.apache.commons.pool.impl.GenericObjectPool; 38 39 84 public abstract class InstanceKeyDataSource 85 implements DataSource , Referenceable , Serializable { 86 private static final String GET_CONNECTION_CALLED 87 = "A Connection was already requested from this source, " 88 + "further initialization is not allowed."; 89 private static final String BAD_TRANSACTION_ISOLATION 90 = "The requested TransactionIsolation level is invalid."; 91 94 protected static final int UNKNOWN_TRANSACTIONISOLATION = -1; 95 96 private boolean getConnectionCalled = false; 97 98 private ConnectionPoolDataSource cpds = null; 99 100 private String dataSourceName = null; 101 private boolean defaultAutoCommit = false; 102 private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; 103 private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE; 104 private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE; 105 private int maxWait = (int)Math.min((long)Integer.MAX_VALUE, 106 GenericObjectPool.DEFAULT_MAX_WAIT); 107 private boolean defaultReadOnly = false; 108 109 private String description = null; 110 111 Properties jndiEnvironment = null; 112 113 private int loginTimeout = 0; 114 115 private PrintWriter logWriter = null; 116 private boolean _testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW; 117 private boolean _testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN; 118 private int _timeBetweenEvictionRunsMillis = (int) 119 Math.min((long)Integer.MAX_VALUE, 120 GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS); 121 private int _numTestsPerEvictionRun = 122 GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; 123 private int _minEvictableIdleTimeMillis = (int) 124 Math.min((long)Integer.MAX_VALUE, 125 GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS); 126 private boolean _testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE; 127 private String validationQuery = null; 128 private boolean testPositionSet = false; 129 130 protected String instanceKey = null; 131 132 135 public InstanceKeyDataSource() { 136 defaultAutoCommit = true; 137 } 138 139 143 protected void assertInitializationAllowed() 144 throws IllegalStateException { 145 if (getConnectionCalled) { 146 throw new IllegalStateException (GET_CONNECTION_CALLED); 147 } 148 } 149 150 153 public abstract void close() throws Exception ; 154 155 158 164 public ConnectionPoolDataSource getConnectionPoolDataSource() { 165 return cpds; 166 } 167 168 174 public void setConnectionPoolDataSource(ConnectionPoolDataSource v) { 175 assertInitializationAllowed(); 176 if (dataSourceName != null) { 177 throw new IllegalStateException ( 178 "Cannot set the DataSource, if JNDI is used."); 179 } 180 if (cpds != null) 181 { 182 throw new IllegalStateException ( 183 "The CPDS has already been set. It cannot be altered."); 184 } 185 cpds = v; 186 instanceKey = InstanceKeyObjectFactory.registerNewInstance(this); 187 } 188 189 196 public String getDataSourceName() { 197 return dataSourceName; 198 } 199 200 207 public void setDataSourceName(String v) { 208 assertInitializationAllowed(); 209 if (cpds != null) { 210 throw new IllegalStateException ( 211 "Cannot set the JNDI name for the DataSource, if already " + 212 "set using setConnectionPoolDataSource."); 213 } 214 if (dataSourceName != null) 215 { 216 throw new IllegalStateException ( 217 "The DataSourceName has already been set. " + 218 "It cannot be altered."); 219 } 220 this.dataSourceName = v; 221 instanceKey = InstanceKeyObjectFactory.registerNewInstance(this); 222 } 223 224 232 public boolean isDefaultAutoCommit() { 233 return defaultAutoCommit; 234 } 235 236 244 public void setDefaultAutoCommit(boolean v) { 245 assertInitializationAllowed(); 246 this.defaultAutoCommit = v; 247 } 248 249 257 public boolean isDefaultReadOnly() { 258 return defaultReadOnly; 259 } 260 261 269 public void setDefaultReadOnly(boolean v) { 270 assertInitializationAllowed(); 271 this.defaultReadOnly = v; 272 } 273 274 282 public int getDefaultTransactionIsolation() { 283 return defaultTransactionIsolation; 284 } 285 286 294 public void setDefaultTransactionIsolation(int v) { 295 assertInitializationAllowed(); 296 switch (v) { 297 case Connection.TRANSACTION_NONE: 298 case Connection.TRANSACTION_READ_COMMITTED: 299 case Connection.TRANSACTION_READ_UNCOMMITTED: 300 case Connection.TRANSACTION_REPEATABLE_READ: 301 case Connection.TRANSACTION_SERIALIZABLE: 302 break; 303 default: 304 throw new IllegalArgumentException (BAD_TRANSACTION_ISOLATION); 305 } 306 this.defaultTransactionIsolation = v; 307 } 308 309 316 public String getDescription() { 317 return description; 318 } 319 320 327 public void setDescription(String v) { 328 this.description = v; 329 } 330 331 338 public String getJndiEnvironment(String key) { 339 String value = null; 340 if (jndiEnvironment != null) { 341 value = jndiEnvironment.getProperty(key); 342 } 343 return value; 344 } 345 346 353 public void setJndiEnvironment(String key, String value) { 354 if (jndiEnvironment == null) { 355 jndiEnvironment = new Properties (); 356 } 357 jndiEnvironment.setProperty(key, value); 358 } 359 360 364 public int getLoginTimeout() { 365 return loginTimeout; 366 } 367 368 372 public void setLoginTimeout(int v) { 373 this.loginTimeout = v; 374 } 375 376 380 public PrintWriter getLogWriter() { 381 if (logWriter == null) { 382 logWriter = new PrintWriter (System.out); 383 } 384 return logWriter; 385 } 386 387 391 public void setLogWriter(PrintWriter v) { 392 this.logWriter = v; 393 } 394 395 398 public final boolean isTestOnBorrow() { 399 return getTestOnBorrow(); 400 } 401 402 412 public boolean getTestOnBorrow() { 413 return _testOnBorrow; 414 } 415 416 426 public void setTestOnBorrow(boolean testOnBorrow) { 427 assertInitializationAllowed(); 428 _testOnBorrow = testOnBorrow; 429 testPositionSet = true; 430 } 431 432 435 public final boolean isTestOnReturn() { 436 return getTestOnReturn(); 437 } 438 439 447 public boolean getTestOnReturn() { 448 return _testOnReturn; 449 } 450 451 459 public void setTestOnReturn(boolean testOnReturn) { 460 assertInitializationAllowed(); 461 _testOnReturn = testOnReturn; 462 testPositionSet = true; 463 } 464 465 473 public int getTimeBetweenEvictionRunsMillis() { 474 return _timeBetweenEvictionRunsMillis; 475 } 476 477 485 public void 486 setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) { 487 assertInitializationAllowed(); 488 _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 489 } 490 491 498 public int getNumTestsPerEvictionRun() { 499 return _numTestsPerEvictionRun; 500 } 501 502 513 public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { 514 assertInitializationAllowed(); 515 _numTestsPerEvictionRun = numTestsPerEvictionRun; 516 } 517 518 526 public int getMinEvictableIdleTimeMillis() { 527 return _minEvictableIdleTimeMillis; 528 } 529 530 540 public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) { 541 assertInitializationAllowed(); 542 _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 543 } 544 545 548 public final boolean isTestWhileIdle() { 549 return getTestWhileIdle(); 550 } 551 552 561 public boolean getTestWhileIdle() { 562 return _testWhileIdle; 563 } 564 565 574 public void setTestWhileIdle(boolean testWhileIdle) { 575 assertInitializationAllowed(); 576 _testWhileIdle = testWhileIdle; 577 testPositionSet = true; 578 } 579 580 586 public String getValidationQuery() { 587 return (this.validationQuery); 588 } 589 590 597 public void setValidationQuery(String validationQuery) { 598 assertInitializationAllowed(); 599 this.validationQuery = validationQuery; 600 if (!testPositionSet) { 601 setTestOnBorrow(true); 602 } 603 } 604 605 608 611 614 public Connection getConnection() throws SQLException { 615 return getConnection(null, null); 616 } 617 618 621 public Connection getConnection(String username, String password) 622 throws SQLException { 623 if (instanceKey == null) { 624 throw new SQLException ("Must set the ConnectionPoolDataSource " 625 + "through setDataSourceName or setConnectionPoolDataSource" 626 + " before calling getConnection."); 627 } 628 getConnectionCalled = true; 629 PooledConnectionAndInfo info = null; 630 try { 631 info = getPooledConnectionAndInfo(username, password); 632 } catch (NoSuchElementException e) { 633 closeDueToException(info); 634 throw new SQLNestedException("Cannot borrow connection from pool", e); 635 } catch (RuntimeException e) { 636 closeDueToException(info); 637 throw e; 638 } catch (SQLException e) { 639 closeDueToException(info); 640 throw e; 641 } catch (Exception e) { 642 closeDueToException(info); 643 throw new SQLNestedException("Cannot borrow connection from pool", e); 644 } 645 646 if (!(null == password ? null == info.getPassword() 647 : password.equals(info.getPassword()))) { 648 closeDueToException(info); 649 throw new SQLException ("Given password did not match password used" 650 + " to create the PooledConnection."); 651 } 652 653 Connection con = info.getPooledConnection().getConnection(); 654 setupDefaults(con, username); 655 con.clearWarnings(); 656 return con; 657 } 658 659 protected abstract PooledConnectionAndInfo 660 getPooledConnectionAndInfo(String username, String password) 661 throws SQLException ; 662 663 protected abstract void setupDefaults(Connection con, String username) 664 throws SQLException ; 665 666 667 private void closeDueToException(PooledConnectionAndInfo info) { 668 if (info != null) { 669 try { 670 info.getPooledConnection().getConnection().close(); 671 } catch (Exception e) { 672 getLogWriter().println("[ERROR] Could not return connection to " 676 + "pool during exception handling. " + e.getMessage()); 677 } 678 } 679 } 680 681 protected ConnectionPoolDataSource 682 testCPDS(String username, String password) 683 throws javax.naming.NamingException , SQLException { 684 ConnectionPoolDataSource cpds = this.cpds; 686 if (cpds == null) { 687 Context ctx = null; 688 if (jndiEnvironment == null) { 689 ctx = new InitialContext (); 690 } else { 691 ctx = new InitialContext (jndiEnvironment); 692 } 693 Object ds = ctx.lookup(dataSourceName); 694 if (ds instanceof ConnectionPoolDataSource ) { 695 cpds = (ConnectionPoolDataSource ) ds; 696 } else { 697 throw new SQLException ("Illegal configuration: " 698 + "DataSource " + dataSourceName 699 + " (" + ds.getClass().getName() + ")" 700 + " doesn't implement javax.sql.ConnectionPoolDataSource"); 701 } 702 } 703 704 PooledConnection conn = null; 706 try { 707 if (username != null) { 708 conn = cpds.getPooledConnection(username, password); 709 } 710 else { 711 conn = cpds.getPooledConnection(); 712 } 713 if (conn == null) { 714 throw new SQLException ( 715 "Cannot connect using the supplied username/password"); 716 } 717 } 718 finally { 719 if (conn != null) { 720 try { 721 conn.close(); 722 } 723 catch (SQLException e) { 724 } 726 } 727 } 728 return cpds; 729 } 730 731 protected byte whenExhaustedAction(int maxActive, int maxWait) { 732 byte whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_BLOCK; 733 if (maxActive <= 0) { 734 whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_GROW; 735 } else if (maxWait == 0) { 736 whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_FAIL; 737 } 738 return whenExhausted; 739 } 740 741 744 748 public Reference getReference() throws NamingException { 749 Reference ref = new Reference (getClass().getName(), 750 InstanceKeyObjectFactory.class.getName(), null); 751 ref.add(new StringRefAddr ("instanceKey", instanceKey)); 752 return ref; 753 } 754 } 755 | Popular Tags |