KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > snaq > db > ConnectionPoolManager


1 /*
2     DBPool - JDBC Connection Pool Manager
3     Copyright (c) Giles Winstanley
4 */

5 package snaq.db;
6
7 import java.io.*;
8 import java.sql.*;
9 import java.text.*;
10 import java.util.*;
11 import snaq.util.LogUtil;
12
13 /**
14  * <p>Class to provide access and management for multiple connection pools
15  * defined in a properties file or object.
16  * Clients get access to each defined instance through one of the
17  * static <tt>getInstance()</tt> methods and can then check-out and check-in
18  * database connections from the pools defined by that manager.</p>
19  *
20  * <p>Each successful call to a <tt>getInstance()</tt> method also increments
21  * an internal counter which keeps a record of the number of clients which hold
22  * a reference to that particular pool manager. When each client has finished
23  * using a pool manager it should call the <tt>release()</tt> method to
24  * let the manager know that it is no longer needed by that client, so it can
25  * clean up it's resources as necessary. The resources will not be released
26  * until the clients counter has reached zero. <em>It is therefore necessary to
27  * allocate and release your pool manager references carefully</em>.</p>
28  *
29  * <p>Properties for a manager can be specified in three different ways.
30  * <ol>
31  * <li>Properties file located in CLASSPATH
32  * <li>Properties file referenced explicitly (with a File object)
33  * <li>Properties object
34  * </ol>
35  *
36  * <ol>
37  * <li>A CLASSPATH located properties file can simply be accessed using the
38  * method <tt>getInstance(name)</tt> where <em>name</em> is the name of the
39  * properties file specified as a string.
40  * <li>To specify a properties file which is not in the CLASSPATH use the
41  * method <tt>getInstance(File)</tt>. This same file handle must be used
42  * each time you want to obtain the instance in this way.
43  * <li>To specify the pools using a Properties object a call must be made to
44  * the <tt>createInstance(Properties)</tt> method. This method creates the
45  * ConnectionPoolManager instance and makes it available via the <tt>getInstance()</tt>
46  * method.
47  * </ol>
48  * <p><b>Note:</b> The <tt>getInstance()</tt> method can return one of two
49  * possible instances depending on the previous calls made to the pool manager.
50  * If the <tt>createInstance(Properties)</tt> method has previously been
51  * called successfully then it will return this manually created instance.
52  * Otherwise it will attempt to return an instance relating to the default
53  * properties file (dbpool.properties) within the CLASSPATH, if it exists.</p>
54  *
55  * <p>The properties given to the manager specify which JDBC drivers to use to
56  * access the relevant databases, and also defines the characteristics of each
57  * connection pool. The properties required/allowed are as follows
58  * (those marked with * are mandatory):</p>
59  * <pre>
60  * drivers* Class names of required JDBC Drivers (comma/space delimited)
61  * logfile* Filename of logfile
62  *
63  * &lt;poolname&gt;.url* The JDBC URL for the database
64  * &lt;poolname&gt;.user Database username for login
65  * &lt;poolname&gt;.password Database password for login
66  * &lt;poolname&gt;.maxpool The maximum number of pooled connections (0 if none)
67  * &lt;poolname&gt;.maxconn The maximum number of possible connections (0 if no limit)
68  * &lt;poolname&gt;.expiry The connection expiry time in seconds (0 if no expiry)
69  * &lt;poolname&gt;.init The initial number of connections to create (default:0)
70  * &lt;poolname&gt;.validator Class name of connection validator (optional)
71  * &lt;poolname&gt;.decoder Class name of password decoder (optional)
72  * &lt;poolname&gt;.cache Whether to cache Statements (optional, default:true)
73  * &lt;poolname&gt;.debug Whether to log debug info (optional, default:false)
74  * &lt;poolname&gt;.prop.<em>XXX</em> Passes property <em>XXX</em> and it's value to the JDBC driver
75  * &lt;poolname&gt;.async Whether to use asynchronous connection destruction (optional, default:false)
76  * &lt;poolname&gt;.logfile Filename of logfile for this pool (optional)
77  * &lt;poolname&gt;.dateformat SimpleDateFormat formatting string for log entries (optional)
78  * </pre>
79  *
80  * <p>Multiple pools can be specified provided they each use a different pool name.
81  * The <tt>validator</tt> property optionally specifies the name of a
82  * class to be used for validating the database connections. The default
83  * connection validation simply performs a test using <tt>Connection.isClosed()</tt>.
84  * This test is not 100% reliable as the Java API documentation specifies that
85  * it only returns true if the connection has been explicitly closed.
86  * If more rigorous connection validation is required you can either use the
87  * provided class <tt>snaq.db.AutoCommitValidator</tt> or write your own
88  * validation class which should implement the <tt>ConnectionValidator</tt>
89  * interface.</p>
90  *
91  * @see snaq.db.AutoCommitValidator
92  * @see snaq.db.ConnectionValidator
93  * @author Giles Winstanley
94  */

