1 21 22 package org.opensubsystems.core.persist.db.connectionpool; 23 24 import java.sql.Connection ; 25 import java.sql.SQLException ; 26 import java.util.Hashtable ; 27 import java.util.Iterator ; 28 import java.util.Map ; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 32 import org.opensubsystems.core.error.OSSConfigException; 33 import org.opensubsystems.core.error.OSSDatabaseAccessException; 34 import org.opensubsystems.core.error.OSSException; 35 import org.opensubsystems.core.persist.db.DatabaseConnectionFactoryImpl; 36 import org.opensubsystems.core.persist.db.DatabaseTransactionFactoryImpl; 37 import org.opensubsystems.core.util.GlobalConstants; 38 import org.opensubsystems.core.util.Log; 39 40 49 public abstract class PooledDatabaseConnectionFactoryImpl extends DatabaseConnectionFactoryImpl 50 { 51 55 class ConnectionPoolDefinition 56 { 57 60 protected String m_strConnectionPoolName; 61 62 65 protected String m_strDriverName; 66 67 70 protected String m_strUrl; 71 72 75 protected String m_strUser; 76 77 80 protected String m_strPassword; 81 82 85 protected Object m_connectionPool; 86 87 90 protected int m_requestedConnectionCount; 91 92 100 public ConnectionPoolDefinition( 101 String connectionPoolName, 102 String driverName, 103 String url, 104 String user, 105 String password, 106 Object connectionPool 107 ) 108 { 109 super(); 110 m_strConnectionPoolName = connectionPoolName; 111 m_strDriverName = driverName; 112 m_strUrl = url; 113 m_strUser = user; 114 m_strPassword = password; 115 m_connectionPool = connectionPool; 116 m_requestedConnectionCount = 0; 117 } 118 119 122 public Object getConnectionPool() 123 { 124 return m_connectionPool; 125 } 126 127 130 public String getConnectionPoolName() 131 { 132 return m_strConnectionPoolName; 133 } 134 135 138 public String getDriverName() 139 { 140 return m_strDriverName; 141 } 142 143 146 public String getPassword() 147 { 148 return m_strPassword; 149 } 150 151 154 public String getUrl() 155 { 156 return m_strUrl; 157 } 158 159 162 public String getUser() 163 { 164 return m_strUser; 165 } 166 167 170 public int getRequestedConnectionCount() 171 { 172 return m_requestedConnectionCount; 173 } 174 175 180 public int connectionRequested() 181 { 182 return m_requestedConnectionCount++; 183 } 184 185 190 public int connectionReturned() 191 { 192 if (GlobalConstants.ERROR_CHECKING) 193 { 194 assert m_requestedConnectionCount > 0 195 : "Cannot return connection that wasn't requested."; 196 } 197 return m_requestedConnectionCount--; 198 } 199 200 203 public String toString() 204 { 205 StringBuffer dump = new StringBuffer (); 206 207 dump.append("ConnectionPoolDefinition["); 208 dump.append("\n m_strConnectionPoolName = "); 209 if (m_strConnectionPoolName != null) 210 { 211 dump.append(m_strConnectionPoolName); 212 } 213 else 214 { 215 dump.append("null"); 216 } 217 dump.append("\n m_strDriverName = "); 218 if (m_strDriverName != null) 219 { 220 dump.append(m_strDriverName); 221 } 222 else 223 { 224 dump.append("null"); 225 } 226 dump.append("\n m_strUrl = "); 227 if (m_strUrl != null) 228 { 229 dump.append(m_strUrl); 230 } 231 else 232 { 233 dump.append("null"); 234 } 235 dump.append("\n m_strUser = "); 236 if (m_strUser != null) 237 { 238 dump.append(m_strUser); 239 } 240 else 241 { 242 dump.append("null"); 243 } 244 dump.append("\n m_strPassword = "); 245 if (m_strUser != null) 246 { 247 dump.append(m_strUser); 248 } 249 else 250 { 251 dump.append("null"); 252 } 253 dump.append("\n m_requestedConnectionCount = "); 254 dump.append(m_requestedConnectionCount); 255 dump.append("\n m_connectionPool = "); 256 if (m_connectionPool != null) 257 { 258 dump.append(m_connectionPool.toString()); 259 } 260 else 261 { 262 dump.append("null"); 263 } 264 dump.append("]"); 265 266 return dump.toString(); 267 } 268 } 269 270 272 278 public static final String DEFAULT_DATASOURCE_NAME = "OSSDS"; 279 280 282 285 protected ConnectionPoolDefinition m_defaultConnectionPool; 286 287 291 protected Map m_mpConnectionPools; 292 293 301 protected Map m_mpNotPooledConnections; 302 303 307 protected Map m_mpConnectionPoolCrossRef; 308 309 311 314 private static Logger s_logger = Log.getInstance(PooledDatabaseConnectionFactoryImpl.class); 315 316 318 321 public PooledDatabaseConnectionFactoryImpl( 322 ) 323 { 324 this(null); 325 } 326 327 333 public PooledDatabaseConnectionFactoryImpl( 334 DatabaseTransactionFactoryImpl transactionFactory 335 ) 336 { 337 super(transactionFactory); 338 339 m_mpNotPooledConnections = new Hashtable (); 341 m_mpConnectionPools = new Hashtable (); 342 m_mpConnectionPoolCrossRef = new Hashtable (); 343 } 344 345 358 public PooledDatabaseConnectionFactoryImpl( 359 String strDriver, 360 String strURL, 361 String strUser, 362 String strPassword, 363 DatabaseTransactionFactoryImpl transactionFactory 364 ) throws OSSConfigException, 365 OSSDatabaseAccessException 366 { 367 super(strDriver, strURL, strUser, strPassword, transactionFactory); 368 369 m_mpNotPooledConnections = new Hashtable (); 371 m_mpConnectionPools = new Hashtable (); 372 } 373 374 376 379 public final String getDefaultDataSourceName( 380 ) 381 { 382 String strName; 383 384 if (m_defaultConnectionPool != null) 385 { 386 strName = m_defaultConnectionPool.getConnectionPoolName(); 387 } 388 else 389 { 390 strName = ""; 391 } 392 393 return strName; 394 } 395 396 399 public final void addDataSource( 400 String strDataSourceName, 401 String strDriverName, 402 String strUrl, 403 String strUser, 404 String strPassword 405 ) throws OSSDatabaseAccessException 406 { 407 if (m_mpConnectionPools.get(strDataSourceName) == null) 408 { 409 Object connectionPool; 411 412 try 413 { 414 connectionPool = createConnectionPool(strDataSourceName, 415 strDriverName, 416 strUrl, 417 strUser, 418 strPassword); 419 } 420 catch (OSSDatabaseAccessException odaExc) 421 { 422 throw odaExc; 426 } 427 catch (OSSException ossExc) 428 { 429 throw new OSSDatabaseAccessException("Cannot create connection pool " 433 + strDataSourceName, ossExc); 434 } 435 436 m_mpConnectionPools.put(strDataSourceName, new ConnectionPoolDefinition( 437 strDataSourceName, 438 strDriverName, 439 strUrl, 440 strUser, 441 strPassword, 442 connectionPool)); 443 444 s_logger.fine("Connection pool " + strDataSourceName + " registered."); 445 } 446 else 447 { 448 s_logger.fine("Connection pool " + strDataSourceName + " already exists."); 449 throw new OSSDatabaseAccessException("Connection pool " + strDataSourceName 450 + " already exists."); 451 } 452 } 453 454 457 public final void setDefaultDataSourceName( 458 String strDataSourceName 459 ) 460 { 461 ConnectionPoolDefinition definition; 462 463 definition = (ConnectionPoolDefinition)m_mpConnectionPools.get(strDataSourceName); 466 if (definition == null) 467 { 468 throw new IllegalArgumentException ("Connection pool with name " 469 + strDataSourceName 470 + " doesn't exist."); 471 } 472 473 m_defaultConnectionPool = definition; 474 m_strDatabaseDriver = definition.getDriverName(); 475 m_strDatabaseURL = definition.getUrl(); 476 m_strDatabaseUser = definition.getUser(); 477 m_strDatabasePassword = definition.getPassword(); 478 } 479 480 483 public boolean isDataSourceDefined( 484 String strDataSourceName 485 ) 486 { 487 return (m_mpConnectionPools.get(strDataSourceName) != null); 488 } 489 490 493 public final void stop( 494 ) throws OSSException 495 { 496 s_logger.fine("Stopping connection pool."); 497 498 Iterator entries; 499 Map.Entry entry; 500 501 for (entries = m_mpNotPooledConnections.entrySet().iterator(); entries.hasNext();) 503 { 504 entry = (Map.Entry )entries.next(); 505 try 506 { 507 ((Connection )entry.getValue()).close(); 508 } 509 catch (Throwable thr) 510 { 511 s_logger.log(Level.WARNING, "Cannot close nonpoolable connection", 514 thr); 515 } 516 entries.remove(); 517 s_logger.fine("Nonpooled connection " + entry.getKey() 518 + " closed. THIS CONNECTION SHOULD" 519 + " HAVE BEEN PROBABLY CLOSED EXPLICITELY."); 520 } 521 522 for (entries = m_mpConnectionPools.entrySet().iterator(); entries.hasNext();) 524 { 525 entry = (Map.Entry )entries.next(); 526 try 527 { 528 closeConnectionPool((ConnectionPoolDefinition)entry.getValue()); 529 } 530 catch (Throwable thr) 531 { 532 throw new OSSDatabaseAccessException( 534 "Unexpected exception while closing connection pool" 535 + entry.getKey(), thr); 536 } 537 entries.remove(); 538 s_logger.fine("Connection pool " + entry.getKey() 539 + " shutdown and unregistered."); 540 } 541 542 if (GlobalConstants.ERROR_CHECKING) 543 { 544 assert m_mpNotPooledConnections.isEmpty() 545 : "Not all nonpooled connection were closed."; 546 assert m_mpConnectionPools.isEmpty() 547 : "Not all connection pools were closed."; 548 } 549 550 m_defaultConnectionPool = null; 553 554 s_logger.fine("Connection pool is stopped."); 555 } 556 557 560 public int getRequestedConnectionCount() 561 { 562 return m_defaultConnectionPool.getRequestedConnectionCount(); 563 } 564 565 568 public int getRequestedConnectionCount( 569 String strDataSourceName 570 ) 571 { 572 ConnectionPoolDefinition definition; 573 int iConnectionCountReturn = 0; 574 575 definition = (ConnectionPoolDefinition)m_mpConnectionPools.get(strDataSourceName); 578 if (definition == null) 579 { 580 throw new IllegalArgumentException ("Connection pool with name " + strDataSourceName 581 + " doesn't exist."); 582 } 583 else 584 { 585 iConnectionCountReturn = definition.getRequestedConnectionCount(); 586 } 587 588 return iConnectionCountReturn; 589 } 590 591 594 public String debug( 595 ) 596 { 597 StringBuffer dump = new StringBuffer (); 598 599 dump.append("PooledDatabaseConnectionFactoryImpl["); 600 if (m_defaultConnectionPool != null) 601 { 602 dump.append("\n m_defaultConnectionPool.getConnectionPoolName() = "); 603 dump.append(m_defaultConnectionPool.getConnectionPoolName()); 604 } 605 else 606 { 607 dump.append("\n m_defaultConnectionPool = null"); 608 } 609 dump.append("\n m_mpConnectionPools = "); 610 if (m_mpConnectionPools != null) 611 { 612 dump.append(m_mpConnectionPools); 613 } 614 else 615 { 616 dump.append("null"); 617 } 618 dump.append("\n m_mpNotPooledConnections = "); 619 if (m_mpNotPooledConnections != null) 620 { 621 dump.append(m_mpNotPooledConnections); 622 } 623 else 624 { 625 dump.append("null"); 626 } 627 dump.append("]"); 628 629 633 return dump.toString(); 634 } 635 636 638 641 protected Connection requestNonTransactionalConnection( 642 boolean bAutoCommit 643 ) throws OSSDatabaseAccessException 644 { 645 Connection cntDBConnection; 646 647 652 if (m_defaultConnectionPool == null) 653 { 654 start(); 655 } 656 657 if (m_defaultConnectionPool != null) 659 { 660 cntDBConnection = getPooledConnection(m_defaultConnectionPool); 665 666 if (cntDBConnection == null) 667 { 668 throw new OSSDatabaseAccessException("Cannot get database connection" + 669 " for an unknown reason"); 670 } 671 672 m_iRequestedConnectionCount++; 674 675 m_mpConnectionPoolCrossRef.put(cntDBConnection, m_defaultConnectionPool); 679 m_defaultConnectionPool.connectionRequested(); 680 681 try 682 { 683 initializeConnection(cntDBConnection, bAutoCommit); 684 } 685 catch (SQLException sqleExc) 686 { 687 throw new OSSDatabaseAccessException( 690 "Cannot initialize database connection", sqleExc); 691 } 692 } 693 else 694 { 695 throw new OSSDatabaseAccessException("Cannot get database connection" + 696 " since no default connection pool is defined."); 697 698 } 699 700 return cntDBConnection; 701 } 702 703 706 protected final Connection requestNonTransactionalConnection( 707 boolean bAutoCommit, 708 String strUser, 709 String strPassword 710 ) throws OSSDatabaseAccessException 711 { 712 Connection cntDBConnection; 713 714 719 if ((m_defaultConnectionPool != null) 720 && (m_defaultConnectionPool.getUser().equals(strUser)) 721 && (m_defaultConnectionPool.getPassword().equals(strPassword))) 722 { 723 cntDBConnection = requestNonTransactionalConnection(bAutoCommit); 726 } 727 else 728 { 729 cntDBConnection = getPooledConnection(m_defaultConnectionPool, 734 strUser, strPassword); 735 736 if (cntDBConnection == null) 737 { 738 throw new OSSDatabaseAccessException("Cannot get database connection" + 739 " for an unknown reason"); 740 } 741 m_iRequestedConnectionCount++; 743 744 m_mpConnectionPoolCrossRef.put(cntDBConnection, m_defaultConnectionPool); 748 m_defaultConnectionPool.connectionRequested(); 749 750 try 751 { 752 initializeConnection(cntDBConnection, bAutoCommit); 753 } 754 catch (SQLException sqleExc) 755 { 756 throw new OSSDatabaseAccessException( 759 "Cannot initialize database connection", sqleExc); 760 } 761 } 762 763 return cntDBConnection; 764 } 765 766 769 protected final Connection requestNonTransactionalConnection( 770 boolean bAutoCommit, 771 String strDataSourceName 772 ) throws OSSDatabaseAccessException 773 { 774 ConnectionPoolDefinition connectionPool; 775 Connection cntDBConnection; 776 777 connectionPool = (ConnectionPoolDefinition)m_mpConnectionPools.get(strDataSourceName); 780 if (connectionPool == null) 781 { 782 throw new IllegalArgumentException ("Connection pool with name " + strDataSourceName 783 + " doesn't exist."); 784 } 785 else 786 { 787 cntDBConnection = getPooledConnection(connectionPool); 788 789 m_iRequestedConnectionCount++; 791 792 m_mpConnectionPoolCrossRef.put(cntDBConnection, connectionPool); 796 connectionPool.connectionRequested(); 797 798 try 799 { 800 initializeConnection(cntDBConnection, bAutoCommit); 801 } 802 catch (SQLException sqleExc) 803 { 804 throw new OSSDatabaseAccessException( 807 "Cannot initialize database connection", sqleExc); 808 } 809 } 810 811 return cntDBConnection; 812 } 813 814 817 protected final Connection requestNonTransactionalConnection( 818 boolean bAutoCommit, 819 String strDataSourceName, 820 String strUser, 821 String strPassword 822 ) throws OSSDatabaseAccessException 823 { 824 ConnectionPoolDefinition connectionPool; 825 Connection cntDBConnection; 826 827 connectionPool = (ConnectionPoolDefinition)m_mpConnectionPools.get(strDataSourceName); 830 if (connectionPool == null) 831 { 832 throw new IllegalArgumentException ("Connection pool with name " + strDataSourceName 833 + " doesn't exist."); 834 } 835 else 836 { 837 cntDBConnection = getPooledConnection(connectionPool, strUser, strPassword); 838 839 m_iRequestedConnectionCount++; 841 842 m_mpConnectionPoolCrossRef.put(cntDBConnection, connectionPool); 846 connectionPool.connectionRequested(); 847 848 try 849 { 850 initializeConnection(cntDBConnection, bAutoCommit); 851 } 852 catch (SQLException sqleExc) 853 { 854 throw new OSSDatabaseAccessException( 857 "Cannot initialize database connection", sqleExc); 858 } 859 } 860 861 return cntDBConnection; 862 } 863 864 867 public final void returnNonTransactionalConnection( 868 Connection cntDBConnection 869 ) 870 { 871 if (cntDBConnection != null) 872 { 873 if (GlobalConstants.ERROR_CHECKING) 874 { 875 try 876 { 877 if (cntDBConnection.isClosed()) 878 { 879 assert false : "Returning closed connection."; 880 } 881 } 882 catch (SQLException sqleExc) 883 { 884 s_logger.log(Level.WARNING, 885 "Cannot check if database connection is closed", 886 sqleExc); 887 } 888 } 889 890 906 907 if (GlobalConstants.ERROR_CHECKING) 909 { 910 assert m_iRequestedConnectionCount > 0 911 : "Cannot return connection that wasn't requested."; 912 } 913 914 m_iRequestedConnectionCount--; 915 ConnectionPoolDefinition connectionPool; 918 919 connectionPool = (ConnectionPoolDefinition)m_mpConnectionPoolCrossRef.remove( 920 cntDBConnection); 921 if (connectionPool != null) 922 { 923 connectionPool.connectionReturned(); 925 } 926 927 if (m_mpNotPooledConnections.remove(cntDBConnection) != null) 929 { 930 try 932 { 933 cntDBConnection.close(); 934 } 935 catch (SQLException sqleExc) 936 { 937 s_logger.log(Level.WARNING, "Closing of connection has failed.", 938 sqleExc); 939 } 940 } 941 else 942 { 943 returnPooledConnection(cntDBConnection); 944 } 945 } 946 } 947 948 953 protected void start( 954 ) throws OSSDatabaseAccessException 955 { 956 if (m_defaultConnectionPool == null) 957 { 958 addDataSource(DEFAULT_DATASOURCE_NAME, 960 getDatabaseDriver(), 961 getDatabaseURL(), 962 getDatabaseUser(), 963 getDatabasePassword()); 964 setDefaultDataSourceName(DEFAULT_DATASOURCE_NAME); 965 } 966 967 s_logger.fine("Connection pool is running..."); 968 } 969 970 977 protected abstract Connection getPooledConnection( 978 ConnectionPoolDefinition connectionpool 979 ) throws OSSDatabaseAccessException; 980 981 991 protected abstract Connection getPooledConnection( 992 ConnectionPoolDefinition connectionpool, 993 String strUser, 994 String strPassword 995 ) throws OSSDatabaseAccessException; 996 997 1006 protected void returnPooledConnection( 1007 Connection cntDBConnection 1008 ) 1009 { 1010 try 1011 { 1012 cntDBConnection.close(); 1013 } 1014 catch (SQLException sqleExc) 1015 { 1016 s_logger.log(Level.WARNING, "Cannot return connection to pool", 1018 sqleExc); 1019 } 1020 } 1021 1022 1033 protected abstract Object createConnectionPool( 1034 String strConnectionPoolName, 1035 String strDriverName, 1036 String strUrl, 1037 String strUser, 1038 String strPassword 1039 ) throws OSSException; 1040 1041 1048 protected abstract void closeConnectionPool( 1049 ConnectionPoolDefinition connectionpool 1050 ) throws OSSException; 1051} 1052 | Popular Tags |