1 6 package org.logicalcobwebs.proxool; 7 8 import org.apache.commons.logging.Log; 9 import org.apache.commons.logging.LogFactory; 10 import org.logicalcobwebs.proxool.admin.Admin; 11 import org.logicalcobwebs.proxool.admin.SnapshotIF; 12 import org.logicalcobwebs.proxool.admin.StatisticsIF; 13 import org.logicalcobwebs.proxool.admin.StatisticsListenerIF; 14 15 import java.lang.reflect.Method ; 16 import java.sql.Connection ; 17 import java.sql.Statement ; 18 import java.util.Collection ; 19 import java.util.HashMap ; 20 import java.util.Map ; 21 import java.util.Properties ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.ArrayList ; 25 26 39 public class ProxoolFacade { 40 41 private static final Log LOG = LogFactory.getLog(ProxoolFacade.class); 42 43 private static Map configurators = new HashMap (); 44 45 private static CompositeProxoolListener compositeProxoolListener = new CompositeProxoolListener(); 46 47 private static boolean versionLogged = false; 48 49 53 private static Thread shutdownHook; 54 55 59 private static boolean shutdownHookEnabled = true; 60 61 68 public static synchronized String registerConnectionPool(String url, Properties info) throws ProxoolException { 69 return registerConnectionPool(url, info, true); 70 } 71 72 81 protected static synchronized String registerConnectionPool(String url, Properties info, boolean explicitRegister) throws ProxoolException { 82 String alias = getAlias(url); 83 84 if (!versionLogged) { 85 versionLogged = true; 86 LOG.info("Proxool " + Version.getVersion()); 87 } 88 89 try { 90 Class.forName(ProxoolDriver.class.getName()); 91 } catch (ClassNotFoundException e) { 92 LOG.error("Couldn't load " + ProxoolDriver.class.getName()); 93 } 94 95 if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) { 96 ConnectionPoolDefinition cpd = new ConnectionPoolDefinition(url, info, explicitRegister); 97 registerConnectionPool(cpd); 98 } else { 99 throw new ProxoolException("Attempt to register duplicate pool called '" + alias + "'"); 100 } 101 102 return alias; 103 } 104 105 protected synchronized static void registerConnectionPool(ConnectionPoolDefinition connectionPoolDefinition) throws ProxoolException { 106 if (!ConnectionPoolManager.getInstance().isPoolExists(connectionPoolDefinition.getAlias())) { 108 Properties jndiProperties = extractJndiProperties(connectionPoolDefinition); 109 ConnectionPool connectionPool = ConnectionPoolManager.getInstance().createConnectionPool(connectionPoolDefinition); 110 connectionPool.start(); 111 compositeProxoolListener.onRegistration(connectionPoolDefinition, connectionPoolDefinition.getCompleteInfo()); 112 if (isConfiguredForJMX(connectionPoolDefinition.getCompleteInfo())) { 113 registerForJmx(connectionPoolDefinition.getAlias(), connectionPoolDefinition.getCompleteInfo()); 114 } 115 if (jndiProperties != null) { 116 registerDataSource(connectionPoolDefinition.getAlias(), jndiProperties); 117 } 118 } else { 119 LOG.debug("Ignoring duplicate attempt to register " + connectionPoolDefinition.getAlias() + " pool"); 120 } 121 } 122 123 127 public static void registerConnectionPool(String url) throws ProxoolException { 128 registerConnectionPool(url, null); 129 } 130 131 140 protected static String getAlias(String url) throws ProxoolException { 141 String alias = null; 142 final String prefix = ProxoolConstants.PROXOOL + ProxoolConstants.ALIAS_DELIMITER; 143 144 if (url.startsWith(prefix)) { 146 147 int endOfPrefix = url.indexOf(ProxoolConstants.URL_DELIMITER); 149 150 if (endOfPrefix > -1) { 151 alias = url.substring(prefix.length(), endOfPrefix); 152 } else { 153 alias = url.substring(prefix.length()); 154 } 155 } 156 157 if (alias == null || alias.length() == 0) { 159 throw new ProxoolException("The URL '" + url + "' is not in the correct form. It should be: 'proxool.alias:driver:url'"); 160 } 161 162 return alias; 163 } 164 165 171 private static void removeConnectionPool(String finalizer, ConnectionPool connectionPool, int delay) { 172 final String alias = connectionPool.getDefinition().getAlias(); 173 if (connectionPool != null) { 174 try { 175 compositeProxoolListener.onShutdown(alias); 176 connectionPool.shutdown(delay, finalizer); 177 } catch (Throwable t) { 178 LOG.error("Problem trying to shutdown '" + alias + "' connection pool", t); 179 } 180 } 181 connectionPool = null; 182 } 183 184 190 public static void removeConnectionPool(String alias, int delay) throws ProxoolException { 191 removeConnectionPool(Thread.currentThread().getName(), ConnectionPoolManager.getInstance().getConnectionPool(alias), delay); 192 } 193 194 199 public static void removeAllConnectionPools(int delay) { 200 shutdown(Thread.currentThread().getName(), delay); 201 } 202 203 208 public static void shutdown() { 209 shutdown(Thread.currentThread().getName(), 0); 210 } 211 212 217 public static void shutdown(int delay) { 218 shutdown(Thread.currentThread().getName(), delay); 219 } 220 221 226 protected static void shutdown(String finalizer, int delay) { 227 228 ConnectionPool[] cps = ConnectionPoolManager.getInstance().getConnectionPools(); 229 for (int i = 0; i < cps.length; i++) { 230 removeConnectionPool(finalizer, cps[i], delay); 231 } 232 233 try { 235 if (shutdownHook != null) { 236 ShutdownHook.remove(shutdownHook); 237 } 238 } catch (Throwable t) { 239 if (LOG.isDebugEnabled()) { 240 LOG.debug("Unanticipated error during removal of ShutdownHook. Ignoring it.", t); 241 } 242 } 243 244 PrototyperController.shutdown(); 246 HouseKeeperController.shutdown(); 247 248 } 249 250 254 public static void disableShutdownHook() { 255 ProxoolFacade.shutdownHookEnabled = false; 256 } 257 258 263 public static void enableShutdownHook() { 264 ProxoolFacade.shutdownHookEnabled = true; 265 } 266 267 273 public static boolean isShutdownHookEnabled() { 274 return shutdownHookEnabled; 275 } 276 277 283 public static void removeConnectionPool(String alias) throws ProxoolException { 284 removeConnectionPool(alias, 0); 285 } 286 287 294 public static ConnectionPoolStatisticsIF getConnectionPoolStatistics(String alias) throws ProxoolException { 295 return ConnectionPoolManager.getInstance().getConnectionPool(alias); 296 } 297 298 306 public static String getConnectionPoolStatisticsDump(String alias) throws ProxoolException { 307 return ConnectionPoolManager.getInstance().getConnectionPool(alias).displayStatistics(); 308 } 309 310 315 public static ConnectionPoolDefinitionIF getConnectionPoolDefinition(String alias) throws ProxoolException { 316 return ConnectionPoolManager.getInstance().getConnectionPool(alias).getDefinition(); 317 } 318 319 327 public static Collection getConnectionInfos(String alias) throws ProxoolException { 328 return ConnectionPoolManager.getInstance().getConnectionPool(alias).getConnectionInfos(); 329 } 330 331 340 public static void killAllConnections(String alias, boolean merciful) throws ProxoolException { 341 killAllConnections(alias, "of thread " + Thread.currentThread().getName(), merciful); 342 } 343 344 352 public static void killAllConnections(String alias, String reason, boolean merciful) throws ProxoolException { 353 ConnectionPoolManager.getInstance().getConnectionPool(alias).expireAllConnections(reason, merciful); 354 } 355 356 363 public static void killAllConnections(String alias) throws ProxoolException { 364 killAllConnections(alias, "of thread " + Thread.currentThread().getName(), MERCIFUL); 365 } 366 367 373 public static void killAllConnections(String alias, String reason) throws ProxoolException { 374 killAllConnections(alias, reason, MERCIFUL); 375 } 376 377 385 public static boolean killConnecton(String alias, long id, boolean merciful) throws ProxoolException { 386 boolean forceExpiry = !merciful; 388 return ConnectionPoolManager.getInstance().getConnectionPool(alias).expireConnection(id, forceExpiry); 389 } 390 391 398 public static boolean killConnecton(Connection connection, boolean merciful) throws ProxoolException { 399 WrappedConnection wrappedConnection = ProxyFactory.getWrappedConnection(connection); 400 if (wrappedConnection != null) { 401 long id = wrappedConnection.getId(); 402 String alias = wrappedConnection.getAlias(); 403 return killConnecton(alias, id, merciful); 404 } else { 405 throw new ProxoolException("Attempt to kill unrecognised exception " + connection); 406 } 407 } 408 409 413 public static void addProxoolListener(ProxoolListenerIF proxoolListener) { 414 compositeProxoolListener.addListener(proxoolListener); 415 } 416 417 422 public static boolean removeProxoolListener(ProxoolListenerIF proxoolListener) { 423 return compositeProxoolListener.removeListener(proxoolListener); 424 } 425 426 429 public static void setStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { 430 addStateListener(alias, stateListener); 431 } 432 433 439 public static void addStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { 440 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 441 cp.addStateListener(stateListener); 442 } 443 444 451 public boolean removeStateListener(String alias, StateListenerIF stateListener) throws ProxoolException { 452 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 453 return cp.removeStateListener(stateListener); 454 } 455 456 459 public static void setConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { 460 addConnectionListener(alias, connectionListener); 461 } 462 463 469 public static void addConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { 470 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 471 cp.addConnectionListener(connectionListener); 472 } 473 474 481 public static boolean removeConnectionListener(String alias, ConnectionListenerIF connectionListener) throws ProxoolException { 482 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 483 return cp.removeConnectionListener(connectionListener); 484 } 485 486 489 public static void setConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { 490 addConfigurationListener(alias, configurationListener); 491 } 492 493 499 public static void addConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { 500 if (ConnectionPoolManager.getInstance().isPoolExists(alias)) { 501 CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) 502 configurators.get(alias); 503 if (compositeConfigurationListener == null) { 504 compositeConfigurationListener = new CompositeConfigurationListener(); 505 configurators.put(alias, compositeConfigurationListener); 506 } 507 compositeConfigurationListener.addListener(configurationListener); 508 } else { 509 throw new ProxoolException(ConnectionPoolManager.getInstance().getKnownPools(alias)); 510 } 511 } 512 513 521 protected static void definitionUpdated(String alias, ConnectionPoolDefinitionIF connectionPoolDefinition, 522 Properties completeInfo, Properties changedInfo) { 523 CompositeConfigurationListener ccl = (CompositeConfigurationListener) configurators.get(alias); 524 if (ccl != null) { 525 ccl.definitionUpdated(connectionPoolDefinition, completeInfo, changedInfo); 526 } 527 } 528 529 537 public static boolean removeConfigurationListener(String alias, ConfigurationListenerIF configurationListener) throws ProxoolException { 538 boolean removed = false; 539 if (ConnectionPoolManager.getInstance().isPoolExists(alias)) { 540 CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) 541 configurators.get(alias); 542 if (compositeConfigurationListener != null) { 543 removed = compositeConfigurationListener.removeListener(configurationListener); 544 } 545 } else { 546 throw new ProxoolException(ConnectionPoolManager.getInstance().getKnownPools(alias)); 547 } 548 return removed; 549 } 550 551 554 private static final boolean MERCIFUL = true; 555 556 565 public static void redefineConnectionPool(String url, Properties info) throws ProxoolException { 566 String alias = getAlias(url); 567 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 568 try { 569 ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp.getDefinition().clone(); 571 cpd.redefine(url, info); 572 cp.setDefinition(cpd); 573 } catch (CloneNotSupportedException e) { 574 throw new ProxoolException("Funny, why couldn't we clone a definition?", e); 575 } 576 } 577 578 579 587 public static void updateConnectionPool(String url, Properties info) throws ProxoolException { 588 String alias = getAlias(url); 589 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 590 try { 591 ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp.getDefinition().clone(); 593 cpd.update(url, info); 594 cp.setDefinition(cpd); 595 } catch (CloneNotSupportedException e) { 596 throw new ProxoolException("Funny, why couldn't we clone a definition?", e); 597 } 598 } 599 600 protected void finalize() throws Throwable { 601 super.finalize(); 602 LOG.debug("Finalising"); 603 } 604 605 610 public static Statement getDelegateStatement(Statement statement) throws ProxoolException { 611 try { 612 return ProxyFactory.getDelegateStatement(statement); 613 } catch (IllegalArgumentException e) { 614 throw new ProxoolException("Statement argument is not one provided by Proxool (it's a " + statement.getClass() + ")"); 615 } 616 } 617 618 623 public static Connection getDelegateConnection(Connection connection) throws ProxoolException { 624 try { 625 return ProxyFactory.getDelegateConnection(connection); 626 } catch (IllegalArgumentException e) { 627 throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); 628 } 629 } 630 631 637 public static long getId(Connection connection) throws ProxoolException { 638 try { 639 return ProxyFactory.getWrappedConnection(connection).getId(); 640 } catch (NullPointerException e) { 641 throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); 642 } catch (IllegalArgumentException e) { 643 throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); 644 } 645 } 646 647 653 public static String getAlias(Connection connection) throws ProxoolException { 654 try { 655 return ProxyFactory.getWrappedConnection(connection).getAlias(); 656 } catch (NullPointerException e) { 657 throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); 658 } catch (IllegalArgumentException e) { 659 throw new ProxoolException("Connection argument is not one provided by Proxool (it's a " + connection.getClass() + ")"); 660 } 661 } 662 663 668 public static String [] getAliases() { 669 return ConnectionPoolManager.getInstance().getConnectionPoolNames(); 670 } 671 672 679 public static StatisticsIF getStatistics(String alias, String token) throws ProxoolException { 680 return ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin().getStatistics(token); 681 } 682 683 689 public static StatisticsIF[] getStatistics(String alias) throws ProxoolException { 690 final Admin monitor = ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin(); 691 if (monitor != null) { 692 return monitor.getStatistics(); 693 } else { 694 return new StatisticsIF[0]; 695 } 696 } 697 698 703 public static void addStatisticsListener(String alias, StatisticsListenerIF statisticsListener) throws ProxoolException { 704 final Admin monitor = ConnectionPoolManager.getInstance().getConnectionPool(alias).getAdmin(); 706 if (monitor != null) { 707 monitor.addStatisticsListener(statisticsListener); 708 } else { 709 throw new ProxoolException("Statistics are switched off, your can't add a listener"); 710 } 711 } 712 713 724 public static SnapshotIF getSnapshot(String alias, boolean detail) throws ProxoolException { 725 SnapshotIF snapshot = null; 726 ConnectionPool cp = ConnectionPoolManager.getInstance().getConnectionPool(alias); 727 728 if (detail) { 729 try { 730 long start = System.currentTimeMillis(); 732 if (cp.attemptConnectionStatusReadLock(10000)) { 733 snapshot = Admin.getSnapshot(cp, cp.getDefinition(), cp.getConnectionInfos()); 734 } else { 735 LOG.warn("Give up waiting for detailed snapshot after " + (System.currentTimeMillis() - start) + " milliseconds. Serving standard snapshot instead."); 736 } 737 } finally { 738 cp.releaseConnectionStatusReadLock(); 739 } 740 } 741 if (snapshot == null) { 742 snapshot = Admin.getSnapshot(cp, cp.getDefinition(), null); 743 } 744 745 return snapshot; 746 } 747 748 753 public static SnapshotIF getSnapshot(String alias) throws ProxoolException { 754 return getSnapshot(alias, false); 755 } 756 757 private static boolean registerForJmx(String alias, Properties properties) { 760 boolean success = false; 761 try { 762 Class jmxHelperClass = Class.forName("org.logicalcobwebs.proxool.admin.jmx.ProxoolJMXHelper"); 763 Method registerMethod = jmxHelperClass.getDeclaredMethod("registerPool", new Class []{String .class, Properties .class}); 764 registerMethod.invoke(null, new Object []{alias, properties}); 765 success = true; 766 } catch (Exception e) { 767 LOG.error("JMX registration of " + alias + " pool failed.", e); 768 } 769 return success; 770 } 771 772 private static boolean registerDataSource(String alias, Properties jndiProperties) { 775 boolean success = false; 776 try { 777 Class jndiHelperClass = Class.forName("org.logicalcobwebs.proxool.admin.jndi.ProxoolJNDIHelper"); 778 Method registerMethod = jndiHelperClass.getDeclaredMethod("registerDatasource", new Class []{String .class, 779 Properties .class}); 780 registerMethod.invoke(null, new Object []{alias, jndiProperties}); 781 success = true; 782 } catch (Exception e) { 783 LOG.error("JNDI DataSource binding of " + alias + " pool failed.", e); 784 } 785 return success; 786 } 787 788 795 private static Properties extractJndiProperties(ConnectionPoolDefinition connectionPoolDefinition) { 796 if (connectionPoolDefinition.getJndiName() == null) { 797 return null; 798 } 799 Properties jndiProperties = new Properties (); 800 jndiProperties.setProperty(ProxoolConstants.JNDI_NAME, connectionPoolDefinition.getJndiName()); 801 if (connectionPoolDefinition.getDelegateProperties() != null) { 802 Properties delegateProperties = connectionPoolDefinition.getDelegateProperties(); 803 String propertyName = null; 806 List propertyNamesList = new ArrayList (10); 807 Iterator keySetIterator = delegateProperties.keySet().iterator(); 808 while (keySetIterator.hasNext()) { 809 propertyName = (String ) keySetIterator.next(); 810 if (propertyName.startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) { 811 propertyNamesList.add(propertyName); 812 } 813 } 814 for (int i = 0; i < propertyNamesList.size(); i++) { 815 propertyName = (String ) propertyNamesList.get(i); 816 if (propertyName.startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) { 817 jndiProperties.setProperty(propertyName.substring(ProxoolConstants.JNDI_PROPERTY_PREFIX.length()), 818 (String ) delegateProperties.getProperty(propertyName)); 819 delegateProperties.remove(propertyName); 820 } 821 } 822 } 823 return jndiProperties; 824 } 825 826 831 private static boolean isConfiguredForJMX(Properties poolProperties) { 832 final String jmxProperty = poolProperties.getProperty(ProxoolConstants.JMX_PROPERTY); 833 if (jmxProperty != null && jmxProperty.equalsIgnoreCase("true")) { 834 return true; 835 } else { 836 return false; 837 } 838 } 839 840 849 protected static void setShutdownHook(Thread t) { 850 shutdownHook = t; 851 } 852 } 853 854 1161 | Popular Tags |