95 public final class ConnectionPoolManager extends LogUtil implements Comparable JavaDoc
96 {
97     private static final String JavaDoc PROPERTIES_INSTANCE_KEY = "PROPERTIES_INSTANCE";
98     private static final String JavaDoc DEFAULT_PROPERTIES_FILE = "/dbpool.properties";
99     private static Hashtable managers = new Hashtable();
100
101     private static ArrayList drivers = new ArrayList();
102     private boolean released = false;
103     private HashMap pools = new HashMap();
104     protected int clients;
105     private Object JavaDoc source, key;
106
107
108     private ConnectionPoolManager(Properties props, Object JavaDoc src)
109     {
110         super();
111         this.source = src;
112         init(props);
113     }
114
115     /** Returns a descriptive string for this instance. */
116     public String JavaDoc toString()
117     {
118         if (source instanceof String JavaDoc)
119             return "ConnectionPoolManager [CLASSPATH resource:" + source + "]";
120         else if (source instanceof File)
121             return "ConnectionPoolManager [File:" + ((File)source).getAbsolutePath() + "]";
122         else if (source instanceof Properties)
123             return "ConnectionPoolManager [Properties]";
124         else
125             return "ConnectionPoolManager [Unknown]";
126     }
127
128     /** Compares this instances to other instances by name. */
129     public int compareTo(Object JavaDoc o) { return this.toString().compareTo(((ConnectionPoolManager)o).toString()); }
130
131     /**
132      * Returns an enumeration of all the available ConnectionPoolManager instances.
133      * This method is included for convenience for external monitoring.
134      * Clients wanting to obtain an instance for using connections should NOT use
135      * this method.
136      * @deprecated Replaced by <tt>getInstances()</tt>, which returns a <tt>Set</tt>
137      */

138     public static Enumeration instances() { return Collections.enumeration(getInstances()); }
139
140     /**
141      * Returns a Set containing all the current ConnectionPoolManager instances.
142      * This method is included for convenience for external monitoring.
143      * Clients wanting to obtain an instance for using connections should NOT use
144      * this method.
145      * @return all current instances of ConnectionPoolManager.
146      */

147     public static Set getInstances()
148     {
149         Set x = new HashSet();
150         x.addAll(managers.values());
151         return x;
152     }
153
154     /**
155      * Returns the singleton instance of the ConnectionPoolManager for the specified properties file.
156      * @param propsFile filename of the properties file to use (path info should not be specified; available CLASSPATH will be searched for the properties file)
157      * @return instance of ConnectionPoolManager relating to the specified properties file
158      * @throws IOException if there was an problem loading the properties
159      */

160     public static synchronized ConnectionPoolManager getInstance(String JavaDoc propsFile) throws IOException
161     {
162         String JavaDoc s = propsFile.startsWith("/") ? propsFile : ("/" + propsFile);
163         Object JavaDoc o = managers.get(s);
164         ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager)o : null;
165         if (cpm == null || cpm.isReleased())
166         {
167             cpm = new ConnectionPoolManager(loadProperties(s), propsFile);
168             cpm.key = s;
169             managers.put(cpm.key, cpm);
170         }
171         cpm.clients++;
172         return cpm;
173     }
174
175     /**
176      * Returns the singleton instance of the ConnectionPoolManager for the specified properties file.
177      * @param propsFile filename of the properties file to use (path info should not be specified; available CLASSPATH will be searched for the properties file)
178      * @return instance of ConnectionPoolManager relating to the specified properties file
179      * @throws IOException if there was an problem loading the properties
180      */

