KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > c3p0 > impl > C3P0PooledConnectionPoolManager


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

22
23
24 package com.mchange.v2.c3p0.impl;
25
26 import java.beans.*;
27 import java.util.*;
28 import java.lang.reflect.*;
29 import java.sql.*;
30 import javax.sql.*;
31 import com.mchange.v2.c3p0.*;
32 import com.mchange.v2.c3p0.cfg.*;
33 import com.mchange.v2.async.*;
34 import com.mchange.v2.coalesce.*;
35 import com.mchange.v1.db.sql.*;
36 import com.mchange.v2.log.*;
37 import com.mchange.v1.lang.BooleanUtils;
38 import com.mchange.v2.sql.SqlUtils;
39 import com.mchange.v2.resourcepool.ResourcePoolFactory;
40 import com.mchange.v2.resourcepool.BasicResourcePoolFactory;
41
42 public final class C3P0PooledConnectionPoolManager
43 {
44     private final static MLogger logger = MLog.getLogger( C3P0PooledConnectionPoolManager.class );
45
46     private final static boolean POOL_EVENT_SUPPORT = false;
47
48     private final static CoalesceChecker COALESCE_CHECKER = IdentityTokenizedCoalesceChecker.INSTANCE;
49
50     // unsync'ed coalescer -- we synchronize the static factory method that uses it
51
final static Coalescer COALESCER = CoalescerFactory.createCoalescer( COALESCE_CHECKER, true, false );
52
53     final static int DFLT_NUM_TASK_THREADS_PER_DATA_SOURCE = 3;
54
55     //MT: protected by this' lock
56
ThreadPoolAsynchronousRunner taskRunner;
57     Timer timer;
58     ResourcePoolFactory rpfact;
59     Map authsToPools;
60
61     /* MT: independently thread-safe, never reassigned post-ctor or factory */
62     final ConnectionPoolDataSource cpds;
63     final Map propNamesToReadMethods;
64     final Map flatPropertyOverrides;
65     final Map userOverrides;
66     final DbAuth defaultAuth;
67     final String JavaDoc parentDataSourceIdentityToken;
68     /* MT: end independently thread-safe, never reassigned post-ctor or factory */
69
70     /* MT: unchanging after constructor completes */
71     int num_task_threads = DFLT_NUM_TASK_THREADS_PER_DATA_SOURCE;
72
73     /* MT: end unchanging after constructor completes */
74
75     public int getThreadPoolSize()
76     { return taskRunner.getThreadCount(); }
77
78     public int getThreadPoolNumActiveThreads()
79     { return taskRunner.getActiveCount(); }
80
81     public int getThreadPoolNumIdleThreads()
82     { return taskRunner.getIdleCount(); }
83
84     public int getThreadPoolNumTasksPending()
85     { return taskRunner.getPendingTaskCount(); }
86
87     public String JavaDoc getThreadPoolStackTraces()
88     { return taskRunner.getStackTraces(); }
89
90     public String JavaDoc getThreadPoolStatus()
91     { return taskRunner.getStatus(); }
92
93     private synchronized void poolsInit()
94     {
95         this.timer = new Timer( true );
96
97         int matt = this.getMaxAdministrativeTaskTime( null );
98         if ( matt > 0 )
99         {
100             int matt_ms = matt * 1000;
101             this.taskRunner = new ThreadPoolAsynchronousRunner( num_task_threads,
102
103                             true, // daemon thread
104

105                             matt_ms, // wait before interrupt()
106

107                             matt_ms * 3, // wait before deadlock declared if no tasks clear
108

109                             matt_ms * 6, // wait before deadlock tasks are interrupted (again)
110
// after the hung thread has been cleared and replaced
111
// (in hopes of getting the thread to terminate for
112
// garbage collection)
113

114                             timer );
115         }
116         else
117             this.taskRunner = new ThreadPoolAsynchronousRunner( num_task_threads, true, timer );
118         //this.taskRunner = new RoundRobinAsynchronousRunner( num_task_threads, true );
119
//this.rpfact = ResourcePoolFactory.createInstance( taskRunner, timer );
120
if (POOL_EVENT_SUPPORT)
121             this.rpfact = ResourcePoolFactory.createInstance( taskRunner, null, timer );
122         else
123             this.rpfact = BasicResourcePoolFactory.createNoEventSupportInstance( taskRunner, timer );
124         this.authsToPools = new HashMap();
125     }
126
127     private void poolsDestroy()
128     { poolsDestroy( true ); }
129
130     private synchronized void poolsDestroy( boolean close_outstanding_connections )
131     {
132         //System.err.println("poolsDestroy() -- " + this);
133
for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
134         {
135             try
136             { ((C3P0PooledConnectionPool) ii.next()).close( close_outstanding_connections ); }
137             catch ( Exception JavaDoc e )
138             {
139                 //e.printStackTrace();
140
logger.log(MLevel.WARNING, "An Exception occurred while trying to clean up a pool!", e);
141             }
142         }
143
144         this.taskRunner.close( true );
145         this.timer.cancel();
146
147         this.taskRunner = null;
148         this.timer = null;
149         this.rpfact = null;
150         this.authsToPools = null;
151     }
152
153     public C3P0PooledConnectionPoolManager(ConnectionPoolDataSource cpds,
154                     Map flatPropertyOverrides, // Map of properties, usually null
155
Map forceUserOverrides, // userNames to Map of properties, usually null
156
int num_task_threads,
157                     String JavaDoc parentDataSourceIdentityToken)
158     throws SQLException
159     {
160         try
161         {
162             this.cpds = cpds;
163             this.flatPropertyOverrides = flatPropertyOverrides;
164             this.num_task_threads = num_task_threads;
165             this.parentDataSourceIdentityToken = parentDataSourceIdentityToken;
166
167             DbAuth auth = null;
168
169             if ( flatPropertyOverrides != null )
170             {
171                 String JavaDoc overrideUser = (String JavaDoc) flatPropertyOverrides.get("overrideDefaultUser");
172                 String JavaDoc overridePassword = (String JavaDoc) flatPropertyOverrides.get("overrideDefaultPassword");
173
174                 if (overrideUser == null)
175                 {
176                     overrideUser = (String JavaDoc) flatPropertyOverrides.get("user");
177                     overridePassword = (String JavaDoc) flatPropertyOverrides.get("password");
178                 }
179
180                 if (overrideUser != null)
181                     auth = new DbAuth( overrideUser, overridePassword );
182             }
183
184             if (auth == null)
185                 auth = C3P0ImplUtils.findAuth( cpds );
186
187             this.defaultAuth = auth;
188
189             Map tmp = new HashMap();
190             BeanInfo bi = Introspector.getBeanInfo( cpds.getClass() );
191             PropertyDescriptor[] pds = bi.getPropertyDescriptors();
192             PropertyDescriptor pd = null;
193             for (int i = 0, len = pds.length; i < len; ++i)
194             {
195                 pd = pds[i];
196
197                 String JavaDoc name = pd.getName();
198                 Method m = pd.getReadMethod();
199
200                 if (m != null)
201                     tmp.put( name, m );
202             }
203             this.propNamesToReadMethods = tmp;
204
205             if (forceUserOverrides == null)
206             {
207                 Method uom = (Method) propNamesToReadMethods.get( "userOverridesAsString" );
208                 if (uom != null)
209                 {
210                     String JavaDoc uoas = (String JavaDoc) uom.invoke( cpds, null );
211                     //System.err.println("uoas: " + uoas);
212
Map uo = C3P0ImplUtils.parseUserOverridesAsString( uoas );
213                     this.userOverrides = uo;
214                 }
215                 else
216                     this.userOverrides = Collections.EMPTY_MAP;
217             }
218             else
219                 this.userOverrides = forceUserOverrides;
220
221             poolsInit();
222         }
223         catch (Exception JavaDoc e)
224         {
225             if (Debug.DEBUG)
226                 logger.log(MLevel.FINE, null, e);
227             //e.printStackTrace();
228
throw SqlUtils.toSQLException(e);
229         }
230     }
231
232     public synchronized C3P0PooledConnectionPool getPool(String JavaDoc username, String JavaDoc password, boolean create) throws SQLException
233     {
234         if (create)
235             return getPool( username, password );
236         else
237         {
238             DbAuth checkAuth = new DbAuth( username, password );
239             C3P0PooledConnectionPool out = (C3P0PooledConnectionPool) authsToPools.get(checkAuth);
240             if (out == null)
241                 throw new SQLException("No pool has been initialized for databse user '" + username + "' with the specified password.");
242             else
243                 return out;
244         }
245     }
246
247     public C3P0PooledConnectionPool getPool(String JavaDoc username, String JavaDoc password)
248     throws SQLException
249     { return getPool( new DbAuth( username, password ) ); }
250
251     public synchronized C3P0PooledConnectionPool getPool(DbAuth auth)
252     throws SQLException
253     {
254         C3P0PooledConnectionPool out = (C3P0PooledConnectionPool) authsToPools.get(auth);
255         if (out == null)
256         {
257             out = createPooledConnectionPool(auth);
258             authsToPools.put( auth, out );
259         }
260         return out;
261     }
262
263     public synchronized Set getManagedAuths()
264     { return Collections.unmodifiableSet( authsToPools.keySet() ); }
265
266     public synchronized int getNumManagedAuths()
267     { return authsToPools.size(); }
268
269     public C3P0PooledConnectionPool getPool()
270     throws SQLException
271     { return getPool( defaultAuth ); }
272
273     public synchronized int getNumIdleConnectionsAllAuths() throws SQLException
274     {
275         int out = 0;
276         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
277             out += ((C3P0PooledConnectionPool) ii.next()).getNumIdleConnections();
278         return out;
279     }
280
281     public synchronized int getNumBusyConnectionsAllAuths() throws SQLException
282     {
283         int out = 0;
284         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
285             out += ((C3P0PooledConnectionPool) ii.next()).getNumBusyConnections();
286         return out;
287     }
288
289     public synchronized int getNumConnectionsAllAuths() throws SQLException
290     {
291         int out = 0;
292         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
293             out += ((C3P0PooledConnectionPool) ii.next()).getNumConnections();
294         return out;
295     }
296
297     public synchronized int getNumUnclosedOrphanedConnectionsAllAuths() throws SQLException
298     {
299         int out = 0;
300         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
301             out += ((C3P0PooledConnectionPool) ii.next()).getNumUnclosedOrphanedConnections();
302         return out;
303     }
304
305     public synchronized int getStatementCacheNumStatementsAllUsers() throws SQLException
306     {
307         int out = 0;
308         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
309             out += ((C3P0PooledConnectionPool) ii.next()).getStatementCacheNumStatements();
310         return out;
311     }
312
313     public synchronized int getStatementCacheNumCheckedOutStatementsAllUsers() throws SQLException
314     {
315         int out = 0;
316         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
317             out += ((C3P0PooledConnectionPool) ii.next()).getStatementCacheNumCheckedOut();
318         return out;
319     }
320
321     public synchronized int getStatementCacheNumConnectionsWithCachedStatementsAllUsers() throws SQLException
322     {
323         int out = 0;
324         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
325             out += ((C3P0PooledConnectionPool) ii.next()).getStatementCacheNumConnectionsWithCachedStatements();
326         return out;
327     }
328
329     public synchronized void softResetAllAuths() throws SQLException
330     {
331         for (Iterator ii = authsToPools.values().iterator(); ii.hasNext(); )
332             ((C3P0PooledConnectionPool) ii.next()).reset();
333     }
334
335     public void close()
336     { this.close( true ); }
337
338     public synchronized void close( boolean close_outstanding_connections )
339     {
340         // System.err.println("close()ing " + this);
341
if (authsToPools != null)
342             poolsDestroy( close_outstanding_connections );
343     }
344
345     protected synchronized void finalize()
346     {
347         // System.err.println("finalizing... " + this);
348
this.close();
349     }
350
351     private Object JavaDoc getObject(String JavaDoc propName, String JavaDoc userName)
352     {
353         Object JavaDoc out = null;
354
355         if (userName != null)
356         {
357             //userOverrides are usually config file defined, unless rarely used forceUserOverrides is supplied!
358
Map specificUserOverrides = (Map) userOverrides.get( userName );
359             if (specificUserOverrides != null)
360                 out = specificUserOverrides.get( propName );
361         }
362
363         if (out == null && flatPropertyOverrides != null) //flatPropertyOverrides is a rarely used mechanism for forcing a config
364
out = flatPropertyOverrides.get( propName );
365
366         //if the ConnectionPoolDataSource has config parameter defined as a property use it
367
//(unless there was a user-specific or force override found above)
368
if (out == null)
369         {
370             try
371             {
372                 Method m = (Method) propNamesToReadMethods.get( propName );
373                 if (m != null)
374                 {
375                     Object JavaDoc readProp = m.invoke( cpds, null );
376                     if (readProp != null)
377                         out = readProp.toString();
378                 }
379             }
380             catch (Exception JavaDoc e)
381             {
382                 if (logger.isLoggable( MLevel.WARNING ))
383                     logger.log(MLevel.WARNING,
384                                     "An exception occurred while trying to read property '" + propName +
385                                     "' from ConnectionPoolDataSource: " + cpds +
386                                     ". Default config value will be used.",
387                                     e );
388             }
389         }
390
391         //if the ConnectionPoolDataSource DID NOT have config parameter defined as a property
392
//(and there was no user-specific or force override)
393
//use config-defined default
394
if (out == null)
395             out = C3P0Config.getUnspecifiedUserProperty( propName, null );
396
397         return out;
398     }
399
400     private String JavaDoc getString(String JavaDoc propName, String JavaDoc userName)
401     {
402         Object JavaDoc o = getObject( propName, userName);
403         return (o == null ? null : o.toString());
404     }
405
406     private int getInt(String JavaDoc propName, String JavaDoc userName) throws Exception JavaDoc
407     {
408         Object JavaDoc o = getObject( propName, userName);
409         if (o instanceof Integer JavaDoc)
410             return ((Integer JavaDoc) o).intValue();
411         else if (o instanceof String JavaDoc)
412             return Integer.parseInt( (String JavaDoc) o );
413         else
414             throw new Exception JavaDoc("Unexpected object found for putative int property '" + propName +"': " + o);
415     }
416
417     private boolean getBoolean(String JavaDoc propName, String JavaDoc userName) throws Exception JavaDoc
418     {
419         Object JavaDoc o = getObject( propName, userName);
420         if (o instanceof Boolean JavaDoc)
421             return ((Boolean JavaDoc) o).booleanValue();
422         else if (o instanceof String JavaDoc)
423             return BooleanUtils.parseBoolean( (String JavaDoc) o );
424         else
425             throw new Exception JavaDoc("Unexpected object found for putative boolean property '" + propName +"': " + o);
426     }
427
428     public String JavaDoc getAutomaticTestTable(String JavaDoc userName)
429     { return getString("automaticTestTable", userName ); }
430
431     public String JavaDoc getPreferredTestQuery(String JavaDoc userName)
432     { return getString("preferredTestQuery", userName ); }
433
434     private int getInitialPoolSize(String JavaDoc userName)
435     {
436         try
437         { return getInt("initialPoolSize", userName ); }
438         catch (Exception JavaDoc e)
439         {
440             if ( logger.isLoggable( MLevel.FINE ) )
441                 logger.log( MLevel.FINE, "Could not fetch int property", e);
442             return C3P0Defaults.initialPoolSize();
443         }
444     }
445
446     public int getMinPoolSize(String JavaDoc userName)
447     {
448         try
449         { return getInt("minPoolSize", userName ); }
450         catch (Exception JavaDoc e)
451         {
452             if ( logger.isLoggable( MLevel.FINE ) )
453                 logger.log( MLevel.FINE, "Could not fetch int property", e);
454             return C3P0Defaults.minPoolSize();
455         }
456     }
457
458     private int getMaxPoolSize(String JavaDoc userName)
459     {
460         try
461         { return getInt("maxPoolSize", userName ); }
462         catch (Exception JavaDoc e)
463         {
464             if ( logger.isLoggable( MLevel.FINE ) )
465                 logger.log( MLevel.FINE, "Could not fetch int property", e);
466             return C3P0Defaults.maxPoolSize();
467         }
468     }
469
470     private int getMaxStatements(String JavaDoc userName)
471     {
472         try
473         { return getInt("maxStatements", userName ); }
474         catch (Exception JavaDoc e)
475         {
476             if ( logger.isLoggable( MLevel.FINE ) )
477                 logger.log( MLevel.FINE, "Could not fetch int property", e);
478             return C3P0Defaults.maxStatements();
479         }
480     }
481
482     private int getMaxStatementsPerConnection(String JavaDoc userName)
483     {
484         try
485         { return getInt("maxStatementsPerConnection", userName ); }
486         catch (Exception JavaDoc e)
487         {
488             if ( logger.isLoggable( MLevel.FINE ) )
489                 logger.log( MLevel.FINE, "Could not fetch int property", e);
490             return C3P0Defaults.maxStatementsPerConnection();
491         }
492     }
493
494     private int getAcquireIncrement(String JavaDoc userName)
495     {
496         try
497         { return getInt("acquireIncrement", userName ); }
498         catch (Exception JavaDoc e)
499         {
500             if ( logger.isLoggable( MLevel.FINE ) )
501                 logger.log( MLevel.FINE, "Could not fetch int property", e);
502             return C3P0Defaults.acquireIncrement();
503         }
504     }
505
506     private int getAcquireRetryAttempts(String JavaDoc userName)
507     {
508         try
509         { return getInt("acquireRetryAttempts", userName ); }
510         catch (Exception JavaDoc e)
511         {
512             if ( logger.isLoggable( MLevel.FINE ) )
513                 logger.log( MLevel.FINE, "Could not fetch int property", e);
514             return C3P0Defaults.acquireRetryAttempts();
515         }
516     }
517
518     private int getAcquireRetryDelay(String JavaDoc userName)
519     {
520         try
521         { return getInt("acquireRetryDelay", userName ); }
522         catch (Exception JavaDoc e)
523         {
524             if ( logger.isLoggable( MLevel.FINE ) )
525                 logger.log( MLevel.FINE, "Could not fetch int property", e);
526             return C3P0Defaults.acquireRetryDelay();
527         }
528     }
529
530     private boolean getBreakAfterAcquireFailure(String JavaDoc userName)
531     {
532         try
533         { return getBoolean("breakAfterAcquireFailure", userName ); }
534         catch (Exception JavaDoc e)
535         {
536             if ( logger.isLoggable( MLevel.FINE ) )
537                 logger.log( MLevel.FINE, "Could not fetch boolean property", e);
538             return C3P0Defaults.breakAfterAcquireFailure();
539         }
540     }
541
542     private int getCheckoutTimeout(String JavaDoc userName)
543     {
544         try
545         { return getInt("checkoutTimeout", userName ); }
546         catch (Exception JavaDoc e)
547         {
548             if ( logger.isLoggable( MLevel.FINE ) )
549                 logger.log( MLevel.FINE, "Could not fetch int property", e);
550             return C3P0Defaults.checkoutTimeout();
551         }
552     }
553
554     private int getIdleConnectionTestPeriod(String JavaDoc userName)
555     {
556         try
557         { return getInt("idleConnectionTestPeriod", userName ); }
558         catch (Exception JavaDoc e)
559         {
560             if ( logger.isLoggable( MLevel.FINE ) )
561                 logger.log( MLevel.FINE, "Could not fetch int property", e);
562             return C3P0Defaults.idleConnectionTestPeriod();
563         }
564     }
565
566     private int getMaxIdleTime(String JavaDoc userName)
567     {
568         try
569         { return getInt("maxIdleTime", userName ); }
570         catch (Exception JavaDoc e)
571         {
572             if ( logger.isLoggable( MLevel.FINE ) )
573                 logger.log( MLevel.FINE, "Could not fetch int property", e);
574             return C3P0Defaults.maxIdleTime();
575         }
576     }
577
578     private int getUnreturnedConnectionTimeout(String JavaDoc userName)
579     {
580         try
581         { return getInt("unreturnedConnectionTimeout", userName ); }
582         catch (Exception JavaDoc e)
583         {
584             if ( logger.isLoggable( MLevel.FINE ) )
585                 logger.log( MLevel.FINE, "Could not fetch int property", e);
586             return C3P0Defaults.unreturnedConnectionTimeout();
587         }
588     }
589
590     private boolean getTestConnectionOnCheckout(String JavaDoc userName)
591     {
592         try
593         { return getBoolean("testConnectionOnCheckout", userName ); }
594         catch (Exception JavaDoc e)
595         {
596             if ( logger.isLoggable( MLevel.FINE ) )
597                 logger.log( MLevel.FINE, "Could not fetch boolean property", e);
598             return C3P0Defaults.testConnectionOnCheckout();
599         }
600     }
601
602     private boolean getTestConnectionOnCheckin(String JavaDoc userName)
603     {
604         try
605         { return getBoolean("testConnectionOnCheckin", userName ); }
606         catch (Exception JavaDoc e)
607         {
608             if ( logger.isLoggable( MLevel.FINE ) )
609                 logger.log( MLevel.FINE, "Could not fetch boolean property", e);
610             return C3P0Defaults.testConnectionOnCheckin();
611         }
612     }
613
614     private boolean getDebugUnreturnedConnectionStackTraces(String JavaDoc userName)
615     {
616         try
617         { return getBoolean("debugUnreturnedConnectionStackTraces", userName ); }
618         catch (Exception JavaDoc e)
619         {
620             if ( logger.isLoggable( MLevel.FINE ) )
621                 logger.log( MLevel.FINE, "Could not fetch boolean property", e);
622             return C3P0Defaults.debugUnreturnedConnectionStackTraces();
623         }
624     }
625
626     private String JavaDoc getConnectionTesterClassName(String JavaDoc userName)
627     { return getString("connectionTesterClassName", userName ); }
628
629     private ConnectionTester getConnectionTester(String JavaDoc userName)
630     { return C3P0Registry.getConnectionTester( getConnectionTesterClassName( userName ) ); }
631
632     private String JavaDoc getConnectionCustomizerClassName(String JavaDoc userName)
633     { return getString("connectionCustomizerClassName", userName ); }
634
635     private ConnectionCustomizer getConnectionCustomizer(String JavaDoc userName) throws SQLException
636     { return C3P0Registry.getConnectionCustomizer( getConnectionCustomizerClassName( userName ) ); }
637
638     private int getMaxIdleTimeExcessConnections(String JavaDoc userName)
639     {
640         try
641         { return getInt("maxIdleTimeExcessConnections", userName ); }
642         catch (Exception JavaDoc e)
643         {
644             if ( logger.isLoggable( MLevel.FINE ) )
645                 logger.log( MLevel.FINE, "Could not fetch int property", e);
646             return C3P0Defaults.maxIdleTimeExcessConnections();
647         }
648     }
649
650     private int getMaxAdministrativeTaskTime(String JavaDoc userName)
651     {
652         try
653         { return getInt("maxAdministrativeTaskTime", userName ); }
654         catch (Exception JavaDoc e)
655         {
656             if ( logger.isLoggable( MLevel.FINE ) )
657                 logger.log( MLevel.FINE, "Could not fetch int property", e);
658             return C3P0Defaults.maxAdministrativeTaskTime();
659         }
660     }
661
662     private int getMaxConnectionAge(String JavaDoc userName)
663     {
664         try
665         { return getInt("maxConnectionAge", userName ); }
666         catch (Exception JavaDoc e)
667         {
668             if ( logger.isLoggable( MLevel.FINE ) )
669                 logger.log( MLevel.FINE, "Could not fetch int property", e);
670             return C3P0Defaults.maxConnectionAge();
671         }
672     }
673
674     private int getPropertyCycle(String JavaDoc userName)
675     {
676         try
677         { return getInt("propertyCycle", userName ); }
678         catch (Exception JavaDoc e)
679         {
680             if ( logger.isLoggable( MLevel.FINE ) )
681                 logger.log( MLevel.FINE, "Could not fetch int property", e);
682             return C3P0Defaults.propertyCycle();
683         }
684     }
685
686
687     // called only from sync'ed methods
688
private C3P0PooledConnectionPool createPooledConnectionPool(DbAuth auth) throws SQLException
689     {
690         String JavaDoc userName = auth.getUser();
691         String JavaDoc automaticTestTable = getAutomaticTestTable( userName );
692         String JavaDoc realTestQuery;
693
694         if (automaticTestTable != null)
695         {
696             realTestQuery = initializeAutomaticTestTable( automaticTestTable, auth );
697             if (this.getPreferredTestQuery( userName ) != null)
698             {
699                 if ( logger.isLoggable( MLevel.WARNING ) )
700                 {
701                     logger.logp(MLevel.WARNING,
702                                     C3P0PooledConnectionPoolManager.class.getName(),
703                                     "createPooledConnectionPool",
704                                     "[c3p0] Both automaticTestTable and preferredTestQuery have been set! " +
705                                     "Using automaticTestTable, and ignoring preferredTestQuery. Real test query is ''{0}''.",
706                                     realTestQuery
707                     );
708                 }
709             }
710         }
711         else
712         {
713         // when there is an automaticTestTable to be constructed, we
714
// have little choice but to grab a Connection on initialization
715
// to ensure that the table exists before the pool tries to
716
// test Connections. in c3p0-0.9.1-pre10, i added the check below
717
// to grab and destroy a cxn even when we don't
718
// need one, to ensure that db access params are correct before
719
// we start up a pool. a user who frequently creates and destroys
720
// PooledDataSources complained about the extra initialization
721
// time. the main use of this test was to prevent superfluous
722
// bad pools from being intialized when JMX users type bad
723
// authentification information into a query method. This is
724
// now prevented in AbstractPoolBackedDataSource. Still, it is
725
// easy for clients to start pools uselessly by asking for
726
// Connections with bad authentification information. We adopt
727
// the compromise position of "trusting" the DataSource's default
728
// authentification info (as defined by defaultAuth), but ensuring
729
// that authentification succeeds via the check below when non-default
730
// authentification info is provided.
731

732         if (! defaultAuth.equals( auth ))
733         ensureFirstConnectionAcquisition( auth );
734
735             realTestQuery = this.getPreferredTestQuery( userName );
736         }
737
738         C3P0PooledConnectionPool out = new C3P0PooledConnectionPool( cpds,
739                         auth,
740                         this.getMinPoolSize( userName ),
741                         this.getMaxPoolSize( userName ),
742                         this.getInitialPoolSize( userName ),
743                         this.getAcquireIncrement( userName ),
744                         this.getAcquireRetryAttempts( userName ),
745                         this.getAcquireRetryDelay( userName ),
746                         this.getBreakAfterAcquireFailure( userName ),
747                         this.getCheckoutTimeout( userName ),
748                         this.getIdleConnectionTestPeriod( userName ),
749                         this.getMaxIdleTime( userName ),
750                         this.getMaxIdleTimeExcessConnections( userName ),
751                         this.getMaxConnectionAge( userName ),
752                         this.getPropertyCycle( userName ),
753                         this.getUnreturnedConnectionTimeout( userName ),
754                         this.getDebugUnreturnedConnectionStackTraces( userName ),
755                         this.getTestConnectionOnCheckout( userName ),
756                         this.getTestConnectionOnCheckin( userName ),
757                         this.getMaxStatements( userName ),
758                         this.getMaxStatementsPerConnection( userName ),
759                         this.getConnectionTester( userName ),
760                         this.getConnectionCustomizer( userName ),
761                         realTestQuery,
762                         rpfact,
763                         taskRunner,
764                         parentDataSourceIdentityToken );
765         return out;
766     }
767
768
769     // only called from sync'ed methods
770
private String JavaDoc initializeAutomaticTestTable(String JavaDoc automaticTestTable, DbAuth auth) throws SQLException
771     {
772         PooledConnection throwawayPooledConnection = auth.equals( defaultAuth ) ?
773                                                         cpds.getPooledConnection() :
774                                                         cpds.getPooledConnection(auth.getUser(), auth.getPassword());
775         Connection c = null;
776         PreparedStatement testStmt = null;
777         PreparedStatement createStmt = null;
778         ResultSet mdrs = null;
779         ResultSet rs = null;
780         boolean exists;
781         boolean has_rows;
782         String JavaDoc out;
783         try
784         {
785             c = throwawayPooledConnection.getConnection();
786
787             DatabaseMetaData dmd = c.getMetaData();
788             String JavaDoc q = dmd.getIdentifierQuoteString();
789             String JavaDoc quotedTableName = q + automaticTestTable + q;
790             out = "SELECT * FROM " + quotedTableName;
791             mdrs = dmd.getTables( null, null, automaticTestTable, new String JavaDoc[] {"TABLE"} );
792             exists = mdrs.next();
793
794             //System.err.println("Table " + automaticTestTable + " exists? " + exists);
795

796             if (exists)
797             {
798                 testStmt = c.prepareStatement( out );
799                 rs = testStmt.executeQuery();
800                 has_rows = rs.next();
801                 if (has_rows)
802                     throw new SQLException("automatic test table '" + automaticTestTable +
803                                     "' contains rows, and it should not! Please set this " +
804                                     "parameter to the name of a table c3p0 can create on its own, " +
805                     "that is not used elsewhere in the database!");
806             }
807             else
808             {
809                 String JavaDoc createSql = "CREATE TABLE " + quotedTableName + " ( a CHAR(1) )";
810                 try
811                 {
812                     createStmt = c.prepareStatement( createSql );
813                     createStmt.executeUpdate();
814                 }
815                 catch (SQLException e)
816                 {
817                     if (logger.isLoggable( MLevel.WARNING ))
818                         logger.log(MLevel.WARNING,
819                                         "An attempt to create an automatic test table failed. Create SQL: " +
820                                         createSql,
821                                         e );
822                     throw e;
823                 }
824             }
825             return out;
826         }
827         finally
828         {
829             ResultSetUtils.attemptClose( mdrs );
830             ResultSetUtils.attemptClose( rs );
831             StatementUtils.attemptClose( testStmt );
832             StatementUtils.attemptClose( createStmt );
833             ConnectionUtils.attemptClose( c );
834             try{ if (throwawayPooledConnection != null) throwawayPooledConnection.close(); }
835             catch ( Exception JavaDoc e )
836             {
837                 //e.printStackTrace();
838
logger.log(MLevel.WARNING, "A PooledConnection failed to close.", e);
839             }
840         }
841     }
842     
843     private void ensureFirstConnectionAcquisition(DbAuth auth) throws SQLException
844     {
845         PooledConnection throwawayPooledConnection = auth.equals( defaultAuth ) ?
846                                                         cpds.getPooledConnection() :
847                                                         cpds.getPooledConnection(auth.getUser(), auth.getPassword());
848         Connection c = null;
849         try
850         {
851             c = throwawayPooledConnection.getConnection();
852         }
853         finally
854         {
855             ConnectionUtils.attemptClose( c );
856             try{ if (throwawayPooledConnection != null) throwawayPooledConnection.close(); }
857             catch ( Exception JavaDoc e )
858             {
859                 //e.printStackTrace();
860
logger.log(MLevel.WARNING, "A PooledConnection failed to close.", e);
861             }
862         }
863     }
864 }
865
866
867
868
869
870 //public static find(ConnectionPoolDataSource cpds,
871
//DbAuth defaultAuth, //may be null
872
//int maxStatements,
873
//int minPoolSize,
874
//int maxPoolSize,
875
//int idleConnectionTestPeriod,
876
//int maxIdleTime,
877
//int acquireIncrement,
878
//boolean testConnectionOnCheckout,
879
//boolean autoCommitOnClose,
880
//boolean forceIgnoreUnresolvedTransactions,
881
//ConnectionTester connectionTester)
882
//{
883
//C3P0PooledConnectionPoolManager nascent = new C3P0PooledConnectionPoolManager( cpds,
884
//defaultAuth,
885
//maxStatements,
886
//minPoolSize,
887
//maxPoolSize,
888
//idleConnectionTestPeriod,
889
//maxIdleTime,
890
//acquireIncrement,
891
//testConnectionOnCheckout,
892
//autoCommitOnClose,
893
//forceIgnoreUnresolvedTransactions,
894
//connectionTester);
895
//C3P0PooledConnectionPoolManager out = (C3P0PooledConnectionPoolManager) coalescer.coalesce( nascent );
896
//if ( out == nascent ) //the new guy is the ONE
897
//out.poolInit();
898
//return out;
899
//}
900

