KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.*;
27 import java.sql.*;
28 import javax.sql.*;
29 import com.mchange.v2.c3p0.*;
30 import com.mchange.v2.c3p0.stmt.*;
31 import com.mchange.v2.c3p0.util.*;
32 import com.mchange.v2.log.*;
33
34 import java.lang.reflect.Method JavaDoc;
35 import com.mchange.v2.lang.ObjectUtils;
36 import com.mchange.v2.sql.SqlUtils;
37
38 public final class NewPooledConnection extends AbstractC3P0PooledConnection{
39
40     private final static MLogger logger = MLog.getLogger( NewPooledConnection.class );
41
42     private final static SQLException NORMAL_CLOSE_PLACEHOLDER = new SQLException("This pooled Connection was explicitly close()ed by " +
43                                           "a client, not invalidated due to an error.");
44
45     //MT: thread-safe post-constructor constants
46
final Connection physicalConnection;
47     final ConnectionTester connectionTester;
48     final boolean autoCommitOnClose;
49     final boolean forceIgnoreUnresolvedTransactions;
50     final String JavaDoc preferredTestQuery;
51     final boolean supports_setHoldability;
52     final boolean supports_setReadOnly;
53     final boolean supports_setTypeMap;
54     final int dflt_txn_isolation;
55     final String JavaDoc dflt_catalog;
56     final int dflt_holdability;
57     final boolean dflt_readOnly;
58     final Map dflt_typeMap;
59     final ConnectionEventSupport ces;
60
61     //MT: protected by this' lock
62
GooGooStatementCache scache = null;
63     Throwable JavaDoc invalidatingException = null;
64     int connection_status = ConnectionTester.CONNECTION_IS_OKAY;
65     Set uncachedActiveStatements = new HashSet(); //cached statements are managed by the cache
66
Map resultSetsForStatements = new HashMap(); //for both cached and uncached statements
67
Set metaDataResultSets = new HashSet();
68     Set rawConnectionResultSets = null; //very rarely used, so we lazy initialize...
69
boolean connection_error_signaled = false;
70
71     //MT: thread-safe, volatile
72
volatile NewProxyConnection exposedProxy = null;
73     volatile boolean isolation_lvl_nondefault = false;
74     volatile boolean catalog_nondefault = false;
75     volatile boolean holdability_nondefault = false;
76     volatile boolean readOnly_nondefault = false;
77     volatile boolean typeMap_nondefault = false;
78
79     // public API
80
public NewPooledConnection(Connection con,
81                    ConnectionTester connectionTester,
82                    boolean autoCommitOnClose,
83                    boolean forceIgnoreUnresolvedTransactions,
84                    String JavaDoc preferredTestQuery,
85                    ConnectionCustomizer cc,
86                    String JavaDoc pdsIdt) throws SQLException
87     {
88     try
89         {
90         if (cc != null)
91             cc.onAcquire( con, pdsIdt );
92         }
93     catch (Exception JavaDoc e)
94         { throw SqlUtils.toSQLException(e); }
95
96     this.physicalConnection = con;
97     this.connectionTester = connectionTester;
98     this.autoCommitOnClose = autoCommitOnClose;
99     this.forceIgnoreUnresolvedTransactions = forceIgnoreUnresolvedTransactions;
100     this.preferredTestQuery = preferredTestQuery;
101     this.supports_setHoldability = C3P0ImplUtils.supportsMethod(con, "setHoldability", new Class JavaDoc[]{ Integer JavaDoc.class });
102     this.supports_setReadOnly = C3P0ImplUtils.supportsMethod(con, "setReadOnly", new Class JavaDoc[]{ Boolean JavaDoc.class });
103     this.supports_setTypeMap = C3P0ImplUtils.supportsMethod(con, "setTypeMap", new Class JavaDoc[]{ Map.class });
104     this.dflt_txn_isolation = con.getTransactionIsolation();
105     this.dflt_catalog = con.getCatalog();
106     this.dflt_holdability = (supports_setHoldability ? con.getHoldability() : ResultSet.CLOSE_CURSORS_AT_COMMIT);
107     this.dflt_readOnly = (supports_setReadOnly ? carefulCheckReadOnly(con) : false);
108     this.dflt_typeMap = (supports_setTypeMap && (carefulCheckTypeMap(con) == null) ? null : Collections.EMPTY_MAP);
109     this.ces = new ConnectionEventSupport(this);
110     }
111
112     private static boolean carefulCheckReadOnly(Connection con)
113     {
114     try { return con.isReadOnly(); }
115     catch (Exception JavaDoc e)
116         {
117         if (false)
118             {
119             if (logger.isLoggable(MLevel.FINER))
120                 logger.log(MLevel.FINER, con + " threw an Exception when we tried to check its default " +
121                        "read only state. This is not usually a problem! It just means the Connection " +
122                        "doesn't support the readOnly property, and c3p0 works around this.", e);
123             }
124         return false;
125         }
126     }
127
128     private static Map carefulCheckTypeMap(Connection con)
129     {
130     try { return con.getTypeMap(); }
131     catch (Exception JavaDoc e)
132         {
133         if (false)
134             {
135             if (logger.isLoggable(MLevel.FINER))
136                 logger.log(MLevel.FINER, con + " threw an Exception when we tried to check its default " +
137                        "type map. This is not usually a problem! It just means the Connection " +
138                        "doesn't support the typeMap property, and c3p0 works around this.", e);
139             }
140         return null;
141         }
142     }
143
144     public synchronized Connection getConnection() throws SQLException
145     {
146     try
147         {
148         //throw new SQLException("NOT IMPLEMENTED");
149
if ( exposedProxy == null )
150             {
151             exposedProxy = new NewProxyConnection( physicalConnection, this );
152             }
153         else
154             {
155 // System.err.println("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " +
156
// "it had already provided a client with a Connection that has not yet been " +
157
// "closed. This probably indicates a bug in the connection pool!!!");
158

159             if ( logger.isLoggable( MLevel.WARNING ) )
160                 logger.warning("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " +
161                        "it had already provided a client with a Connection that has not yet been " +
162                        "closed. This probably indicates a bug in the connection pool!!!");
163
164             }
165         return exposedProxy;
166         }
167     catch ( Exception JavaDoc e )
168         {
169         SQLException sqle = handleThrowable( e );
170         throw sqle;
171         }
172     }
173
174     public synchronized int getConnectionStatus()
175     { return connection_status; }
176
177     public synchronized void closeAll() throws SQLException
178     {
179     try
180         {
181         closeAllCachedStatements();
182         }
183     catch ( Exception JavaDoc e )
184         {
185         SQLException sqle = handleThrowable( e );
186         throw sqle;
187         }
188     }
189
190     public synchronized void close() throws SQLException
191     { close( null ); }
192
193     public void addConnectionEventListener(ConnectionEventListener cel)
194     { ces.addConnectionEventListener( cel ); }
195
196     public void removeConnectionEventListener(ConnectionEventListener cel)
197     { ces.removeConnectionEventListener( cel ); }
198
199     // api for C3P0PooledConnectionPool
200
public synchronized void initStatementCache( GooGooStatementCache scache )
201     { this.scache = scache; }
202
203     public synchronized GooGooStatementCache getStatementCache()
204     { return scache; }
205
206     //api for NewProxyConnections
207
void markNewTxnIsolation( int lvl ) //intentionally unsync'd -- isolation_lvl_nondefault is marked volatile
208
{
209     this.isolation_lvl_nondefault = (lvl != dflt_txn_isolation);
210     //System.err.println("isolation_lvl_nondefault: " + isolation_lvl_nondefault);
211
}
212
213     void markNewCatalog( String JavaDoc catalog ) //intentionally unsync'd -- catalog_nondefault is marked volatile
214
{
215     this.catalog_nondefault = ObjectUtils.eqOrBothNull(catalog, dflt_catalog);
216     }
217
218     void markNewHoldability( int holdability ) //intentionally unsync'd -- holdability_nondefault is marked volatile
219
{
220     this.holdability_nondefault = (holdability != dflt_holdability);
221     }
222
223     void markNewReadOnly( boolean readOnly ) //intentionally unsync'd -- readOnly_nondefault is marked volatile
224
{
225     this.readOnly_nondefault = (readOnly != dflt_readOnly);
226     }
227
228     void markNewTypeMap( Map typeMap ) //intentionally unsync'd -- typeMap_nondefault is marked volatile
229
{
230     this.typeMap_nondefault = (typeMap != dflt_typeMap);
231     }
232
233     synchronized Object JavaDoc checkoutStatement( Method JavaDoc stmtProducingMethod, Object JavaDoc[] args ) throws SQLException
234     { return scache.checkoutStatement( physicalConnection, stmtProducingMethod, args ); }
235
236     synchronized void checkinStatement( Statement stmt ) throws SQLException
237     {
238     cleanupStatementResultSets( stmt );
239     scache.checkinStatement( stmt );
240     }
241
242     synchronized void markActiveUncachedStatement( Statement stmt )
243     { uncachedActiveStatements.add( stmt ); }
244
245     synchronized void markInactiveUncachedStatement( Statement stmt )
246     {
247     cleanupStatementResultSets( stmt );
248     uncachedActiveStatements.remove( stmt );
249     }
250
251     synchronized void markActiveResultSetForStatement( Statement stmt, ResultSet rs )
252     {
253     Set rss = resultSets( stmt, true );
254     rss.add( rs );
255     }
256
257     synchronized void markInactiveResultSetForStatement( Statement stmt, ResultSet rs )
258     {
259     Set rss = resultSets( stmt, false );
260     if (rss == null)
261         {
262         if (logger.isLoggable( MLevel.FINE ))
263             logger.fine( "ResultSet " + rs + " was apparently closed after the Statement that created it had already been closed." );
264         }
265     else if ( ! rss.remove( rs ) )
266         throw new InternalError JavaDoc("Marking a ResultSet inactive that we did not know was opened!");
267     }
268
269     synchronized void markActiveRawConnectionResultSet( ResultSet rs )
270     {
271     if (rawConnectionResultSets == null)
272         rawConnectionResultSets = new HashSet();
273     rawConnectionResultSets.add( rs );
274     }
275
276     synchronized void markInactiveRawConnectionResultSet( ResultSet rs )
277     {
278     if ( ! rawConnectionResultSets.remove( rs ) )
279         throw new InternalError JavaDoc("Marking a raw Connection ResultSet inactive that we did not know was opened!");
280     }
281
282     synchronized void markActiveMetaDataResultSet( ResultSet rs )
283     { metaDataResultSets.add( rs ); }
284
285     synchronized void markInactiveMetaDataResultSet( ResultSet rs )
286     { metaDataResultSets.remove( rs ); }
287
288     synchronized void markClosedProxyConnection( NewProxyConnection npc, boolean txn_known_resolved )
289     {
290     try
291         {
292         if (npc != exposedProxy)
293             throw new InternalError JavaDoc("C3P0 Error: An exposed proxy asked a PooledConnection that was not its parents to clean up its resources!");
294         
295         List closeExceptions = new LinkedList();
296         cleanupResultSets( closeExceptions );
297         cleanupUncachedStatements( closeExceptions );
298         checkinAllCachedStatements( closeExceptions );
299         if ( closeExceptions.size() > 0 )
300             {
301 // System.err.println("[c3p0] The following Exceptions occurred while trying to clean up a Connection's stranded resources:");
302
if ( logger.isLoggable( MLevel.INFO ) )
303                 logger.info("[c3p0] The following Exceptions occurred while trying to clean up a Connection's stranded resources:");
304             for ( Iterator ii = closeExceptions.iterator(); ii.hasNext(); )
305                 {
306                 Throwable JavaDoc t = (Throwable JavaDoc) ii.next();
307 // System.err.print("[c3p0 -- conection resource close Exception]: ");
308
// t.printStackTrace();
309
if ( logger.isLoggable( MLevel.INFO ) )
310                     logger.log( MLevel.INFO, "[c3p0 -- conection resource close Exception]", t );
311                 }
312             }
313         reset( txn_known_resolved );
314         }
315     catch (SQLException e) //Connection failed to reset!
316
{
317         //e.printStackTrace();
318
if (Debug.DEBUG && logger.isLoggable( MLevel.FINE ))
319             logger.log(MLevel.FINE, "An exception occurred while reseting a closed Connection. Invalidating Connection.", e);
320
321         updateConnectionStatus( ConnectionTester.CONNECTION_IS_INVALID );
322         fireConnectionErrorOccurred( e );
323         }
324     finally
325         {
326         fireConnectionClosed();
327         }
328     }
329
330     private void reset( boolean txn_known_resolved ) throws SQLException
331     {
332     C3P0ImplUtils.resetTxnState( physicalConnection, forceIgnoreUnresolvedTransactions, autoCommitOnClose, txn_known_resolved );
333     if (isolation_lvl_nondefault)
334         {
335         physicalConnection.setTransactionIsolation( dflt_txn_isolation );
336         isolation_lvl_nondefault = false;
337         //System.err.println("reset txn isolation: " + dflt_txn_isolation);
338
}
339     if (catalog_nondefault)
340         {
341         physicalConnection.setCatalog( dflt_catalog );
342         catalog_nondefault = false;
343         }
344     if (holdability_nondefault) //this cannot go to true if holdability is not supported, so we don't have to check.
345
{
346         physicalConnection.setHoldability( dflt_holdability );
347         holdability_nondefault = false;
348         }
349     if (readOnly_nondefault)
350         {
351         physicalConnection.setReadOnly( dflt_readOnly );
352         readOnly_nondefault = false;
353         }
354     if (typeMap_nondefault)
355         {
356         physicalConnection.setTypeMap( dflt_typeMap );
357         typeMap_nondefault = false;
358         }
359     }
360
361     synchronized boolean isStatementCaching()
362     { return scache != null; }
363
364     synchronized SQLException handleThrowable( Throwable JavaDoc t )
365     {
366     if (Debug.DEBUG && Debug.TRACE == Debug.TRACE_MAX && logger.isLoggable( MLevel.FINER ))
367         logger.log( MLevel.FINER, this + " handling a throwable.", t );
368
369     SQLException sqle = SqlUtils.toSQLException( t );
370     //logger.warning("handle throwable ct: " + connectionTester);
371

372     int status;
373     if (connectionTester instanceof FullQueryConnectionTester)
374         status = ((FullQueryConnectionTester) connectionTester).statusOnException( physicalConnection, sqle, preferredTestQuery );
375     else
376         status = connectionTester.statusOnException( physicalConnection, sqle );
377
378     updateConnectionStatus( status );
379     if (status != ConnectionTester.CONNECTION_IS_OKAY)
380         {
381         if (Debug.DEBUG)
382             {
383 // System.err.print(this + " invalidated by Exception: ");
384
// t.printStackTrace();
385
if ( logger.isLoggable( MLevel.FINE ) )
386                 logger.log(MLevel.FINE, this + " invalidated by Exception.", t);
387             }
388
389         /*
390           ------
391           A users have complained that SQLExceptions ought not close their Connections underneath
392           them under any circumstance. Signalling the Connection error after updating the Connection
393           status should be sufficient from the pool's perspective, because the PooledConnection
394           will be marked broken by the pool and will be destroyed on checkin. I think actually
395           close()ing the Connection when it appears to be broken rather than waiting for users
396           to close() it themselves is overly aggressive, so I'm commenting the old behavior out.
397           The only potential downside to this approach is that users who do not close() in a finally
398           clause properly might see their close()es skipped by exceptions that previously would
399           have led to automatic close(). But relying on the automatic close() was never reliable
400           (since it only ever happened when c3p0 determined a Connection to be absolutely broken),
401           and is generally speaking a client error that c3p0 ought not be responsible for dealing
402           with. I think it's right to leave this out. -- swaldman 2004-12-09
403           ------
404
405         try { close( t ); }
406         catch (SQLException e)
407             {
408             e.printStackTrace();
409             throw new InternalError("C3P0 Error: NewPooledConnection's private close() method should " +
410                         "suppress any Exceptions if a throwable cause is provided.");
411             }
412         */

413
414         if (! connection_error_signaled)
415             {
416             ces.fireConnectionErrorOccurred( sqle );
417             connection_error_signaled = true;
418             }
419         else
420             {
421 // System.err.println("[c3p0] Warning: PooledConnection that has already signalled a Connection error is still in use!");
422
// System.err.println("[c3p0] Another error has occurred [ " + t + " ] which will not be reported to listeners!");
423
if ( logger.isLoggable( MLevel.WARNING ) )
424                 {
425                 logger.log(MLevel.WARNING, "[c3p0] A PooledConnection that has already signalled a Connection error is still in use!");
426                 logger.log(MLevel.WARNING, "[c3p0] Another error has occurred [ " + t + " ] which will not be reported to listeners!", t);
427                 }
428             }
429         }
430     return sqle;
431     }
432
433
434     // private methods
435

436     private void fireConnectionClosed()
437     {
438     exposedProxy = null;
439     ces.fireConnectionClosed();
440     }
441
442     private void fireConnectionErrorOccurred(SQLException error)
443     { ces.fireConnectionErrorOccurred( error ); }
444
445     // methods below must be called from sync'ed methods
446

447     /*
448      * If a throwable cause is provided, the PooledConnection is known to be broken (cause is an invalidating exception)
449      * and this method will not throw any exceptions, even if some resource closes fail.
450      *
451      * If cause is null, then we think the PooledConnection is healthy, and we will report (throw) an exception
452      * if resources unexpectedlay fail to close.
453      */

454     private void close( Throwable JavaDoc cause ) throws SQLException
455     {
456     if ( this.invalidatingException == null )
457         {
458         List closeExceptions = new LinkedList();
459         
460         // cleanup ResultSets
461
cleanupResultSets( closeExceptions );
462         
463         // cleanup uncached Statements
464
cleanupUncachedStatements( closeExceptions );
465         
466         // cleanup cached Statements
467
try
468             { closeAllCachedStatements(); }
469         catch ( SQLException e )
470             { closeExceptions.add(e); }
471         
472         // cleanup physicalConnection
473
try
474             { physicalConnection.close(); }
475         catch ( SQLException e )
476             {
477             if (logger.isLoggable( MLevel.FINER ))
478                 logger.log( MLevel.FINER, "Failed to close physical Connection: " + physicalConnection, e );
479
480             closeExceptions.add(e);
481             }
482         
483         // update our state to bad status and closed, and log any exceptions
484
if ( connection_status == ConnectionTester.CONNECTION_IS_OKAY )
485             connection_status = ConnectionTester.CONNECTION_IS_INVALID;
486         if ( cause == null )
487             {
488             this.invalidatingException = NORMAL_CLOSE_PLACEHOLDER;
489
490             if ( logger.isLoggable( MLevel.FINEST ) )
491                 logger.log( MLevel.FINEST, this + " closed by a client.", new Exception JavaDoc("DEBUG -- CLOSE BY CLIENT STACK TRACE") );
492
493             logCloseExceptions( null, closeExceptions );
494
495             if (closeExceptions.size() > 0)
496                 throw new SQLException("Some resources failed to close properly while closing " + this);
497             }
498         else
499             {
500             this.invalidatingException = cause;
501             if (Debug.TRACE >= Debug.TRACE_MED)
502                 logCloseExceptions( cause, closeExceptions );
503             else
504                 logCloseExceptions( cause, null );
505             }
506         }
507     }
508
509     private void cleanupResultSets( List closeExceptions )
510     {
511     cleanupAllStatementResultSets( closeExceptions );
512     cleanupUnclosedResultSetsSet( metaDataResultSets, closeExceptions );
513     if ( rawConnectionResultSets != null )
514         cleanupUnclosedResultSetsSet( rawConnectionResultSets, closeExceptions );
515     }
516
517     private void cleanupUnclosedResultSetsSet( Set rsSet, List closeExceptions )
518     {
519     for ( Iterator ii = rsSet.iterator(); ii.hasNext(); )
520         {
521         ResultSet rs = (ResultSet) ii.next();
522         try
523             { rs.close(); }
524         catch ( SQLException e )
525             { closeExceptions.add(e); }
526
527         ii.remove();
528         }
529     }
530
531     private void cleanupStatementResultSets( Statement stmt )
532     {
533     Set rss = resultSets( stmt, false );
534     if ( rss != null )
535         {
536         for ( Iterator ii = rss.iterator(); ii.hasNext(); )
537             {
538             try
539                 { ((ResultSet) ii.next()).close(); }
540             catch ( Exception JavaDoc e )
541                 {
542 // System.err.print("ResultSet close() failed: ");
543
// e.printStackTrace();
544
if ( logger.isLoggable( MLevel.INFO ) )
545                     logger.log(MLevel.INFO, "ResultSet close() failed.", e);
546                 }
547             }
548         }
549     resultSetsForStatements.remove( stmt );
550     }
551
552     private void cleanupAllStatementResultSets( List closeExceptions )
553     {
554     for ( Iterator ii = resultSetsForStatements.keySet().iterator(); ii.hasNext(); )
555         {
556         Object JavaDoc stmt = ii.next();
557         Set rss = (Set) resultSetsForStatements.get( stmt );
558         for (Iterator jj = rss.iterator(); jj.hasNext(); )
559             {
560             ResultSet rs = (ResultSet) jj.next();
561             try
562                 { rs.close(); }
563             catch ( SQLException e )
564                 { closeExceptions.add(e); }
565             }
566         }
567     resultSetsForStatements.clear();
568     }
569
570     private void cleanupUncachedStatements( List closeExceptions )
571     {
572     for ( Iterator ii = uncachedActiveStatements.iterator(); ii.hasNext(); )
573         {
574         Statement stmt = (Statement) ii.next();
575         try
576             { stmt.close(); }
577         catch ( SQLException e )
578             { closeExceptions.add(e); }
579
580         ii.remove();
581         }
582     }
583     
584     private void checkinAllCachedStatements( List closeExceptions )
585     {
586     try
587         {
588         if (scache != null)
589             scache.checkinAll( physicalConnection );
590         }
591     catch ( SQLException e )
592         { closeExceptions.add(e); }
593     }
594     
595     private void closeAllCachedStatements() throws SQLException
596     {
597     if (scache != null)
598         scache.closeAll( physicalConnection );
599     }
600
601     private void updateConnectionStatus(int status)
602     {
603     switch ( this.connection_status )
604         {
605         case ConnectionTester.DATABASE_IS_INVALID:
606         //can't get worse than this, do nothing.
607
break;
608         case ConnectionTester.CONNECTION_IS_INVALID:
609         if (status == ConnectionTester.DATABASE_IS_INVALID)
610             this.connection_status = status;
611         break;
612         case ConnectionTester.CONNECTION_IS_OKAY:
613         if (status != ConnectionTester.CONNECTION_IS_OKAY)
614             this.connection_status = status;
615         break;
616         default:
617         throw new InternalError JavaDoc(this + " -- Illegal Connection Status: " + this.connection_status);
618         }
619     }
620
621     private Set resultSets( Statement stmt, boolean create )
622     {
623     Set out = (Set) resultSetsForStatements.get( stmt );
624     if ( out == null && create )
625         {
626         out = new HashSet();
627         resultSetsForStatements.put( stmt, out );
628         }
629     return out;
630     }
631
632     //used by C3P0PooledConnectionPool
633
Connection getPhysicalConnection()
634     { return physicalConnection; }
635
636     // static utility functions
637
private static void logCloseExceptions( Throwable JavaDoc cause, Collection exceptions )
638     {
639     if ( logger.isLoggable( MLevel.INFO ) )
640         {
641         if (cause != null)
642             {
643             // System.err.println("[c3p0] A PooledConnection died due to the following error!");
644
// cause.printStackTrace();
645
logger.log(MLevel.INFO, "[c3p0] A PooledConnection died due to the following error!", cause);
646             }
647         if ( exceptions != null && exceptions.size() > 0)
648             {
649             if ( cause == null )
650                 logger.info("[c3p0] Exceptions occurred while trying to close a PooledConnection's resources normally.");
651             //System.err.println("[c3p0] The following Exceptions occurred while trying to close a PooledConnection's resources normally.");
652
else
653                 logger.info("[c3p0] Exceptions occurred while trying to close a Broken PooledConnection.");
654             //System.err.println("[c3p0] The following Exceptions occurred while trying to close a broken PooledConnection.");
655
for ( Iterator ii = exceptions.iterator(); ii.hasNext(); )
656                 {
657                 Throwable JavaDoc t = (Throwable JavaDoc) ii.next();
658                 // System.err.print("[c3p0 -- close Exception]: ");
659
// t.printStackTrace();
660
logger.log(MLevel.INFO, "[c3p0] NewPooledConnection close Exception.", t);
661                 }
662             }
663         }
664     }
665 }
666
Popular Tags