181     public static synchronized ConnectionPoolManager getInstance(File propsFile) throws IOException
182     {
183         Object JavaDoc o = managers.get(propsFile);
184         ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager)o : null;
185         if (cpm == null || cpm.isReleased())
186         {
187             try
188             {
189                 cpm = new ConnectionPoolManager(loadProperties(propsFile), propsFile);
190                 cpm.key = propsFile;
191                 managers.put(cpm.key, cpm);
192             }
193             catch (IOException ioe)
194             {
195                 if (ioe instanceof FileNotFoundException)
196                     System.err.println("Unable to find the properties file " + propsFile.getAbsolutePath());
197                 else
198                     System.err.println("Error loading the properties file " + propsFile.getAbsolutePath());
199                 ioe.printStackTrace();
200                 return null;
201             }
202         }
203         cpm.clients++;
204         return cpm;
205     }
206
207     /**
208      * Returns the standard singleton instance of the ConnectionPoolManager.
209      * If an instance has been obtained with a user-specified Properties object
210      * then this instance is returned, otherwise an attempt is made to return an
211      * instance using the default properties file (dbpool.properties).
212      * @throws IOException if there was an problem loading the properties
213      */

214     public static synchronized ConnectionPoolManager getInstance() throws IOException
215     {
216         Object JavaDoc o = managers.get(PROPERTIES_INSTANCE_KEY);
217         ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager)o : null;
218         if (cpm != null && !cpm.released)
219             cpm.clients++;
220         else
221             cpm = getInstance(DEFAULT_PROPERTIES_FILE);
222
223         return cpm;
224     }
225
226     /**
227      * Creates a singleton instance of the ConnectionPoolManager for the specified
228      * Properties object. To subsequently use this instance user's should call the
229      * getInstance() method. This mechanism is used to provide the maximum
230      * separation between creation and use of this instance to avoid haphazard
231      * changes to any referenced Properties onject that may occur between calls.
232      * (This method can only be used successfully if no default properties
233      * instance exists and is in use at the time of calling.)
234      * @param props Properties object to use
235      * @throws RuntimeException if default properties instance already exists and is in use
236      */

237     public static synchronized void createInstance(Properties props)
238     {
239         // Check for presence of default properties file instance
240
Object JavaDoc o = managers.get(DEFAULT_PROPERTIES_FILE);
241         ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager)o : null;
242         if (cpm != null && !cpm.isReleased())
243             throw new RuntimeException JavaDoc("Default properties file instance already exists");
244
245         // Create new instance and store reference
246
cpm = new ConnectionPoolManager(props, props);
247         cpm.key = PROPERTIES_INSTANCE_KEY;
248         managers.put(cpm.key, cpm);
249     }
250
251     /**
252      * Loads and returns a Properties object from file.
253      */

254     private static Properties loadProperties(File propsFile) throws IOException
255     {
256         if (!propsFile.exists())
257             throw new FileNotFoundException(propsFile.getAbsolutePath() + " does not exist");
258         if (propsFile.isDirectory())
259             throw new IOException("Error accessing properties file - " + propsFile.getAbsolutePath() + " is a directory");
260         InputStream is = new FileInputStream(propsFile);
261         Properties props = new Properties();
262         props.load(is);
263         is.close();
264         return props;
265     }
266
267     /**
268      * Loads and returns a Properties object from the resource specified..
269      * The resource should be located in the current CLASSPATH to be found.
270      * @throws IOException if there was an problem loading the properties
271      */