901 //private C3P0PooledConnectionPoolManager(ConnectionPoolDataSource cpds,
902
//DbAuth defaultAuth, //may be null
903
//int maxStatements,
904
//int minPoolSize,
905
//int maxPoolSize,
906
//int idleConnectionTestPeriod,
907
//int maxIdleTime,
908
//int acquireIncrement,
909
//boolean testConnectionOnCheckout,
910
//boolean autoCommitOnClose,
911
//boolean forceIgnoreUnresolvedTransactions,
912
//ConnectionTester connectionTester)
913
//{
914
//this.cpds = cpds;
915
//this.defaultAuth = (defaultAuth == null ? C3P0ImplUtils.NULL_AUTH : defaultAuth);
916
//this.maxStatements = maxStatements;
917
//this.minPoolSize = minPoolSize;
918
//this.maxPoolSize = maxPoolSize;
919
//this.idleConnectionTestPeriod = idleConnectionTestPeriod;
920
//this.maxIdleTime = maxIdleTime;
921
//this.acquireIncrement = acquireIncrement;
922
//this.testConnectionOnCheckout = testConnectionOnCheckout;
923
//this.autoCommitOnClose = autoCommitOnClose;
924
//this.testConnectionOnCheckout = testConnectionOnCheckout;
925
//this.forceIgnoreUnresolvedTransactions = forceIgnoreUnresolvedTransactions;
926
//}
927

