Source Code Cross Referenced for ConnectionPoolManager.java in  » Database-JDBC-Connection-Pool » DBPool » snaq » db » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » DBPool » snaq.db 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:        	DBPool - JDBC Connection Pool Manager
003:        	Copyright (c) Giles Winstanley
004:         */
005:        package snaq.db;
006:
007:        import java.io.*;
008:        import java.sql.*;
009:        import java.text.*;
010:        import java.util.*;
011:        import snaq.util.LogUtil;
012:
013:        /**
014:         * <p>Class to provide access and management for multiple connection pools
015:         * defined in a properties file or object.
016:         * Clients get access to each defined instance through one of the
017:         * static <tt>getInstance()</tt> methods and can then check-out and check-in
018:         * database connections from the pools defined by that manager.</p>
019:         *
020:         * <p>Each successful call to a <tt>getInstance()</tt> method also increments
021:         * an internal counter which keeps a record of the number of clients which hold
022:         * a reference to that particular pool manager. When each client has finished
023:         * using a pool manager it should call the <tt>release()</tt> method to
024:         * let the manager know that it is no longer needed by that client, so it can
025:         * clean up it's resources as necessary. The resources will not be released
026:         * until the clients counter has reached zero. <em>It is therefore necessary to
027:         * allocate and release your pool manager references carefully</em>.</p>
028:         *
029:         * <p>Properties for a manager can be specified in three different ways.
030:         * <ol>
031:         * <li>Properties file located in CLASSPATH
032:         * <li>Properties file referenced explicitly (with a File object)
033:         * <li>Properties object
034:         * </ol>
035:         *
036:         * <ol>
037:         * <li>A CLASSPATH located properties file can simply be accessed using the
038:         * method <tt>getInstance(name)</tt> where <em>name</em> is the name of the
039:         * properties file specified as a string.
040:         * <li>To specify a properties file which is not in the CLASSPATH use the
041:         * method <tt>getInstance(File)</tt>. This same file handle must be used
042:         * each time you want to obtain the instance in this way.
043:         * <li>To specify the pools using a Properties object a call must be made to
044:         * the <tt>createInstance(Properties)</tt> method. This method creates the
045:         * ConnectionPoolManager instance and makes it available via the <tt>getInstance()</tt>
046:         * method.
047:         * </ol>
048:         * <p><b>Note:</b> The <tt>getInstance()</tt> method can return one of two
049:         * possible instances depending on the previous calls made to the pool manager.
050:         * If the <tt>createInstance(Properties)</tt> method has previously been
051:         * called successfully then it will return this manually created instance.
052:         * Otherwise it will attempt to return an instance relating to the default
053:         * properties file (dbpool.properties) within the CLASSPATH, if it exists.</p>
054:         *
055:         * <p>The properties given to the manager specify which JDBC drivers to use to
056:         * access the relevant databases, and also defines the characteristics of each
057:         * connection pool. The properties required/allowed are as follows
058:         * (those marked with * are mandatory):</p>
059:         * <pre>
060:         * drivers*               Class names of required JDBC Drivers (comma/space delimited)
061:         * logfile*               Filename of logfile
062:         *
063:         * &lt;poolname&gt;.url*        The JDBC URL for the database
064:         * &lt;poolname&gt;.user        Database username for login
065:         * &lt;poolname&gt;.password    Database password for login
066:         * &lt;poolname&gt;.maxpool     The maximum number of pooled connections (0 if none)
067:         * &lt;poolname&gt;.maxconn     The maximum number of possible connections (0 if no limit)
068:         * &lt;poolname&gt;.expiry      The connection expiry time in seconds (0 if no expiry)
069:         * &lt;poolname&gt;.init        The initial number of connections to create (default:0)
070:         * &lt;poolname&gt;.validator   Class name of connection validator (optional)
071:         * &lt;poolname&gt;.decoder     Class name of password decoder (optional)
072:         * &lt;poolname&gt;.cache       Whether to cache Statements (optional, default:true)
073:         * &lt;poolname&gt;.debug       Whether to log debug info (optional, default:false)
074:         * &lt;poolname&gt;.prop.<em>XXX</em>    Passes property <em>XXX</em> and it's value to the JDBC driver
075:         * &lt;poolname&gt;.async       Whether to use asynchronous connection destruction (optional, default:false)
076:         * &lt;poolname&gt;.logfile     Filename of logfile for this pool (optional)
077:         * &lt;poolname&gt;.dateformat  SimpleDateFormat formatting string for log entries (optional)
078:         * </pre>
079:         *
080:         * <p>Multiple pools can be specified provided they each use a different pool name.
081:         * The <tt>validator</tt> property optionally specifies the name of a
082:         * class to be used for validating the database connections. The default
083:         * connection validation simply performs a test using <tt>Connection.isClosed()</tt>.
084:         * This test is not 100% reliable as the Java API documentation specifies that
085:         * it only returns true if the connection has been explicitly closed.
086:         * If more rigorous connection validation is required you can either use the
087:         * provided class <tt>snaq.db.AutoCommitValidator</tt> or write your own
088:         * validation class which should implement the <tt>ConnectionValidator</tt>
089:         * interface.</p>
090:         *
091:         * @see snaq.db.AutoCommitValidator
092:         * @see snaq.db.ConnectionValidator
093:         * @author Giles Winstanley
094:         */
095:        public final class ConnectionPoolManager extends LogUtil implements 
096:                Comparable {
097:            private static final String PROPERTIES_INSTANCE_KEY = "PROPERTIES_INSTANCE";
098:            private static final String DEFAULT_PROPERTIES_FILE = "/dbpool.properties";
099:            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 source, key;
106:
107:            private ConnectionPoolManager(Properties props, Object src) {
108:                super ();
109:                this .source = src;
110:                init(props);
111:            }
112:
113:            /** Returns a descriptive string for this instance. */
114:            public String toString() {
115:                if (source instanceof  String)
116:                    return "ConnectionPoolManager [CLASSPATH resource:"
117:                            + source + "]";
118:                else if (source instanceof  File)
119:                    return "ConnectionPoolManager [File:"
120:                            + ((File) source).getAbsolutePath() + "]";
121:                else if (source instanceof  Properties)
122:                    return "ConnectionPoolManager [Properties]";
123:                else
124:                    return "ConnectionPoolManager [Unknown]";
125:            }
126:
127:            /** Compares this instances to other instances by name. */
128:            public int compareTo(Object o) {
129:                return this .toString().compareTo(
130:                        ((ConnectionPoolManager) o).toString());
131:            }
132:
133:            /**
134:             * Returns an enumeration of all the available ConnectionPoolManager instances.
135:             * This method is included for convenience for external monitoring.
136:             * Clients wanting to obtain an instance for using connections should NOT use
137:             * this method.
138:             * @deprecated Replaced by <tt>getInstances()</tt>, which returns a <tt>Set</tt>
139:             */
140:            public static Enumeration instances() {
141:                return Collections.enumeration(getInstances());
142:            }
143:
144:            /**
145:             * Returns a Set containing all the current ConnectionPoolManager instances.
146:             * This method is included for convenience for external monitoring.
147:             * Clients wanting to obtain an instance for using connections should NOT use
148:             * this method.
149:             * @return all current instances of ConnectionPoolManager.
150:             */
151:            public static Set getInstances() {
152:                Set x = new HashSet();
153:                x.addAll(managers.values());
154:                return x;
155:            }
156:
157:            /**
158:             * Returns the singleton instance of the ConnectionPoolManager for the specified properties file.
159:             * @param propsFile filename of the properties file to use (path info should not be specified; available CLASSPATH will be searched for the properties file)
160:             * @return instance of ConnectionPoolManager relating to the specified properties file
161:             * @throws IOException if there was an problem loading the properties
162:             */
163:            public static synchronized ConnectionPoolManager getInstance(
164:                    String propsFile) throws IOException {
165:                String s = propsFile.startsWith("/") ? propsFile
166:                        : ("/" + propsFile);
167:                Object o = managers.get(s);
168:                ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager) o
169:                        : null;
170:                if (cpm == null || cpm.isReleased()) {
171:                    cpm = new ConnectionPoolManager(loadProperties(s),
172:                            propsFile);
173:                    cpm.key = s;
174:                    managers.put(cpm.key, cpm);
175:                }
176:                cpm.clients++;
177:                return cpm;
178:            }
179:
180:            /**
181:             * Returns the singleton instance of the ConnectionPoolManager for the specified properties file.
182:             * @param propsFile filename of the properties file to use (path info should not be specified; available CLASSPATH will be searched for the properties file)
183:             * @return instance of ConnectionPoolManager relating to the specified properties file
184:             * @throws IOException if there was an problem loading the properties
185:             */
186:            public static synchronized ConnectionPoolManager getInstance(
187:                    File propsFile) throws IOException {
188:                Object o = managers.get(propsFile);
189:                ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager) o
190:                        : null;
191:                if (cpm == null || cpm.isReleased()) {
192:                    try {
193:                        cpm = new ConnectionPoolManager(
194:                                loadProperties(propsFile), propsFile);
195:                        cpm.key = propsFile;
196:                        managers.put(cpm.key, cpm);
197:                    } catch (IOException ioe) {
198:                        if (ioe instanceof  FileNotFoundException)
199:                            System.err
200:                                    .println("Unable to find the properties file "
201:                                            + propsFile.getAbsolutePath());
202:                        else
203:                            System.err
204:                                    .println("Error loading the properties file "
205:                                            + propsFile.getAbsolutePath());
206:                        ioe.printStackTrace();
207:                        return null;
208:                    }
209:                }
210:                cpm.clients++;
211:                return cpm;
212:            }
213:
214:            /**
215:             * Returns the standard singleton instance of the ConnectionPoolManager.
216:             * If an instance has been obtained with a user-specified Properties object
217:             * then this instance is returned, otherwise an attempt is made to return an
218:             * instance using the default properties file (dbpool.properties).
219:             * @throws IOException if there was an problem loading the properties
220:             */
221:            public static synchronized ConnectionPoolManager getInstance()
222:                    throws IOException {
223:                Object o = managers.get(PROPERTIES_INSTANCE_KEY);
224:                ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager) o
225:                        : null;
226:                if (cpm != null && !cpm.released)
227:                    cpm.clients++;
228:                else
229:                    cpm = getInstance(DEFAULT_PROPERTIES_FILE);
230:
231:                return cpm;
232:            }
233:
234:            /**
235:             * Creates a singleton instance of the ConnectionPoolManager for the specified
236:             * Properties object. To subsequently use this instance user's should call the
237:             * getInstance() method. This mechanism is used to provide the maximum
238:             * separation between creation and use of this instance to avoid haphazard
239:             * changes to any referenced Properties onject that may occur between calls.
240:             * (This method can only be used successfully if no default properties
241:             * instance exists and is in use at the time of calling.)
242:             * @param props Properties object to use
243:             * @throws RuntimeException if default properties instance already exists and is in use
244:             */
245:            public static synchronized void createInstance(Properties props) {
246:                // Check for presence of default properties file instance
247:                Object o = managers.get(DEFAULT_PROPERTIES_FILE);
248:                ConnectionPoolManager cpm = (o != null) ? (ConnectionPoolManager) o
249:                        : null;
250:                if (cpm != null && !cpm.isReleased())
251:                    throw new RuntimeException(
252:                            "Default properties file instance already exists");
253:
254:                // Create new instance and store reference
255:                cpm = new ConnectionPoolManager(props, props);
256:                cpm.key = PROPERTIES_INSTANCE_KEY;
257:                managers.put(cpm.key, cpm);
258:            }
259:
260:            /**
261:             * Loads and returns a Properties object from file.
262:             */
263:            private static Properties loadProperties(File propsFile)
264:                    throws IOException {
265:                if (!propsFile.exists())
266:                    throw new FileNotFoundException(propsFile.getAbsolutePath()
267:                            + " does not exist");
268:                if (propsFile.isDirectory())
269:                    throw new IOException("Error accessing properties file - "
270:                            + propsFile.getAbsolutePath() + " is a directory");
271:                InputStream is = new FileInputStream(propsFile);
272:                Properties props = new Properties();
273:                props.load(is);
274:                is.close();
275:                return props;
276:            }
277:
278:            /**
279:             * Loads and returns a Properties object from the resource specified..
280:             * The resource should be located in the current CLASSPATH to be found.
281:             * @throws IOException if there was an problem loading the properties
282:             */
283:            private static Properties loadProperties(String propsResource)
284:                    throws IOException {
285:                InputStream is = ConnectionPoolManager.class
286:                        .getResourceAsStream(propsResource);
287:                Properties props = new Properties();
288:                try {
289:                    props.load(is);
290:                } catch (IOException ioe) {
291:                    System.err
292:                            .println("Unable to load the properties file. Make sure "
293:                                    + propsResource + " is in the CLASSPATH.");
294:                    ioe.printStackTrace();
295:                    throw ioe;
296:                }
297:                return props;
298:            }
299:
300:            /**
301:             * Initializes this instance with values from the given Properties object.
302:             */
303:            private void init(Properties props) {
304:                String logFile = props.getProperty("logfile",
305:                        "ConnectionPoolManager.log");
306:                String df = props.getProperty("dateformat",
307:                        "EEE MMM dd hh:mm:ss.SSS ZZZ yyyy");
308:                try {
309:                    setDateFormat(new SimpleDateFormat(df));
310:                    setLog(new FileOutputStream(logFile, true));
311:                } catch (IOException e) {
312:                    System.err.println("Can't open the log file: " + logFile);
313:                }
314:                loadDrivers(props);
315:                createPools(props);
316:            }
317:
318:            /**
319:             * Loads and registers all JDBC drivers. This is done by the
320:             * DBConnectionManager, as opposed to the ConnectionPool,
321:             * since many pools may share the same driver.
322:             * @param props the connection pool properties
323:             */
324:            private void loadDrivers(Properties props) {
325:                String driverClasses = props.getProperty("drivers");
326:                StringTokenizer st = new StringTokenizer(driverClasses,
327:                        ",: \t\n\r\f");
328:                Enumeration current = DriverManager.getDrivers();
329:                while (st.hasMoreElements()) {
330:                    String driverClassName = st.nextToken().trim();
331:                    try {
332:                        // Check if driver already registered
333:                        boolean using = false;
334:                        while (current.hasMoreElements()) {
335:                            String cName = current.nextElement().getClass()
336:                                    .getName();
337:                            if (cName.equals(driverClassName))
338:                                using = true;
339:                        }
340:                        if (!using) {
341:                            Driver driver = (Driver) Class.forName(
342:                                    driverClassName).newInstance();
343:                            DriverManager.registerDriver(driver);
344:                            drivers.add(driver);
345:                            log("Registered JDBC driver " + driverClassName);
346:                        }
347:                    } catch (Exception e) {
348:                        log("Unable to register JDBC driver: "
349:                                + driverClassName + ", Exception: " + e);
350:                    }
351:                }
352:            }
353:
354:            /**
355:             * Creates instances of ConnectionPool based on the properties.
356:             * @param props the connection pool properties
357:             */
358:            private void createPools(Properties props) {
359:                Iterator iter = props.keySet().iterator();
360:                while (iter.hasNext()) {
361:                    String name = (String) iter.next();
362:                    if (name.endsWith(".url")) {
363:                        String poolName = name.substring(0, name
364:                                .lastIndexOf("."));
365:                        String url = props.getProperty(poolName + ".url");
366:                        if (url == null) {
367:                            log("No URL specified for " + poolName);
368:                            continue;
369:                        }
370:
371:                        String user = props.getProperty(poolName + ".user");
372:                        user = (user != null) ? user.trim() : user;
373:                        String pass = props.getProperty(poolName + ".password");
374:                        pass = (pass != null) ? pass.trim() : pass;
375:                        String poolSize = props.getProperty(
376:                                poolName + ".maxpool", "0").trim();
377:                        String maxSize = props.getProperty(
378:                                poolName + ".maxconn", "0").trim();
379:                        String init = props
380:                                .getProperty(poolName + ".init", "0").trim();
381:                        String expiry = props.getProperty(poolName + ".expiry",
382:                                "0").trim();
383:                        String validator = props.getProperty(poolName
384:                                + ".validator");
385:                        String decoder = props.getProperty(poolName
386:                                + ".decoder");
387:                        String logFile = props.getProperty(poolName
388:                                + ".logfile");
389:                        String dateformat = props.getProperty(poolName
390:                                + ".dateformat");
391:                        validator = (validator != null) ? validator.trim()
392:                                : validator;
393:                        boolean noCache = props.getProperty(
394:                                poolName + ".cache", "true").trim()
395:                                .equalsIgnoreCase("false");
396:                        boolean async = props.getProperty(poolName + ".async",
397:                                "false").trim().equalsIgnoreCase("true");
398:                        boolean poolDebug = props.getProperty(
399:                                poolName + ".debug", "false").trim()
400:                                .equalsIgnoreCase("true");
401:
402:                        // Construct properties object for pool if extra info supplied
403:                        Properties poolProps = new Properties();
404:                        String prefix = poolName + ".prop.";
405:                        Iterator it = props.keySet().iterator();
406:                        while (it.hasNext()) {
407:                            String s = (String) it.next();
408:                            if (s.startsWith(prefix))
409:                                poolProps.setProperty(s.substring(prefix
410:                                        .length()), props.getProperty(s));
411:                        }
412:                        if (!poolProps.isEmpty() && user != null
413:                                && !user.equals("")) {
414:                            poolProps.setProperty("user", user);
415:                            poolProps.setProperty("password", pass);
416:                        } else
417:                            poolProps = null;
418:
419:                        // Validate poolsize
420:                        int pSize, mSize, iSize, exp;
421:                        try {
422:                            pSize = Integer.valueOf(poolSize).intValue();
423:                        } catch (NumberFormatException nfe) {
424:                            log("Invalid maxpool value " + poolSize + " for "
425:                                    + poolName);
426:                            pSize = 0;
427:                        }
428:                        // Validate maxsize
429:                        try {
430:                            mSize = Integer.valueOf(maxSize).intValue();
431:                        } catch (NumberFormatException nfe) {
432:                            log("Invalid maxconn value " + maxSize + " for "
433:                                    + poolName);
434:                            mSize = 0;
435:                        }
436:                        // Validate init
437:                        try {
438:                            iSize = Integer.valueOf(init).intValue();
439:                        } catch (NumberFormatException nfe) {
440:                            log("Invalid initsize value " + init + " for "
441:                                    + poolName);
442:                            iSize = 0;
443:                        }
444:                        // Validate expiry
445:                        try {
446:                            exp = Integer.valueOf(expiry).intValue();
447:                        } catch (NumberFormatException nfe) {
448:                            log("Invalid expiry value " + expiry + " for "
449:                                    + poolName);
450:                            exp = 0;
451:                        }
452:
453:                        // Validate pool size logic
454:                        pSize = Math.max(pSize, 0); // (ensure pSize >= 0)
455:                        mSize = Math.max(mSize, 0); // (ensure mSize >= 0)
456:                        if (mSize > 0) // (if mSize > 0, ensure mSize >= pSize)
457:                            mSize = Math.max(mSize, pSize);
458:                        iSize = Math.min(Math.max(iSize, 0), pSize); // (ensure 0 <= iSize <= pSize)
459:                        exp = Math.max(exp, 0); // (ensure exp >= 0)
460:
461:                        // Create connection pool
462:                        ConnectionPool pool = null;
463:                        if (poolProps != null)
464:                            pool = new ConnectionPool(poolName, pSize, mSize,
465:                                    (long) (exp * 1000), url, poolProps);
466:                        else
467:                            pool = new ConnectionPool(poolName, pSize, mSize,
468:                                    (long) (exp * 1000), url, user, pass);
469:
470:                        // Set custom date format, if applicable.
471:                        try {
472:                            DateFormat df = new SimpleDateFormat(dateformat);
473:                            pool.setDateFormat(df);
474:                        } catch (Exception e) {
475:                            log("Invalid dateformat string specified: "
476:                                    + dateformat);
477:                        }
478:
479:                        // Setup pool logging (pool-specific if specified, otherwise generic logfile)
480:                        if (logFile != null && !logFile.equals("")) {
481:                            File f = new File(logFile);
482:                            if (f.exists() && f.isDirectory())
483:                                log("Invalid logfile specified for pool "
484:                                        + poolName
485:                                        + " - specified file is a directory");
486:                            else if (!f.exists() && !f.mkdirs())
487:                                log("Invalid logfile specified for pool "
488:                                        + poolName + " - cannot create file "
489:                                        + f.getAbsolutePath());
490:                            try {
491:                                pool.setLog(new FileOutputStream(f, true));
492:                            } catch (FileNotFoundException fnfe) {
493:                                log(fnfe, "Invalid logfile specified for pool "
494:                                        + poolName);
495:                                pool.setLog(getLogStream());
496:                            }
497:                        } else
498:                            pool.setLog(getLogStream());
499:
500:                        if (poolDebug)
501:                            log("Enabling debug info on pool " + poolName);
502:                        pool.setDebug(poolDebug);
503:                        if (noCache)
504:                            log("Disabling caching on pool " + poolName);
505:                        pool.setCaching(!noCache);
506:                        if (async)
507:                            log("Enabling asynchronous destruction on pool "
508:                                    + poolName);
509:                        pool.setAsyncDestroy(async);
510:
511:                        // Setup connection validator for pool
512:                        if (validator != null && !validator.equals("")) {
513:                            try {
514:                                Object o = Class.forName(validator)
515:                                        .newInstance();
516:                                if (o instanceof  ConnectionValidator)
517:                                    pool.setValidator((ConnectionValidator) o);
518:                            } catch (Exception ex) {
519:                                log("Unable to instantiate validator class for pool "
520:                                        + poolName + ": " + validator);
521:                            }
522:                        }
523:
524:                        // Setup password decoder for pool
525:                        if (decoder != null && !decoder.equals("")) {
526:                            try {
527:                                Object o = Class.forName(decoder).newInstance();
528:                                if (o instanceof  PasswordDecoder)
529:                                    pool
530:                                            .setPasswordDecoder((PasswordDecoder) o);
531:                            } catch (Exception ex) {
532:                                log("Unable to instantiate password decoder class for pool "
533:                                        + poolName + ": " + decoder);
534:                            }
535:                        }
536:
537:                        // Add new pool to collection, and show summary info
538:                        synchronized (pools) {
539:                            pools.put(poolName, pool);
540:                        }
541:                        String info = "pool=" + pool.getPoolSize() + ",max="
542:                                + pool.getMaxSize() + ",expiry=";
543:                        info += pool.getExpiryTime() == 0 ? "none" : pool
544:                                .getExpiryTime()
545:                                + "ms";
546:                        log("Initialized pool " + poolName + " (" + info + ")");
547:
548:                        // Setup initial connections in pool (spawns a thread)
549:                        if (iSize > 0)
550:                            pool.init(iSize);
551:                    }
552:                }
553:            }
554:
555:            /**
556:             * Returns a connection pool.
557:             * (This is only provided as a convenience method to allow fine-tuning in
558:             * exceptional circumstances.)
559:             * @param name pool name as defined in the properties file
560:             * @return the pool or null
561:             */
562:            public ConnectionPool getPool(String name) {
563:                if (released)
564:                    throw new RuntimeException(
565:                            "Pool manager no longer valid for use");
566:                return (ConnectionPool) pools.get(name);
567:            }
568:
569:            /**
570:             * Returns all the current connection pools maintained by this manager.
571:             * (This is only provided as a convenience method.)
572:             * @return array of ConnectionPool objects
573:             */
574:            public ConnectionPool[] getPools() {
575:                synchronized (pools) {
576:                    return (ConnectionPool[]) pools.values().toArray(
577:                            new ConnectionPool[0]);
578:                }
579:            }
580:
581:            /**
582:             * Returns an open connection from the specified pool.
583:             * If one is not available, and the max number of connections has not been
584:             * reached, a new connection is created.
585:             * @param name pool name as defined in the properties file
586:             * @return a connection, or null if unable to obtain one
587:             */
588:            public Connection getConnection(String name) throws SQLException {
589:                if (released)
590:                    throw new RuntimeException(
591:                            "Pool manager no longer valid for use");
592:
593:                ConnectionPool pool = (ConnectionPool) pools.get(name);
594:                if (pool != null)
595:                    return pool.getConnection();
596:                return null;
597:            }
598:
599:            /**
600:             * Returns an open connection from the specified pool.
601:             * If one is not available, and the max number of connections has not been
602:             * reached, a new connection is created. If the max number has been
603:             * reached, waits until one is available or the specified time has elapsed.
604:             * @param name pool name as defined in the properties file
605:             * @param time number of milliseconds to wait
606:             * @return the connection or null
607:             */
608:            public Connection getConnection(String name, long time)
609:                    throws SQLException {
610:                if (released)
611:                    throw new RuntimeException(
612:                            "Pool manager no longer valid for use");
613:
614:                ConnectionPool pool = (ConnectionPool) pools.get(name);
615:                if (pool != null)
616:                    return pool.getConnection(time);
617:                return null;
618:            }
619:
620:            /**
621:             * Releases all resources for this ConnectionPoolManager, and deregisters
622:             * JDBC drivers if necessary. Any connections still in use are forcibly closed.
623:             */
624:            public synchronized void release() {
625:                // Don't release if client still active
626:                if (--clients > 0)
627:                    return;
628:                // Set released flag to prevent check-out of new items
629:                released = true;
630:
631:                synchronized (pools) {
632:                    for (Iterator it = pools.values().iterator(); it.hasNext();) {
633:                        ConnectionPool pool = (ConnectionPool) it.next();
634:                        pool.releaseForcibly();
635:                    }
636:                }
637:
638:                // Check if drivers can be deregistered (only 1 manager left)
639:                if (managers.size() == 1) {
640:                    for (Iterator it = drivers.iterator(); it.hasNext();) {
641:                        Driver driver = (Driver) it.next();
642:                        try {
643:                            DriverManager.deregisterDriver(driver);
644:                            log("Deregistered JDBC driver "
645:                                    + driver.getClass().getName());
646:                        } catch (SQLException sqle) {
647:                            log(sqle, "Can't deregister JDBC driver: "
648:                                    + driver.getClass().getName());
649:                        }
650:                    }
651:                }
652:                // Remove this manager from those referenced
653:                managers.remove(this .key);
654:
655:                // Close log
656:                super .close();
657:            }
658:
659:            /**
660:             * Returns whether this instance has been released (and therefore is unusable).
661:             */
662:            public synchronized boolean isReleased() {
663:                return this .released;
664:            }
665:
666:            /**
667:             * Convenience method to set the validator class for all managed connection pools.
668:             * @deprecated To be removed in a future release
669:             */
670:            public synchronized void setValidator(ConnectionValidator cv) {
671:                synchronized (pools) {
672:                    if (pools != null) {
673:                        for (Iterator it = pools.values().iterator(); it
674:                                .hasNext();)
675:                            ((ConnectionPool) it.next()).setValidator(cv);
676:                    }
677:                }
678:            }
679:
680:            /**
681:             * Convenience method to override LogUtil method to set log for pools.
682:             * @deprecated To be removed in a future release
683:             */
684:            public void setLog(OutputStream out) {
685:                super .setLog(out);
686:                // Set log for all pools
687:                synchronized (pools) {
688:                    if (pools != null) {
689:                        for (Iterator it = pools.values().iterator(); it
690:                                .hasNext();)
691:                            ((ConnectionPool) it.next()).setLog(out);
692:                    }
693:                }
694:            }
695:
696:            /**
697:             * Convenience method to override LogUtil method to set log for pools.
698:             * @deprecated To be removed in a future release
699:             */
700:            public void setLog(PrintStream ps) {
701:                super .setLog(ps);
702:                // Set log for all pools
703:                synchronized (pools) {
704:                    if (pools != null) {
705:                        for (Iterator it = pools.values().iterator(); it
706:                                .hasNext();)
707:                            ((ConnectionPool) it.next()).setLog(ps);
708:                    }
709:                }
710:            }
711:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.