272     private static Properties loadProperties(String JavaDoc propsResource) throws IOException
273     {
274         InputStream is = ConnectionPoolManager.class.getResourceAsStream(propsResource);
275         Properties props = new Properties();
276         try
277         {
278             props.load(is);
279         }
280         catch (IOException ioe)
281         {
282             System.err.println("Unable to load the properties file. Make sure " + propsResource + " is in the CLASSPATH.");
283             ioe.printStackTrace();
284             throw ioe;
285         }
286         return props;
287     }
288
289     /**
290      * Initializes this instance with values from the given Properties object.
291      */

292     private void init(Properties props)
293     {
294         String JavaDoc logFile = props.getProperty("logfile", "ConnectionPoolManager.log");
295         String JavaDoc df = props.getProperty("dateformat", "EEE MMM dd hh:mm:ss.SSS ZZZ yyyy");
296         try
297         {
298             setDateFormat(new SimpleDateFormat(df));
299             setLog(new FileOutputStream(logFile, true));
300         }
301         catch (IOException e)
302         {
303             System.err.println("Can't open the log file: " + logFile);
304         }
305         loadDrivers(props);
306         createPools(props);
307     }
308
309     /**
310      * Loads and registers all JDBC drivers. This is done by the
311      * DBConnectionManager, as opposed to the ConnectionPool,
312      * since many pools may share the same driver.
313      * @param props the connection pool properties
314      */

315     private void loadDrivers(Properties props)
316     {
317         String JavaDoc driverClasses = props.getProperty("drivers");
318         StringTokenizer st = new StringTokenizer(driverClasses, ",: \t\n\r\f");
319         Enumeration current = DriverManager.getDrivers();
320         while (st.hasMoreElements())
321         {
322             String JavaDoc driverClassName = st.nextToken().trim();
323             try
324             {
325                 // Check if driver already registered
326
boolean using = false;
327                 while (current.hasMoreElements())
328                 {
329                     String JavaDoc cName = current.nextElement().getClass().getName();
330                     if (cName.equals(driverClassName))
331                         using = true;
332                 }
333                 if (!using)
334                 {
335                     Driver driver = (Driver)Class.forName(driverClassName).newInstance();
336                     DriverManager.registerDriver(driver);
337                     drivers.add(driver);
338                     log("Registered JDBC driver " + driverClassName);
339                 }
340             }
341             catch (Exception JavaDoc e)
342             {
343                 log("Unable to register JDBC driver: " + driverClassName + ", Exception: " + e);
344             }
345         }
346     }
347
348     /**
349      * Creates instances of ConnectionPool based on the properties.
350      * @param props the connection pool properties
351      */