928 //private final static CoalesceChecker COALESCE_CHECKER = new CoalesceChecker()
929
//{
930
//// note that we expect all ConnectionTesters of a single class to be effectively
931
//// equivalent, since they are to be constructed via a no-arg ctor and no
932
//// extra initialization is performed. thus we only compare the classes of ConnectionTesters.
933
//public boolean checkCoalesce( Object a, Object b )
934
//{
935
//C3P0PooledConnectionPoolManager aa = (C3P0PooledConnectionPoolManager) a;
936
//C3P0PooledConnectionPoolManager bb = (C3P0PooledConnectionPoolManager) b;
937

938 //return
939
//aa.poolOwnerIdentityToken.equals( bb.poolOwnerIdentityToken ) &&
940
//(aa.preferredTestQuery == null ? (bb.preferredTestQuery == null ) : (aa.preferredTestQuery.equals( bb.preferredTestQuery ))) &&
941
//(aa.automaticTestTable == null ? (bb.automaticTestTable == null ) : (aa.automaticTestTable.equals( bb.automaticTestTable ))) &&
942
//aa.sourceCpdsIdentityToken.equals( bb.sourceCpdsIdentityToken ) &&
943
//aa.num_task_threads == bb.num_task_threads &&
944
//aa.maxStatements == bb.maxStatements &&
945
//aa.maxStatementsPerConnection == bb.maxStatementsPerConnection &&
946
//aa.minPoolSize == bb.minPoolSize &&
947
//aa.idleConnectionTestPeriod == bb.idleConnectionTestPeriod &&
948
//aa.maxIdleTime == bb.maxIdleTime &&
949
//aa.checkoutTimeout == bb.checkoutTimeout &&
950
//aa.acquireIncrement == bb.acquireIncrement &&
951
//aa.acquireRetryAttempts == bb.acquireRetryAttempts &&
952
//aa.acquireRetryDelay == bb.acquireRetryDelay &&
953
//aa.breakAfterAcquireFailure == bb.breakAfterAcquireFailure &&
954
//aa.testConnectionOnCheckout == bb.testConnectionOnCheckout &&
955
//aa.testConnectionOnCheckin == bb.testConnectionOnCheckin &&
956
//aa.autoCommitOnClose == bb.autoCommitOnClose &&
957
//aa.forceIgnoreUnresolvedTransactions == bb.forceIgnoreUnresolvedTransactions &&
958
//aa.defaultAuth.equals( bb.defaultAuth ) &&
959
//aa.connectionTester.getClass().equals( bb.connectionTester.getClass() );
960
//};
961

