0001: /*
0002: * This software is released under a licence similar to the Apache Software Licence.
0003: * See org.logicalcobwebs.proxool.package.html for details.
0004: * The latest version is available at http://proxool.sourceforge.net
0005: */
0006: package org.logicalcobwebs.proxool;
0007:
0008: import org.apache.commons.logging.Log;
0009: import org.apache.commons.logging.LogFactory;
0010: import org.logicalcobwebs.proxool.admin.Admin;
0011: import org.logicalcobwebs.proxool.admin.SnapshotIF;
0012: import org.logicalcobwebs.proxool.admin.StatisticsIF;
0013: import org.logicalcobwebs.proxool.admin.StatisticsListenerIF;
0014:
0015: import java.lang.reflect.Method;
0016: import java.sql.Connection;
0017: import java.sql.Statement;
0018: import java.util.Collection;
0019: import java.util.HashMap;
0020: import java.util.Map;
0021: import java.util.Properties;
0022: import java.util.Iterator;
0023: import java.util.List;
0024: import java.util.ArrayList;
0025:
0026: /**
0027: * <p>This provides some nice-to-have features that can't be provided by the
0028: * {@link java.sql.Driver} {@link ProxoolDriver implementation} of java.sql.Driver. Like starting up
0029: * a pool before you need a connection. And getting statistical information.</p>
0030: *
0031: * <p>You need to use this class wisely. It is obviously specfic to proxool so it will
0032: * stop you switching to another driver. Consider isolating the code that calls this
0033: * class so that you can easily remove it if you have to.</p>
0034: *
0035: * @version $Revision: 1.85 $, $Date: 2006/11/02 10:00:34 $
0036: * @author billhorsman
0037: * @author $Author: billhorsman $ (current maintainer)
0038: */
0039: public class ProxoolFacade {
0040:
0041: private static final Log LOG = LogFactory
0042: .getLog(ProxoolFacade.class);
0043:
0044: private static Map configurators = new HashMap();
0045:
0046: private static CompositeProxoolListener compositeProxoolListener = new CompositeProxoolListener();
0047:
0048: private static boolean versionLogged = false;
0049:
0050: /**
0051: * This is the thread that has been registered with {@link Runtime} as a
0052: * shutdownHook. It is removed during shutdown.
0053: */
0054: private static Thread shutdownHook;
0055:
0056: /**
0057: * If you setthis to false then it us up to you to call shutdown explicitly
0058: * @see #shutdown(String, int)
0059: */
0060: private static boolean shutdownHookEnabled = true;
0061:
0062: /**
0063: * Build a ConnectionPool based on this definition and then start it.
0064: * @param url defines the delegate driver and delegate url.
0065: * @param info the properties used to configure Proxool (and any for the delegate driver too) - optional
0066: * @return the alias for this pool (or the full url if no alias is specified)
0067: * @throws ProxoolException if anything goes wrong
0068: */
0069: public static synchronized String registerConnectionPool(
0070: String url, Properties info) throws ProxoolException {
0071: return registerConnectionPool(url, info, true);
0072: }
0073:
0074: /**
0075: * Build a ConnectionPool based on this definition and then start it.
0076: * @param url defines the delegate driver and delegate url.
0077: * @param info the properties used to configure Proxool (and any for the delegate driver too) - optional
0078: * @param explicitRegister set to true if we are registering a new pool explicitly, or false
0079: * if it's just because we are serving a url that we haven't come across before
0080: * @return the alias for this pool (or the full url if no alias is specified)
0081: * @throws ProxoolException if anything goes wrong
0082: */
0083: protected static synchronized String registerConnectionPool(
0084: String url, Properties info, boolean explicitRegister)
0085: throws ProxoolException {
0086: String alias = getAlias(url);
0087:
0088: if (!versionLogged) {
0089: versionLogged = true;
0090: LOG.info("Proxool " + Version.getVersion());
0091: }
0092:
0093: try {
0094: Class.forName(ProxoolDriver.class.getName());
0095: } catch (ClassNotFoundException e) {
0096: LOG.error("Couldn't load " + ProxoolDriver.class.getName());
0097: }
0098:
0099: if (!ConnectionPoolManager.getInstance().isPoolExists(alias)) {
0100: ConnectionPoolDefinition cpd = new ConnectionPoolDefinition(
0101: url, info, explicitRegister);
0102: registerConnectionPool(cpd);
0103: } else {
0104: throw new ProxoolException(
0105: "Attempt to register duplicate pool called '"
0106: + alias + "'");
0107: }
0108:
0109: return alias;
0110: }
0111:
0112: protected synchronized static void registerConnectionPool(
0113: ConnectionPoolDefinition connectionPoolDefinition)
0114: throws ProxoolException {
0115: // check isPoolExists once more now we are inside synchronized block.
0116: if (!ConnectionPoolManager.getInstance().isPoolExists(
0117: connectionPoolDefinition.getAlias())) {
0118: Properties jndiProperties = extractJndiProperties(connectionPoolDefinition);
0119: ConnectionPool connectionPool = ConnectionPoolManager
0120: .getInstance().createConnectionPool(
0121: connectionPoolDefinition);
0122: connectionPool.start();
0123: compositeProxoolListener.onRegistration(
0124: connectionPoolDefinition, connectionPoolDefinition
0125: .getCompleteInfo());
0126: if (isConfiguredForJMX(connectionPoolDefinition
0127: .getCompleteInfo())) {
0128: registerForJmx(connectionPoolDefinition.getAlias(),
0129: connectionPoolDefinition.getCompleteInfo());
0130: }
0131: if (jndiProperties != null) {
0132: registerDataSource(connectionPoolDefinition.getAlias(),
0133: jndiProperties);
0134: }
0135: } else {
0136: LOG.debug("Ignoring duplicate attempt to register "
0137: + connectionPoolDefinition.getAlias() + " pool");
0138: }
0139: }
0140:
0141: /**
0142: * With no configurator or properties (using default values)
0143: * @see #registerConnectionPool(java.lang.String, java.util.Properties)
0144: */
0145: public static void registerConnectionPool(String url)
0146: throws ProxoolException {
0147: registerConnectionPool(url, null);
0148: }
0149:
0150: /**
0151: * Extracts the pool alias from the url:
0152: *
0153: * proxool.alias:driver:url -> alias
0154: * proxool.alias -> alias
0155: *
0156: * @return the alias defined within the url
0157: * @throws ProxoolException if we couldn't find the alias
0158: */
0159: protected static String getAlias(String url)
0160: throws ProxoolException {
0161: String alias = null;
0162: final String prefix = ProxoolConstants.PROXOOL
0163: + ProxoolConstants.ALIAS_DELIMITER;
0164:
0165: // Check that the prefix is there
0166: if (url.startsWith(prefix)) {
0167:
0168: // Check for the alias
0169: int endOfPrefix = url
0170: .indexOf(ProxoolConstants.URL_DELIMITER);
0171:
0172: if (endOfPrefix > -1) {
0173: alias = url.substring(prefix.length(), endOfPrefix);
0174: } else {
0175: alias = url.substring(prefix.length());
0176: }
0177: }
0178:
0179: // Check we found it.
0180: if (alias == null || alias.length() == 0) {
0181: throw new ProxoolException(
0182: "The URL '"
0183: + url
0184: + "' is not in the correct form. It should be: 'proxool.alias:driver:url'");
0185: }
0186:
0187: return alias;
0188: }
0189:
0190: /**
0191: * Remove a connection pool. Kills all the connections. Resets everything.
0192: * @param finalizer the name of the thread requesting shutdown (for logging)
0193: * @param connectionPool the pool to remove
0194: * @param delay the time to wait for connections to become inactive before killing it (milliseconds)
0195: */
0196: private static void removeConnectionPool(String finalizer,
0197: ConnectionPool connectionPool, int delay) {
0198: final String alias = connectionPool.getDefinition().getAlias();
0199: if (connectionPool != null) {
0200: try {
0201: compositeProxoolListener.onShutdown(alias);
0202: connectionPool.shutdown(delay, finalizer);
0203: } catch (Throwable t) {
0204: LOG.error("Problem trying to shutdown '" + alias
0205: + "' connection pool", t);
0206: }
0207: }
0208: connectionPool = null;
0209: }
0210:
0211: /**
0212: * Remove a connection pool. Kills all the connections. Resets everything.
0213: * @param alias the pool to remove
0214: * @param delay the time to wait for connections to become inactive before killing it (milliseconds)
0215: * @throws ProxoolException if we couldn't find the pool
0216: */
0217: public static void removeConnectionPool(String alias, int delay)
0218: throws ProxoolException {
0219: removeConnectionPool(Thread.currentThread().getName(),
0220: ConnectionPoolManager.getInstance().getConnectionPool(
0221: alias), delay);
0222: }
0223:
0224: /**
0225: * Removes all connection pools. Kills all the connections. Resets everything.
0226: * @param delay the time to wait for connections to become inactive before killing it (milliseconds)
0227: * @deprecated use the better named {@link #shutdown(int) shutdown()} instead.
0228: */
0229: public static void removeAllConnectionPools(int delay) {
0230: shutdown(Thread.currentThread().getName(), delay);
0231: }
0232:
0233: /**
0234: * Removes all connection pools. Kills all the connections. Resets everything.
0235: * Like {@link #shutdown(java.lang.String, int)} but passes the current thread name
0236: * and a delay of zero.
0237: */
0238: public static void shutdown() {
0239: shutdown(Thread.currentThread().getName(), 0);
0240: }
0241:
0242: /**
0243: * Removes all connection pools. Kills all the connections. Resets everything.
0244: * Like {@link #shutdown(java.lang.String, int)} but passes the current thread name.
0245: * @param delay the time to wait for connections to become inactive before killing it (milliseconds)
0246: */
0247: public static void shutdown(int delay) {
0248: shutdown(Thread.currentThread().getName(), delay);
0249: }
0250:
0251: /**
0252: * Removes all connection pools. Kills all the connections. Resets everything.
0253: * @param finalizer used to identify who is causing the pools to be removed (helps logging)
0254: * @param delay the time to wait for connections to become inactive before killing it (milliseconds)
0255: */
0256: protected static void shutdown(String finalizer, int delay) {
0257:
0258: ConnectionPool[] cps = ConnectionPoolManager.getInstance()
0259: .getConnectionPools();
0260: for (int i = 0; i < cps.length; i++) {
0261: removeConnectionPool(finalizer, cps[i], delay);
0262: }
0263:
0264: // If a shutdown hook was registered then remove it
0265: try {
0266: if (shutdownHook != null) {
0267: ShutdownHook.remove(shutdownHook);
0268: }
0269: } catch (Throwable t) {
0270: if (LOG.isDebugEnabled()) {
0271: LOG
0272: .debug(
0273: "Unanticipated error during removal of ShutdownHook. Ignoring it.",
0274: t);
0275: }
0276: }
0277:
0278: // Stop threads
0279: PrototyperController.shutdown();
0280: HouseKeeperController.shutdown();
0281:
0282: }
0283:
0284: /**
0285: * If you call this then you'll have to call shutdown explicitly
0286: * @see #shutdown(String, int)
0287: */
0288: public static void disableShutdownHook() {
0289: ProxoolFacade.shutdownHookEnabled = false;
0290: }
0291:
0292: /**
0293: * Call this if you change your mind about {@link #disableShutdownHook() disabling} it.
0294: * The default behaviour is to have it enabled so unless you have disabled it then
0295: * there's nothing to do.
0296: */
0297: public static void enableShutdownHook() {
0298: ProxoolFacade.shutdownHookEnabled = true;
0299: }
0300:
0301: /**
0302: * Whether the {@link ShutdownHook} should do anything.
0303: * @see #disableShutdownHook()
0304: * @see #enableShutdownHook()
0305: * @return true if the shutdown hook should clean up
0306: */
0307: public static boolean isShutdownHookEnabled() {
0308: return shutdownHookEnabled;
0309: }
0310:
0311: /**
0312: * Like {@link #removeConnectionPool(java.lang.String, int)} but uses no delay. (Kills
0313: * everything as quickly as possible).
0314: * @param alias to identify the pool
0315: * @throws ProxoolException if we couldn't find the pool
0316: */
0317: public static void removeConnectionPool(String alias)
0318: throws ProxoolException {
0319: removeConnectionPool(alias, 0);
0320: }
0321:
0322: /**
0323: * Get real-time statistical information about how a pool is performing.
0324: * @param alias to identify the pool
0325: * @return the statistics
0326: * @throws ProxoolException if we couldn't find the pool
0327: * @deprecated use {@link #getSnapshot}
0328: */
0329: public static ConnectionPoolStatisticsIF getConnectionPoolStatistics(
0330: String alias) throws ProxoolException {
0331: return ConnectionPoolManager.getInstance().getConnectionPool(
0332: alias);
0333: }
0334:
0335: /**
0336: * Get real-time statistical information about how a pool is performing.
0337: * and extract the information piece by piece.
0338: * @param alias to identify the pool
0339: * @return a horrible string describing the statistics
0340: * @throws ProxoolException if we couldn't find the pool
0341: * @deprecated use {@link #getSnapshot}
0342: */
0343: public static String getConnectionPoolStatisticsDump(String alias)
0344: throws ProxoolException {
0345: return ConnectionPoolManager.getInstance().getConnectionPool(
0346: alias).displayStatistics();
0347: }
0348:
0349: /**
0350: * Get the definition of a pool.
0351: * @param alias identifies the pool
0352: * @throws ProxoolException if we couldn't find the pool
0353: */
0354: public static ConnectionPoolDefinitionIF getConnectionPoolDefinition(
0355: String alias) throws ProxoolException {
0356: return ConnectionPoolManager.getInstance().getConnectionPool(
0357: alias).getDefinition();
0358: }
0359:
0360: /**
0361: * Get details on each connection within the pool. This can tell you which ones are active, how long they have
0362: * been active, etc.
0363: * @param alias identifies the pool
0364: * @return a collection of {@link ConnectionInfoIF ConnectionInfoIFs}
0365: * @throws ProxoolException if we couldn't find the pool
0366: * @deprecated use {@link #getSnapshot(java.lang.String, boolean) snapshot} instead.
0367: */
0368: public static Collection getConnectionInfos(String alias)
0369: throws ProxoolException {
0370: return ConnectionPoolManager.getInstance().getConnectionPool(
0371: alias).getConnectionInfos();
0372: }
0373:
0374: /**
0375: * Kill all connections in a pool. The pool continues to work however, and new connections will be
0376: * made as required.
0377: * @param alias the pool containing the connection
0378: * @param merciful if true will only kill connections that aren't active
0379: * @throws ProxoolException if we couldn't find the pool
0380: * @deprecated use {@link #killAllConnections(java.lang.String, java.lang.String, boolean) alternative}
0381: * to provide better auditing in log
0382: */
0383: public static void killAllConnections(String alias, boolean merciful)
0384: throws ProxoolException {
0385: killAllConnections(alias, "of thread "
0386: + Thread.currentThread().getName(), merciful);
0387: }
0388:
0389: /**
0390: * Kill all connections in a pool. The pool continues to work however, and new connections will be
0391: * made as required.
0392: * @param alias the pool containing the connection
0393: * @param reason provides audit in log of why connections were killed
0394: * @param merciful if true will only kill connections that aren't active
0395: * @throws ProxoolException if we couldn't find the pool
0396: */
0397: public static void killAllConnections(String alias, String reason,
0398: boolean merciful) throws ProxoolException {
0399: ConnectionPoolManager.getInstance().getConnectionPool(alias)
0400: .expireAllConnections(reason, merciful);
0401: }
0402:
0403: /**
0404: * Like {@link #killAllConnections} but defaults to merciful.
0405: * @param alias to identify the pool
0406: * @throws ProxoolException if we couldn't find the pool
0407: * @deprecated use {@link #killAllConnections(java.lang.String, java.lang.String) alternative}
0408: * to provide better auditing in log
0409: */
0410: public static void killAllConnections(String alias)
0411: throws ProxoolException {
0412: killAllConnections(alias, "of thread "
0413: + Thread.currentThread().getName(), MERCIFUL);
0414: }
0415:
0416: /**
0417: * Like {@link #killAllConnections} but defaults to merciful.
0418: * @param alias to identify the pool
0419: * @param reason provides audit in log of why connections were killed
0420: * @throws ProxoolException if we couldn't find the pool
0421: */
0422: public static void killAllConnections(String alias, String reason)
0423: throws ProxoolException {
0424: killAllConnections(alias, reason, MERCIFUL);
0425: }
0426:
0427: /**
0428: * Kill a single connection
0429: * @param alias the pool containing the connection
0430: * @param id the id of the specific connection
0431: * @param merciful if true will only kill connections that aren't active
0432: * @return true if the connection was killed, or false if it couldn't be found.
0433: * @throws ProxoolException if we couldn't find the pool
0434: */
0435: public static boolean killConnecton(String alias, long id,
0436: boolean merciful) throws ProxoolException {
0437: // Let's be explicit about what we're doing here
0438: boolean forceExpiry = !merciful;
0439: return ConnectionPoolManager.getInstance().getConnectionPool(
0440: alias).expireConnection(id, forceExpiry);
0441: }
0442:
0443: /**
0444: * Kill a single connection
0445: * @param connection the connection to kill
0446: * @param merciful if true will only kill connections that aren't active
0447: * @return true if the connection was killed, or false if it couldn't be found.
0448: * @throws ProxoolException if we didn't recognise the connection
0449: */
0450: public static boolean killConnecton(Connection connection,
0451: boolean merciful) throws ProxoolException {
0452: WrappedConnection wrappedConnection = ProxyFactory
0453: .getWrappedConnection(connection);
0454: if (wrappedConnection != null) {
0455: long id = wrappedConnection.getId();
0456: String alias = wrappedConnection.getAlias();
0457: return killConnecton(alias, id, merciful);
0458: } else {
0459: throw new ProxoolException(
0460: "Attempt to kill unrecognised exception "
0461: + connection);
0462: }
0463: }
0464:
0465: /**
0466: * Add a listener that gets called everytime a global Proxool event ocours.
0467: * @param proxoolListener the listener to add.
0468: */
0469: public static void addProxoolListener(
0470: ProxoolListenerIF proxoolListener) {
0471: compositeProxoolListener.addListener(proxoolListener);
0472: }
0473:
0474: /**
0475: * Remove a registered <code>ProxoolListenerIF</code>.
0476: * @param proxoolListener the listener to remove.
0477: * @return whether the listener was found or removed or not.
0478: */
0479: public static boolean removeProxoolListener(
0480: ProxoolListenerIF proxoolListener) {
0481: return compositeProxoolListener.removeListener(proxoolListener);
0482: }
0483:
0484: /**
0485: * @deprecated use {@link #addStateListener(String, StateListenerIF)} instead.
0486: */
0487: public static void setStateListener(String alias,
0488: StateListenerIF stateListener) throws ProxoolException {
0489: addStateListener(alias, stateListener);
0490: }
0491:
0492: /**
0493: * Add a listener that monitors the change of state of the pool (quiet, busy, overloaded, or down)
0494: * @param alias identifies the pool
0495: * @param stateListener the new listener
0496: * @throws ProxoolException if we couldn't find the pool
0497: */
0498: public static void addStateListener(String alias,
0499: StateListenerIF stateListener) throws ProxoolException {
0500: ConnectionPool cp = ConnectionPoolManager.getInstance()
0501: .getConnectionPool(alias);
0502: cp.addStateListener(stateListener);
0503: }
0504:
0505: /**
0506: * Remove a listener that monitors the change of state of the pool (quiet, busy, overloaded, or down)
0507: * @param alias identifies the pool
0508: * @param stateListener the listener to be removed.
0509: * @throws ProxoolException if we couldn't find the pool
0510: * @return wether the listnener was found and removed or not.
0511: */
0512: public boolean removeStateListener(String alias,
0513: StateListenerIF stateListener) throws ProxoolException {
0514: ConnectionPool cp = ConnectionPoolManager.getInstance()
0515: .getConnectionPool(alias);
0516: return cp.removeStateListener(stateListener);
0517: }
0518:
0519: /**
0520: * @deprecated use {@link #addConnectionListener(String, ConnectionListenerIF)} instead.
0521: */
0522: public static void setConnectionListener(String alias,
0523: ConnectionListenerIF connectionListener)
0524: throws ProxoolException {
0525: addConnectionListener(alias, connectionListener);
0526: }
0527:
0528: /**
0529: * Add a listener that monitors each time a connection is made or destroyed.
0530: * @param alias identifies the pool
0531: * @param connectionListener the new listener
0532: * @throws ProxoolException if we couldn't find the pool
0533: */
0534: public static void addConnectionListener(String alias,
0535: ConnectionListenerIF connectionListener)
0536: throws ProxoolException {
0537: ConnectionPool cp = ConnectionPoolManager.getInstance()
0538: .getConnectionPool(alias);
0539: cp.addConnectionListener(connectionListener);
0540: }
0541:
0542: /**
0543: * Remove a listener that monitors each time a connection is made or destroyed.
0544: * @param alias identifies the pool
0545: * @param connectionListener the listener to be removed
0546: * @throws ProxoolException if we couldn't find the pool
0547: * @return wether the listnener was found and removed or not.
0548: */
0549: public static boolean removeConnectionListener(String alias,
0550: ConnectionListenerIF connectionListener)
0551: throws ProxoolException {
0552: ConnectionPool cp = ConnectionPoolManager.getInstance()
0553: .getConnectionPool(alias);
0554: return cp.removeConnectionListener(connectionListener);
0555: }
0556:
0557: /**
0558: * @deprecated use {@link #addConfigurationListener(String, ConfigurationListenerIF)} instead.
0559: */
0560: public static void setConfigurationListener(String alias,
0561: ConfigurationListenerIF configurationListener)
0562: throws ProxoolException {
0563: addConfigurationListener(alias, configurationListener);
0564: }
0565:
0566: /**
0567: * Adds a listener that gets called everytime the configuration changes.
0568: * @param alias identifies the pool
0569: * @param configurationListener the new listener
0570: * @throws ProxoolException if we couldn't find the pool
0571: */
0572: public static void addConfigurationListener(String alias,
0573: ConfigurationListenerIF configurationListener)
0574: throws ProxoolException {
0575: if (ConnectionPoolManager.getInstance().isPoolExists(alias)) {
0576: CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) configurators
0577: .get(alias);
0578: if (compositeConfigurationListener == null) {
0579: compositeConfigurationListener = new CompositeConfigurationListener();
0580: configurators
0581: .put(alias, compositeConfigurationListener);
0582: }
0583: compositeConfigurationListener
0584: .addListener(configurationListener);
0585: } else {
0586: throw new ProxoolException(ConnectionPoolManager
0587: .getInstance().getKnownPools(alias));
0588: }
0589: }
0590:
0591: /**
0592: * Broadcast a configuration change
0593: * @param alias identifies the pool
0594: * @param connectionPoolDefinition the definition
0595: * @param completeInfo all properties
0596: * @param changedInfo only changed properties (since the last
0597: * time this method was called)
0598: */
0599: protected static void definitionUpdated(String alias,
0600: ConnectionPoolDefinitionIF connectionPoolDefinition,
0601: Properties completeInfo, Properties changedInfo) {
0602: CompositeConfigurationListener ccl = (CompositeConfigurationListener) configurators
0603: .get(alias);
0604: if (ccl != null) {
0605: ccl.definitionUpdated(connectionPoolDefinition,
0606: completeInfo, changedInfo);
0607: }
0608: }
0609:
0610: /**
0611: * Remove a listener that gets called everytime the configuration changes.
0612: * @param alias identifies the pool.
0613: * @param configurationListener the listener to be removed.
0614: * @throws ProxoolException if we couldn't find the pool
0615: * @return wether the listnener was found and removed or not.
0616: *
0617: */
0618: public static boolean removeConfigurationListener(String alias,
0619: ConfigurationListenerIF configurationListener)
0620: throws ProxoolException {
0621: boolean removed = false;
0622: if (ConnectionPoolManager.getInstance().isPoolExists(alias)) {
0623: CompositeConfigurationListener compositeConfigurationListener = (CompositeConfigurationListener) configurators
0624: .get(alias);
0625: if (compositeConfigurationListener != null) {
0626: removed = compositeConfigurationListener
0627: .removeListener(configurationListener);
0628: }
0629: } else {
0630: throw new ProxoolException(ConnectionPoolManager
0631: .getInstance().getKnownPools(alias));
0632: }
0633: return removed;
0634: }
0635:
0636: /**
0637: * @see #killAllConnections(java.lang.String)
0638: */
0639: private static final boolean MERCIFUL = true;
0640:
0641: /**
0642: * Redefine the behaviour of the pool. All existing properties (for Proxool
0643: * and the delegate driver are reset to their default) and reapplied
0644: * based on the parameters sent here.
0645: *
0646: * @param url the url that defines the pool (or the abbreviated ""proxool.alias")
0647: * @param info the new properties
0648: * @see #updateConnectionPool
0649: */
0650: public static void redefineConnectionPool(String url,
0651: Properties info) throws ProxoolException {
0652: String alias = getAlias(url);
0653: ConnectionPool cp = ConnectionPoolManager.getInstance()
0654: .getConnectionPool(alias);
0655: try {
0656: // Clone the old one
0657: ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp
0658: .getDefinition().clone();
0659: cpd.redefine(url, info);
0660: cp.setDefinition(cpd);
0661: } catch (CloneNotSupportedException e) {
0662: throw new ProxoolException(
0663: "Funny, why couldn't we clone a definition?", e);
0664: }
0665: }
0666:
0667: /**
0668: * Update the behaviour of the pool. Only properties that are defined here are overwritten. That is, properties
0669: * that were defined before but are not mentioned here are retained.
0670: *
0671: * @param url the url that defines the pool (or the abbreviated ""proxool.alias")
0672: * @param info the new properties
0673: * @see #redefineConnectionPool
0674: */
0675: public static void updateConnectionPool(String url, Properties info)
0676: throws ProxoolException {
0677: String alias = getAlias(url);
0678: ConnectionPool cp = ConnectionPoolManager.getInstance()
0679: .getConnectionPool(alias);
0680: try {
0681: // Clone the old one
0682: ConnectionPoolDefinition cpd = (ConnectionPoolDefinition) cp
0683: .getDefinition().clone();
0684: cpd.update(url, info);
0685: cp.setDefinition(cpd);
0686: } catch (CloneNotSupportedException e) {
0687: throw new ProxoolException(
0688: "Funny, why couldn't we clone a definition?", e);
0689: }
0690: }
0691:
0692: protected void finalize() throws Throwable {
0693: super .finalize();
0694: LOG.debug("Finalising");
0695: }
0696:
0697: /**
0698: * Returns the driver provided statement that Proxool wraps up before it gives it to you.
0699: * @return delegate statement
0700: * @deprecated Just cast the statement that you are given into the driver specific one.
0701: */
0702: public static Statement getDelegateStatement(Statement statement)
0703: throws ProxoolException {
0704: try {
0705: return ProxyFactory.getDelegateStatement(statement);
0706: } catch (IllegalArgumentException e) {
0707: throw new ProxoolException(
0708: "Statement argument is not one provided by Proxool (it's a "
0709: + statement.getClass() + ")");
0710: }
0711: }
0712:
0713: /**
0714: * Returns the driver provided connection that Proxool wraps up before it gives it to you.
0715: * @return delegate connection
0716: * @deprecated Just cast the connection that you are given into the driver specific one.
0717: */
0718: public static Connection getDelegateConnection(Connection connection)
0719: throws ProxoolException {
0720: try {
0721: return ProxyFactory.getDelegateConnection(connection);
0722: } catch (IllegalArgumentException e) {
0723: throw new ProxoolException(
0724: "Connection argument is not one provided by Proxool (it's a "
0725: + connection.getClass() + ")");
0726: }
0727: }
0728:
0729: /**
0730: * Get the connection ID for a connection
0731: * @param connection the connection that was served
0732: * @return the ID
0733: * @throws ProxoolException if the connection wasn't recognised.
0734: */
0735: public static long getId(Connection connection)
0736: throws ProxoolException {
0737: try {
0738: return ProxyFactory.getWrappedConnection(connection)
0739: .getId();
0740: } catch (NullPointerException e) {
0741: throw new ProxoolException(
0742: "Connection argument is not one provided by Proxool (it's a "
0743: + connection.getClass() + ")");
0744: } catch (IllegalArgumentException e) {
0745: throw new ProxoolException(
0746: "Connection argument is not one provided by Proxool (it's a "
0747: + connection.getClass() + ")");
0748: }
0749: }
0750:
0751: /**
0752: * Get the alias for the connection pool that served a connection
0753: * @param connection the connection that was served
0754: * @return the alias
0755: * @throws ProxoolException if the connection wasn't recognised.
0756: */
0757: public static String getAlias(Connection connection)
0758: throws ProxoolException {
0759: try {
0760: return ProxyFactory.getWrappedConnection(connection)
0761: .getAlias();
0762: } catch (NullPointerException e) {
0763: throw new ProxoolException(
0764: "Connection argument is not one provided by Proxool (it's a "
0765: + connection.getClass() + ")");
0766: } catch (IllegalArgumentException e) {
0767: throw new ProxoolException(
0768: "Connection argument is not one provided by Proxool (it's a "
0769: + connection.getClass() + ")");
0770: }
0771: }
0772:
0773: /**
0774: * Get a list of all the registered pools
0775: * @return an array of aliases
0776: * @since Proxool 0.7
0777: */
0778: public static String[] getAliases() {
0779: return ConnectionPoolManager.getInstance()
0780: .getConnectionPoolNames();
0781: }
0782:
0783: /**
0784: * Get a particular set of performance statistics for this pool
0785: * @param alias identifies the pool
0786: * @param token identifies which set, as defined in the configuration (see {@link ConnectionPoolDefinitionIF#getStatistics definition})
0787: * @return a sample containing the statistics
0788: * @throws ProxoolException if we couldn't find the pool
0789: */
0790: public static StatisticsIF getStatistics(String alias, String token)
0791: throws ProxoolException {
0792: return ConnectionPoolManager.getInstance().getConnectionPool(
0793: alias).getAdmin().getStatistics(token);
0794: }
0795:
0796: /**
0797: * Get all the lastest performance statistics for this pool
0798: * @param alias identifies the pool
0799: * @return a sample containing the statistics, or a zero length array if there none
0800: * @throws ProxoolException if we couldn't find the pool
0801: */
0802: public static StatisticsIF[] getStatistics(String alias)
0803: throws ProxoolException {
0804: final Admin monitor = ConnectionPoolManager.getInstance()
0805: .getConnectionPool(alias).getAdmin();
0806: if (monitor != null) {
0807: return monitor.getStatistics();
0808: } else {
0809: return new StatisticsIF[0];
0810: }
0811: }
0812:
0813: /**
0814: * Add a listener that receives statistics as they are produced
0815: * @param statisticsListener the new listener
0816: * @throws ProxoolException if the pool couldn't be found
0817: */
0818: public static void addStatisticsListener(String alias,
0819: StatisticsListenerIF statisticsListener)
0820: throws ProxoolException {
0821: // TODO investigate what happens if we add a statistics monitor after we register a listener
0822: final Admin monitor = ConnectionPoolManager.getInstance()
0823: .getConnectionPool(alias).getAdmin();
0824: if (monitor != null) {
0825: monitor.addStatisticsListener(statisticsListener);
0826: } else {
0827: throw new ProxoolException(
0828: "Statistics are switched off, your can't add a listener");
0829: }
0830: }
0831:
0832: /**
0833: * Gives a snapshot of what the pool is doing
0834: * @param alias identifies the pool
0835: * @param detail if true then include detail of each connection. Note it you ask for
0836: * detail then the pool must necessarily be locked for the duration it takes to gather
0837: * the information (which isn't very long). You probably shouldn't do it that often (like
0838: * not every second or something). Being locked means that connections cannot be
0839: * served or returned (it doesn't mean that they can't be active).
0840: * @return the current status of the pool
0841: * @throws ProxoolException if we couldn't find the pool
0842: */
0843: public static SnapshotIF getSnapshot(String alias, boolean detail)
0844: throws ProxoolException {
0845: SnapshotIF snapshot = null;
0846: ConnectionPool cp = ConnectionPoolManager.getInstance()
0847: .getConnectionPool(alias);
0848:
0849: if (detail) {
0850: try {
0851: // Only try for 10 seconds!
0852: long start = System.currentTimeMillis();
0853: if (cp.attemptConnectionStatusReadLock(10000)) {
0854: snapshot = Admin
0855: .getSnapshot(cp, cp.getDefinition(), cp
0856: .getConnectionInfos());
0857: } else {
0858: LOG
0859: .warn("Give up waiting for detailed snapshot after "
0860: + (System.currentTimeMillis() - start)
0861: + " milliseconds. Serving standard snapshot instead.");
0862: }
0863: } finally {
0864: cp.releaseConnectionStatusReadLock();
0865: }
0866: }
0867: if (snapshot == null) {
0868: snapshot = Admin.getSnapshot(cp, cp.getDefinition(), null);
0869: }
0870:
0871: return snapshot;
0872: }
0873:
0874: /**
0875: * Calls {@link #getSnapshot(java.lang.String, boolean) getSnapshot}
0876: * using false for the detail parameter.
0877: * @see #getSnapshot(java.lang.String, boolean)
0878: */
0879: public static SnapshotIF getSnapshot(String alias)
0880: throws ProxoolException {
0881: return getSnapshot(alias, false);
0882: }
0883:
0884: // all jmx operations are done through reflection
0885: // to avoid making the facade dependant on the JMX classes
0886: private static boolean registerForJmx(String alias,
0887: Properties properties) {
0888: boolean success = false;
0889: try {
0890: Class jmxHelperClass = Class
0891: .forName("org.logicalcobwebs.proxool.admin.jmx.ProxoolJMXHelper");
0892: Method registerMethod = jmxHelperClass.getDeclaredMethod(
0893: "registerPool", new Class[] { String.class,
0894: Properties.class });
0895: registerMethod.invoke(null, new Object[] { alias,
0896: properties });
0897: success = true;
0898: } catch (Exception e) {
0899: LOG.error("JMX registration of " + alias + " pool failed.",
0900: e);
0901: }
0902: return success;
0903: }
0904:
0905: // all JNDI operations are done through reflection
0906: // to avoid making the facade dependant on the JNDI classes
0907: private static boolean registerDataSource(String alias,
0908: Properties jndiProperties) {
0909: boolean success = false;
0910: try {
0911: Class jndiHelperClass = Class
0912: .forName("org.logicalcobwebs.proxool.admin.jndi.ProxoolJNDIHelper");
0913: Method registerMethod = jndiHelperClass.getDeclaredMethod(
0914: "registerDatasource", new Class[] { String.class,
0915: Properties.class });
0916: registerMethod.invoke(null, new Object[] { alias,
0917: jndiProperties });
0918: success = true;
0919: } catch (Exception e) {
0920: LOG.error("JNDI DataSource binding of " + alias
0921: + " pool failed.", e);
0922: }
0923: return success;
0924: }
0925:
0926: /**
0927: * Get the JNDI properties for the given pool definition if it is configured for JNDI registration.
0928: * Will remove generic JNDI properties from the delegate properties so that they will not be passed to the
0929: * delegate driver.
0930: * @param connectionPoolDefinition the pool definition to get the eventual JNDI configuration from.
0931: * @return the JNDI properties, or <code>null</code> if the given definition was not configured for JNDI.
0932: */
0933: private static Properties extractJndiProperties(
0934: ConnectionPoolDefinition connectionPoolDefinition) {
0935: if (connectionPoolDefinition.getJndiName() == null) {
0936: return null;
0937: }
0938: Properties jndiProperties = new Properties();
0939: jndiProperties.setProperty(ProxoolConstants.JNDI_NAME,
0940: connectionPoolDefinition.getJndiName());
0941: if (connectionPoolDefinition.getDelegateProperties() != null) {
0942: Properties delegateProperties = connectionPoolDefinition
0943: .getDelegateProperties();
0944: // we must retrieve all the relevant property names before removing them from
0945: // the given properties to avoid ConcurrentModificationException
0946: String propertyName = null;
0947: List propertyNamesList = new ArrayList(10);
0948: Iterator keySetIterator = delegateProperties.keySet()
0949: .iterator();
0950: while (keySetIterator.hasNext()) {
0951: propertyName = (String) keySetIterator.next();
0952: if (propertyName
0953: .startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) {
0954: propertyNamesList.add(propertyName);
0955: }
0956: }
0957: for (int i = 0; i < propertyNamesList.size(); i++) {
0958: propertyName = (String) propertyNamesList.get(i);
0959: if (propertyName
0960: .startsWith(ProxoolConstants.JNDI_PROPERTY_PREFIX)) {
0961: jndiProperties
0962: .setProperty(
0963: propertyName
0964: .substring(ProxoolConstants.JNDI_PROPERTY_PREFIX
0965: .length()),
0966: (String) delegateProperties
0967: .getProperty(propertyName));
0968: delegateProperties.remove(propertyName);
0969: }
0970: }
0971: }
0972: return jndiProperties;
0973: }
0974:
0975: /**
0976: * Get wether the given pool properties contains configuration for JMX instrumentation of the pool.
0977: * @param poolProperties the properties to check for JMX configuration.
0978: * @return wether the given pool properties contains configuration for JMX instrumentation or not.
0979: */
0980: private static boolean isConfiguredForJMX(Properties poolProperties) {
0981: final String jmxProperty = poolProperties
0982: .getProperty(ProxoolConstants.JMX_PROPERTY);
0983: if (jmxProperty != null && jmxProperty.equalsIgnoreCase("true")) {
0984: return true;
0985: } else {
0986: return false;
0987: }
0988: }
0989:
0990: /**
0991: * By remembering the most recent {@link ShutdownHook} ProxoolFacade
0992: * will know to disable it when it is {@link #shutdown}. It will gracefully
0993: * cope with the fact that it may be shutting down by the request of the
0994: * sutdownHook. If you don't do this and do several "hot deploys" then you
0995: * end up with a series of shutdown hooks. We only every want one.
0996: * @param t the thread that will be run as a shutdown hook
0997: * @see ShutdownHook
0998: */
0999: protected static void setShutdownHook(Thread t) {
1000: shutdownHook = t;
1001: }
1002: }
1003:
1004: /*
1005: Revision history:
1006: $Log: ProxoolFacade.java,v $
1007: Revision 1.85 2006/11/02 10:00:34 billhorsman
1008: Added ProxoolFacade.disableShutdownHook.
1009:
1010: Revision 1.84 2006/01/18 14:40:01 billhorsman
1011: Unbundled Jakarta's Commons Logging.
1012:
1013: Revision 1.83 2005/09/26 09:54:14 billhorsman
1014: Avoid suspected deadlock when getting a detailed snapshot. Only attempt to get the concurrent lock for 10 seconds before giving up.
1015:
1016: Revision 1.82 2005/05/04 16:32:31 billhorsman
1017: Clone the definition when redefining or updating the pool.
1018:
1019: Revision 1.81 2004/09/29 15:43:25 billhorsman
1020: Recheck isPoolExists inside synchronized registerConnectionPool method. Credit Juergen Hoeller.
1021:
1022: Revision 1.80 2004/06/02 20:47:05 billhorsman
1023: Override shutdown with a zero-parameter version for Spring integration.
1024:
1025: Revision 1.79 2004/03/26 15:58:56 billhorsman
1026: Fixes to ensure that house keeper and prototyper threads finish after shutdown.
1027:
1028: Revision 1.78 2004/03/23 21:25:54 billhorsman
1029: Added getAlias() call.
1030:
1031: Revision 1.77 2004/03/23 21:19:45 billhorsman
1032: Added disposable wrapper to proxied connection. And made proxied objects implement delegate interfaces too.
1033:
1034: Revision 1.76 2004/03/15 02:45:19 chr32
1035: Added handling of Proxool managed JNDI DataSources.
1036:
1037: Revision 1.75 2004/02/12 12:54:49 billhorsman
1038: Fix merciful/forceExpiry confusion
1039:
1040: Revision 1.74 2003/10/30 00:16:13 billhorsman
1041: Throw a friendlier exception if you try and add a statistics listener to a pool with no statistics
1042:
1043: Revision 1.73 2003/10/16 18:52:35 billhorsman
1044: Fixed a bug: the redefine() method was actually calling the update() method. Also, added checks to make the
1045: "Attempt to use a pool with incomplete definition" exception a bit more descriptive. It's often because you
1046: are referring to an unregistered pool simply by using an alias.
1047:
1048: Revision 1.72 2003/09/07 22:09:21 billhorsman
1049: Remove any registered ShutdownHooks during shutdown.
1050:
1051: Revision 1.71 2003/08/30 14:54:04 billhorsman
1052: Checkstyle
1053:
1054: Revision 1.70 2003/08/28 10:55:49 billhorsman
1055: comment out JNDI stuff for now
1056:
1057: Revision 1.69 2003/08/27 18:03:20 billhorsman
1058: added new getDelegateConnection() method
1059:
1060: Revision 1.68 2003/07/23 12:38:50 billhorsman
1061: some fixes, but more to come
1062:
1063: Revision 1.67 2003/07/23 06:54:48 billhorsman
1064: draft JNDI changes (shouldn't effect normal operation)
1065:
1066: Revision 1.66 2003/04/10 21:49:34 billhorsman
1067: refactored registration slightly to allow DataSource access
1068:
1069: Revision 1.65 2003/03/11 14:51:53 billhorsman
1070: more concurrency fixes relating to snapshots
1071:
1072: Revision 1.64 2003/03/10 15:26:49 billhorsman
1073: refactoringn of concurrency stuff (and some import
1074: optimisation)
1075:
1076: Revision 1.63 2003/03/03 11:11:58 billhorsman
1077: fixed licence
1078:
1079: Revision 1.62 2003/02/28 10:42:59 billhorsman
1080: ConnectionPoolManager now passes ProxoolFacade an
1081: array of ConnectionPools rather than a Collection
1082: to avoid a ConcurrentModificationException during
1083: shutdown.
1084:
1085: Revision 1.61 2003/02/27 17:19:18 billhorsman
1086: new overloaded getSnapshot method
1087:
1088: Revision 1.60 2003/02/26 16:05:53 billhorsman
1089: widespread changes caused by refactoring the way we
1090: update and redefine pool definitions.
1091:
1092: Revision 1.59 2003/02/24 18:03:24 chr32
1093: Added JMX operations.
1094:
1095: Revision 1.58 2003/02/24 01:15:33 chr32
1096: Added support for ProxoolListenerIF.
1097:
1098: Revision 1.57 2003/02/19 23:46:10 billhorsman
1099: renamed monitor package to admin
1100:
1101: Revision 1.56 2003/02/19 13:48:28 chr32
1102: Added 'removeConfigurationListener' method.
1103:
1104: Revision 1.55 2003/02/18 16:50:00 chr32
1105: Added possibility to remove connection and state listeners.
1106:
1107: Revision 1.54 2003/02/14 14:19:42 billhorsman
1108: automatically load ProxoolDriver
1109:
1110: Revision 1.53 2003/02/14 13:26:23 billhorsman
1111: better exception for incorrect url
1112:
1113: Revision 1.52 2003/02/12 12:28:27 billhorsman
1114: added url, proxyHashcode and delegateHashcode to
1115: ConnectionInfoIF
1116:
1117: Revision 1.51 2003/02/07 17:26:05 billhorsman
1118: deprecated removeAllConnectionPools in favour of
1119: shutdown (and dropped unreliable finalize() method)
1120:
1121: Revision 1.50 2003/02/07 15:12:41 billhorsman
1122: fix statisticsLogLevel property recognition again
1123:
1124: Revision 1.49 2003/02/07 14:45:40 billhorsman
1125: fix statisticsLogLevel property recognition
1126:
1127: Revision 1.48 2003/02/07 14:16:46 billhorsman
1128: support for StatisticsListenerIF
1129:
1130: Revision 1.47 2003/02/07 10:27:47 billhorsman
1131: change in shutdown procedure to allow re-registration
1132:
1133: Revision 1.46 2003/02/07 01:48:15 chr32
1134: Started using new composite listeners.
1135:
1136: Revision 1.45 2003/02/06 17:41:04 billhorsman
1137: now uses imported logging
1138:
1139: Revision 1.44 2003/02/06 15:46:43 billhorsman
1140: checkstyle
1141:
1142: Revision 1.43 2003/02/06 15:41:16 billhorsman
1143: add statistics-log-level
1144:
1145: Revision 1.42 2003/02/05 17:05:02 billhorsman
1146: registerConnectionPool is now synchronized
1147:
1148: Revision 1.41 2003/02/05 00:20:01 billhorsman
1149: copes with pools with no statistics
1150:
1151: Revision 1.40 2003/02/04 17:18:29 billhorsman
1152: move ShutdownHook init code
1153:
1154: Revision 1.39 2003/02/04 15:04:17 billhorsman
1155: New ShutdownHook
1156:
1157: Revision 1.38 2003/01/31 16:53:17 billhorsman
1158: checkstyle
1159:
1160: Revision 1.37 2003/01/31 11:50:39 billhorsman
1161: changes for snapshot improvements
1162:
1163: Revision 1.36 2003/01/31 00:18:27 billhorsman
1164: statistics is now a string to allow multiple,
1165: comma-delimited values (plus allow access to all
1166: statistics)
1167:
1168: Revision 1.35 2003/01/30 17:50:28 billhorsman
1169: spelling
1170:
1171: Revision 1.34 2003/01/30 17:48:50 billhorsman
1172: configuration listener now linked to alias not url
1173:
1174: Revision 1.33 2003/01/30 17:22:23 billhorsman
1175: add statistics support
1176:
1177: Revision 1.32 2003/01/27 18:26:36 billhorsman
1178: refactoring of ProxyConnection and ProxyStatement to
1179: make it easier to write JDK 1.2 patch
1180:
1181: Revision 1.31 2003/01/23 11:08:26 billhorsman
1182: new setConfiguratorListener method (and remove from optional
1183: parameter when registering pool)
1184:
1185: Revision 1.30 2003/01/19 15:21:07 billhorsman
1186: doc
1187:
1188: Revision 1.29 2003/01/18 15:13:12 billhorsman
1189: Signature changes (new ProxoolException
1190: thrown) on the ProxoolFacade API.
1191:
1192: Revision 1.28 2003/01/17 00:38:12 billhorsman
1193: wide ranging changes to clarify use of alias and url -
1194: this has led to some signature changes (new exceptions
1195: thrown) on the ProxoolFacade API.
1196:
1197: Revision 1.27 2003/01/15 14:51:40 billhorsman
1198: checkstyle
1199:
1200: Revision 1.26 2003/01/15 12:20:06 billhorsman
1201: deprecated getConnectionPoolStatisticsDump
1202:
1203: Revision 1.25 2003/01/14 23:50:58 billhorsman
1204: logs version
1205:
1206: Revision 1.24 2002/12/16 17:15:03 billhorsman
1207: fix for url
1208:
1209: Revision 1.23 2002/12/16 16:47:22 billhorsman
1210: fix for updating properties with zero length strings
1211:
1212: Revision 1.22 2002/12/16 16:42:30 billhorsman
1213: allow URL updates to pool
1214:
1215: Revision 1.21 2002/12/16 11:46:00 billhorsman
1216: send properties to definitionUpdated
1217:
1218: Revision 1.20 2002/12/16 11:16:51 billhorsman
1219: checkstyle
1220:
1221: Revision 1.19 2002/12/16 11:15:19 billhorsman
1222: fixed getDelegateStatement
1223:
1224: Revision 1.18 2002/12/16 10:57:48 billhorsman
1225: add getDelegateStatement to allow access to the
1226: delegate JDBC driver's Statement
1227:
1228: Revision 1.17 2002/12/12 10:49:43 billhorsman
1229: now includes properties in definitionChanged event
1230:
1231: Revision 1.16 2002/12/04 13:19:43 billhorsman
1232: draft ConfigurationListenerIF stuff for persistent configuration
1233:
1234: Revision 1.15 2002/11/13 19:12:24 billhorsman
1235: fix where update properties weren't being recognised
1236: when the properties object was the same as the original
1237:
1238: Revision 1.14 2002/11/13 11:28:38 billhorsman
1239: trace property wasn't being configured
1240:
1241: Revision 1.13 2002/11/09 15:56:31 billhorsman
1242: log if serConnectionListener couldn't find pool
1243:
1244: Revision 1.12 2002/11/03 10:46:57 billhorsman
1245: hide passwords in log
1246:
1247: Revision 1.11 2002/11/02 13:57:33 billhorsman
1248: checkstyle
1249:
1250: Revision 1.10 2002/10/29 08:54:45 billhorsman
1251: fix to getAlias so that it correctly extracts alias from "proxool.alias" form
1252:
1253: Revision 1.9 2002/10/28 19:43:30 billhorsman
1254: configuring of pool now gets logged to that pool's logger (rather than general log)
1255:
1256: Revision 1.8 2002/10/27 13:29:38 billhorsman
1257: deprecated debug-level in favour of verbose
1258:
1259: Revision 1.7 2002/10/27 13:01:23 billhorsman
1260: layout
1261:
1262: Revision 1.6 2002/10/25 15:59:32 billhorsman
1263: made non-public where possible
1264:
1265: Revision 1.5 2002/10/25 10:12:52 billhorsman
1266: Improvements and fixes to the way connection pools close down. Including new ReloadMonitor to detect when a class is reloaded. Much better logging too.
1267:
1268: Revision 1.4 2002/10/24 17:40:31 billhorsman
1269: Fixed recognition of existing pool (which was resulting in an extra configuration step - but which didn't cause any problems)
1270:
1271: Revision 1.3 2002/10/23 21:04:36 billhorsman
1272: checkstyle fixes (reduced max line width and lenient naming convention
1273:
1274: Revision 1.2 2002/10/17 15:27:31 billhorsman
1275: better reporting of property settings
1276:
1277: Revision 1.1.1.1 2002/09/13 08:13:19 billhorsman
1278: new
1279:
1280: Revision 1.11 2002/08/24 20:07:28 billhorsman
1281: removed debug to stdout
1282:
1283: Revision 1.10 2002/08/24 19:44:13 billhorsman
1284: fixes for logging
1285:
1286: Revision 1.9 2002/07/10 16:14:47 billhorsman
1287: widespread layout changes and move constants into ProxoolConstants
1288:
1289: Revision 1.8 2002/07/05 13:24:32 billhorsman
1290: doc
1291:
1292: Revision 1.7 2002/07/04 09:04:20 billhorsman
1293: Now throws an SQLException if you ask for a ConnectionPoolDefinition, ConnectionPoolStatistics that doesn't exist. This makes it easier to show the list of possible ones you can choose.
1294:
1295: Revision 1.6 2002/07/02 11:19:08 billhorsman
1296: layout code and imports
1297:
1298: Revision 1.5 2002/07/02 11:14:26 billhorsman
1299: added test (andbug fixes) for FileLogger
1300:
1301: Revision 1.4 2002/07/02 09:13:08 billhorsman
1302: removed redundant import
1303:
1304: Revision 1.3 2002/07/02 08:52:42 billhorsman
1305: Added lots more methods and moved configuration stuff here
1306:
1307: Revision 1.2 2002/06/28 11:19:47 billhorsman
1308: improved doc
1309:
1310: */
|