352     private void createPools(Properties props)
353     {
354         Iterator iter = props.keySet().iterator();
355         while (iter.hasNext())
356         {
357             String JavaDoc name = (String JavaDoc)iter.next();
358             if (name.endsWith(".url"))
359             {
360                 String JavaDoc poolName = name.substring(0, name.lastIndexOf("."));
361                 String JavaDoc url = props.getProperty(poolName + ".url");
362                 if (url == null)
363                 {
364                     log("No URL specified for " + poolName);
365                     continue;
366                 }
367
368                 String JavaDoc user = props.getProperty(poolName + ".user");
369                 user = (user != null) ? user.trim() : user;
370                 String JavaDoc pass = props.getProperty(poolName + ".password");
371                 pass = (pass != null) ? pass.trim() : pass;
372                 String JavaDoc poolSize = props.getProperty(poolName + ".maxpool", "0").trim();
373                 String JavaDoc maxSize = props.getProperty(poolName + ".maxconn", "0").trim();
374                 String JavaDoc init = props.getProperty(poolName + ".init", "0").trim();
375                 String JavaDoc expiry = props.getProperty(poolName + ".expiry", "0").trim();
376                 String JavaDoc validator = props.getProperty(poolName + ".validator");
377                 String JavaDoc decoder = props.getProperty(poolName + ".decoder");
378                 String JavaDoc logFile = props.getProperty(poolName + ".logfile");
379                 String JavaDoc dateformat = props.getProperty(poolName + ".dateformat");
380                 validator = (validator != null) ? validator.trim() : validator;
381                 boolean noCache = props.getProperty(poolName + ".cache", "true").trim().equalsIgnoreCase("false");
382                 boolean async = props.getProperty(poolName + ".async", "false").trim().equalsIgnoreCase("true");
383                 boolean poolDebug = props.getProperty(poolName + ".debug", "false").trim().equalsIgnoreCase("true");
384
385                 // Construct properties object for pool if extra info supplied
386
Properties poolProps = new Properties();
387                 String JavaDoc prefix = poolName + ".prop.";
388                 Iterator it = props.keySet().iterator();
389                 while (it.hasNext())
390                 {
391                     String JavaDoc s = (String JavaDoc)it.next();
392                     if (s.startsWith(prefix))
393                         poolProps.setProperty(s.substring(prefix.length()), props.getProperty(s));
394                 }
395                 if (!poolProps.isEmpty() && user != null && !user.equals(""))
396                 {
397                     poolProps.setProperty("user", user);
398                     poolProps.setProperty("password", pass);
399                 }
400                 else
401                     poolProps = null;
402
403                 // Validate poolsize
404
int pSize, mSize, iSize, exp;
405                 try { pSize = Integer.valueOf(poolSize).intValue(); }
406                 catch (NumberFormatException JavaDoc nfe)
407                 {
408                     log("Invalid maxpool value " + poolSize + " for " + poolName);
409                     pSize = 0;
410                 }
411                 // Validate maxsize
412
try { mSize = Integer.valueOf(maxSize).intValue(); }
413                 catch (NumberFormatException JavaDoc nfe)
414                 {
415                     log("Invalid maxconn value " + maxSize + " for " + poolName);
416                     mSize = 0;
417                 }
418                 // Validate init
419
try { iSize = Integer.valueOf(init).intValue(); }
420                 catch (NumberFormatException JavaDoc nfe)
421                 {
422                     log("Invalid initsize value " + init + " for " + poolName);
423                     iSize = 0;
424                 }
425                 // Validate expiry
426
try { exp = Integer.valueOf(expiry).intValue(); }
427                 catch (NumberFormatException JavaDoc nfe)
428                 {
429                     log("Invalid expiry value " + expiry + " for " + poolName);
430                     exp = 0;
431                 }
432
433                 // Validate pool size logic
434
pSize = Math.max(pSize, 0); // (ensure pSize >= 0)
435
mSize = Math.max(mSize, 0); // (ensure mSize >= 0)
436
if (mSize > 0) // (if mSize > 0, ensure mSize >= pSize)
437
mSize = Math.max(mSize, pSize);
438                 iSize = Math.min(Math.max(iSize, 0), pSize); // (ensure 0 <= iSize <= pSize)
439
exp = Math.max(exp, 0); // (ensure exp >= 0)
440

441                 // Create connection pool
442
ConnectionPool pool = null;
443                 if (poolProps != null)
444                     pool = new ConnectionPool(poolName, pSize, mSize, (long)(exp * 1000), url, poolProps);
445                 else
446                     pool = new ConnectionPool(poolName, pSize, mSize, (long)(exp * 1000), url, user, pass);
447
448                 // Set custom date format, if applicable.
449
try
450                 {
451                     DateFormat df = new SimpleDateFormat(dateformat);
452                     pool.setDateFormat(df);
453                 }
454                 catch (Exception JavaDoc e)
455                 {
456                     log("Invalid dateformat string specified: " + dateformat);
457                 }
458
459                 // Setup pool logging (pool-specific if specified, otherwise generic logfile)
460
if (logFile != null && !logFile.equals(""))
461                 {
462                     File f = new File(logFile);
463                     if (f.exists() && f.isDirectory())
464                         log("Invalid logfile specified for pool " + poolName + " - specified file is a directory");
465                     else if (!f.exists() && !f.mkdirs())
466                         log("Invalid logfile specified for pool " + poolName + " - cannot create file " + f.getAbsolutePath());
467                     try { pool.setLog(new FileOutputStream(f, true)); }
468                     catch (FileNotFoundException fnfe)
469                     {
470                         log(fnfe, "Invalid logfile specified for pool " + poolName);
471                         pool.setLog(getLogStream());
472                     }
473                 }
474                 else
475                     pool.setLog(getLogStream());
476
477                 if (poolDebug)
478                     log("Enabling debug info on pool " + poolName);
479                 pool.setDebug(poolDebug);
480                 if (noCache)
481                     log("Disabling caching on pool " + poolName);
482                 pool.setCaching(!noCache);
483                 if (async)
484                     log("Enabling asynchronous destruction on pool " + poolName);
485                 pool.setAsyncDestroy(async);
486
487                 // Setup connection validator for pool
488
if (validator != null && !validator.equals(""))
489                 {
490                     try
491                     {
492                         Object JavaDoc o = Class.forName(validator).newInstance();
493                         if (o instanceof ConnectionValidator)
494                             pool.setValidator((ConnectionValidator)o);
495                     }
496                     catch (Exception JavaDoc ex)
497                     {
498                         log("Unable to instantiate validator class for pool " + poolName + ": " + validator);
499                     }
500                 }
501
502                 // Setup password decoder for pool
503
if (decoder != null && !decoder.equals(""))
504                 {
505                     try
506                     {
507                         Object JavaDoc o = Class.forName(decoder).newInstance();
508                         if (o instanceof PasswordDecoder)
509                             pool.setPasswordDecoder((PasswordDecoder)o);
510                     }
511                     catch (Exception JavaDoc ex)
512                     {
513                         log("Unable to instantiate password decoder class for pool " + poolName + ": " + decoder);
514                     }
515                 }
516
517                 // Add new pool to collection, and show summary info
518
synchronized(pools) { pools.put(poolName, pool); }
519                 String JavaDoc info = "pool=" + pool.getPoolSize() + ",max=" + pool.getMaxSize() + ",expiry=";
520                 info += pool.getExpiryTime() == 0 ? "none" : pool.getExpiryTime() + "ms";
521                 log("Initialized pool " + poolName + " (" + info + ")");
522
523                 // Setup initial connections in pool (spawns a thread)
524
if (iSize > 0)
525                     pool.init(iSize);
526             }
527         }
528     }
529
530     /**
531      * Returns a connection pool.
532      * (This is only provided as a convenience method to allow fine-tuning in
533      * exceptional circumstances.)
534      * @param name pool name as defined in the properties file
535      * @return the pool or null
536      */