962 //public int coalesceHash( Object a )
963
//{
964
//C3P0PooledConnectionPoolManager aa = (C3P0PooledConnectionPoolManager) a;
965
//int out =
966
//aa.poolOwnerIdentityToken.hashCode() ^
967
//(aa.preferredTestQuery == null ? 0 : aa.preferredTestQuery.hashCode()) ^
968
//(aa.automaticTestTable == null ? 0 : aa.automaticTestTable.hashCode()) ^
969
//aa.sourceCpdsIdentityToken.hashCode() ^
970
//aa.num_task_threads ^
971
//aa.maxStatements ^
972
//aa.maxStatementsPerConnection ^
973
//aa.minPoolSize ^
974
//aa.idleConnectionTestPeriod ^
975
//aa.maxIdleTime ^
976
//aa.checkoutTimeout ^
977
//aa.acquireIncrement ^
978
//aa.acquireRetryAttempts ^
979
//aa.acquireRetryDelay ^
980
//(aa.testConnectionOnCheckout ? 1<<0 : 0) ^
981
//(aa.testConnectionOnCheckin ? 1<<1 : 0) ^
982
//(aa.autoCommitOnClose ? 1<<2 : 0) ^
983
//(aa.forceIgnoreUnresolvedTransactions ? 1<<3 : 0) ^
984
//(aa.breakAfterAcquireFailure ? 1<<4 : 0) ^
985
//aa.defaultAuth.hashCode() ^
986
//aa.connectionTester.getClass().hashCode();
987
////System.err.println("coalesceHash() --> " + out);
988
//return out;
989
//};
990
//};
991