537     public ConnectionPool getPool(String JavaDoc name)
538     {
539         if (released)
540             throw new RuntimeException JavaDoc("Pool manager no longer valid for use");
541         return (ConnectionPool)pools.get(name);
542     }
543
544     /**
545      * Returns all the current connection pools maintained by this manager.
546      * (This is only provided as a convenience method.)
547      * @return array of ConnectionPool objects
548      */

549     public ConnectionPool[] getPools()
550     {
551         synchronized(pools)
552         {
553             return (ConnectionPool[])pools.values().toArray(new ConnectionPool[0]);
554         }
555     }
556
557     /**
558      * Returns an open connection from the specified pool.
559      * If one is not available, and the max number of connections has not been
560      * reached, a new connection is created.
561      * @param name pool name as defined in the properties file
562      * @return a connection, or null if unable to obtain one
563      */

564     public Connection getConnection(String JavaDoc name) throws SQLException
565     {
566         if (released)
567             throw new RuntimeException JavaDoc("Pool manager no longer valid for use");
568
569         ConnectionPool pool = (ConnectionPool)pools.get(name);
570         if (pool != null)
571             return pool.getConnection();
572         return null;
573     }
574
575     /**
576      * Returns an open connection from the specified pool.
577      * If one is not available, and the max number of connections has not been
578      * reached, a new connection is created. If the max number has been
579      * reached, waits until one is available or the specified time has elapsed.
580      * @param name pool name as defined in the properties file
581      * @param time number of milliseconds to wait
582      * @return the connection or null
583      */