992 //int maxStatements = PoolConfig.defaultMaxStatements();
993
//int maxStatementsPerConnection = PoolConfig.defaultMaxStatementsPerConnection();
994
//int minPoolSize = PoolConfig.defaultMinPoolSize();
995
//int maxPoolSize = PoolConfig.defaultMaxPoolSize();
996
//int idleConnectionTestPeriod = PoolConfig.defaultIdleConnectionTestPeriod();
997
//int maxIdleTime = PoolConfig.defaultMaxIdleTime();
998
//int checkoutTimeout = PoolConfig.defaultCheckoutTimeout();
999
//int acquireIncrement = PoolConfig.defaultAcquireIncrement();
1000
//int acquireRetryAttempts = PoolConfig.defaultAcquireRetryAttempts();
1001
//int acquireRetryDelay = PoolConfig.defaultAcquireRetryDelay();
1002
//boolean breakAfterAcquireFailure = PoolConfig.defaultBreakAfterAcquireFailure();
1003
//boolean testConnectionOnCheckout = PoolConfig.defaultTestConnectionOnCheckout();
1004
//boolean testConnectionOnCheckin = PoolConfig.defaultTestConnectionOnCheckin();
1005
//boolean autoCommitOnClose = PoolConfig.defaultAutoCommitOnClose();
1006
//boolean forceIgnoreUnresolvedTransactions = PoolConfig.defaultForceIgnoreUnresolvedTransactions();
1007
//String preferredTestQuery = PoolConfig.defaultPreferredTestQuery();
1008
//String automaticTestTable = PoolConfig.defaultAutomaticTestTable();
1009
//DbAuth defaultAuth = C3P0ImplUtils.NULL_AUTH;
1010
//ConnectionTester connectionTester = C3P0ImplUtils.defaultConnectionTester();;
1011