584     public Connection getConnection(String JavaDoc name, long time) throws SQLException
585     {
586         if (released)
587             throw new RuntimeException JavaDoc("Pool manager no longer valid for use");
588
589         ConnectionPool pool = (ConnectionPool)pools.get(name);
590         if (pool != null)
591             return pool.getConnection(time);
592         return null;
593     }
594
595     /**
596      * Releases all resources for this ConnectionPoolManager, and deregisters
597      * JDBC drivers if necessary. Any connections still in use are forcibly closed.
598      */

599     public synchronized void release()
600     {
601         // Don't release if client still active
602
if (--clients > 0)
603             return;
604         // Set released flag to prevent check-out of new items
605
released = true;
606
607         synchronized(pools)
608         {
609             for (Iterator it = pools.values().iterator(); it.hasNext();)
610             {
611                 ConnectionPool pool = (ConnectionPool)it.next();
612                 pool.releaseForcibly();
613             }
614         }
615
616         // Check if drivers can be deregistered (only 1 manager left)
617
if (managers.size() == 1)
618         {
619             for (Iterator it = drivers.iterator(); it.hasNext();)
620             {
621                 Driver driver = (Driver)it.next();
622                 try
623                 {
624                     DriverManager.deregisterDriver(driver);
625                     log("Deregistered JDBC driver " + driver.getClass().getName());
626                 }
627                 catch (SQLException sqle)
628                 {
629                     log(sqle, "Can't deregister JDBC driver: " + driver.getClass().getName());
630                 }
631             }
632         }
633         // Remove this manager from those referenced
634
managers.remove(this.key);
635
636         // Close log
637
super.close();
638     }
639
640     /**
641      * Returns whether this instance has been released (and therefore is unusable).
642      */

643     public synchronized boolean isReleased() { return this.released; }
644
645     /**
646      * Convenience method to set the validator class for all managed connection pools.
647      * @deprecated To be removed in a future release
648      */

649     public synchronized void setValidator(ConnectionValidator cv)
650     {
651         synchronized(pools)
652         {
653             if (pools != null)
654             {
655                 for (Iterator it = pools.values().iterator(); it.hasNext();)
656                     ((ConnectionPool)it.next()).setValidator(cv);
657             }
658         }
659     }
660
661     /**
662      * Convenience method to override LogUtil method to set log for pools.
663      * @deprecated To be removed in a future release
664      */

665     public void setLog(OutputStream out)
666     {
667         super.setLog(out);
668         // Set log for all pools
669
synchronized(pools)
670         {
671             if (pools != null)
672             {
673                 for (Iterator it = pools.values().iterator(); it.hasNext();)
674                     ((ConnectionPool)it.next()).setLog(out);
675             }
676         }
677     }
678
679     /**
680      * Convenience method to override LogUtil method to set log for pools.
681      * @deprecated To be removed in a future release
682      */

683     public void setLog(PrintStream ps)
684     {
685         super.setLog(ps);
686         // Set log for all pools
687
synchronized(pools)
688         {
689             if (pools != null)
690             {
691                 for (Iterator it = pools.values().iterator(); it.hasNext();)
692                     ((ConnectionPool)it.next()).setLog(ps);
693             }
694         }
695     }
696 }
Popular Tags