1012
1013//// we look for non-standard props user and
1014
//// password, available as read-only props on
1015
//// our implementation of ConnectionPoolDataSource.
1016
////
1017
//// If other implementations are used, the only
1018
//// hazard is the possibility that there will be
1019
//// two pools for the same real authorization credentials
1020
//// one for when the credentials are explicitly specified,
1021
//// and one for when the defaults are used.
1022

1023//this.defaultAuth = C3P0ImplUtils.findAuth( cpds );
1024

1025//BeanInfo bi = Introspector.getBeanInfo( cpds.getClass() );
1026
//PropertyDescriptor[] pds = bi.getPropertyDescriptors();
1027
//for (int i = 0, len = pds.length; i < len; ++i)
1028
//{
1029
//PropertyDescriptor pd = pds[i];
1030
//Class propCl = pd.getPropertyType();
1031
//String propName = pd.getName();
1032
//Method readMethod = pd.getReadMethod();
1033
//Object propVal;
1034
//if (propCl == int.class)
1035
//{
1036
//propVal = readMethod.invoke( cpds, C3P0ImplUtils.NOARGS );
1037
//int value = ((Integer) propVal).intValue();
1038
//if ("maxStatements".equals(propName))
1039
//this.maxStatements = value;
1040
//else if ("maxStatementsPerConnection".equals(propName))
1041
//this.maxStatementsPerConnection = value;
1042
//else if ("minPoolSize".equals(propName))
1043
//this.minPoolSize = value;
1044
//else if ("maxPoolSize".equals(propName))
1045
//this.maxPoolSize = value;
1046
//else if ("idleConnectionTestPeriod".equals(propName))
1047
//this.idleConnectionTestPeriod = value;
1048
//else if ("maxIdleTime".equals(propName))
1049
//this.maxIdleTime = value;
1050
//else if ("checkoutTimeout".equals(propName))
1051
//this.checkoutTimeout = value;
1052
//else if ("acquireIncrement".equals(propName))
1053
//this.acquireIncrement = value;
1054
//else if ("acquireRetryAttempts".equals(propName))
1055
//this.acquireRetryAttempts = value;
1056
//else if ("acquireRetryDelay".equals(propName))
1057
//this.acquireRetryDelay = value;
1058
//// System.err.println( propName + " -> " + propVal );
1059
//}
1060
//else if (propCl == String.class)
1061
//{
1062
//propVal = readMethod.invoke( cpds, C3P0ImplUtils.NOARGS );
1063
//String value = (String) propVal;
1064
//if ("connectionTesterClassName".equals(propName))
1065
//this.connectionTester =
1066
//(ConnectionTester) Class.forName( value ).newInstance();
1067
//else if ("preferredTestQuery".equals(propName))
1068
//this.preferredTestQuery = value;
1069
//else if ("automaticTestTable".equals(propName))
1070
//this.automaticTestTable = value;
1071
//// System.err.println( propName + " -> " + propVal );
1072
//}
1073
//else if (propCl == boolean.class)
1074
//{
1075
//propVal = readMethod.invoke( cpds, C3P0ImplUtils.NOARGS );
1076
//boolean value = ((Boolean) propVal).booleanValue();
1077
//if ("testConnectionOnCheckout".equals(propName))
1078
//this.testConnectionOnCheckout = value;
1079
//else if ("testConnectionOnCheckin".equals(propName))
1080
//this.testConnectionOnCheckin = value;
1081
//else if ("autoCommitOnClose".equals(propName))
1082
//this.autoCommitOnClose = value;
1083
//else if ("forceIgnoreUnresolvedTransactions".equals(propName))
1084
//this.forceIgnoreUnresolvedTransactions = value;
1085
//else if ("breakAfterAcquireFailure".equals(propName))
1086
//this.breakAfterAcquireFailure = value;
1087
//// System.err.println( propName + " -> " + propVal );
1088
//}
1089

1090//}
1091

1092
Popular Tags