KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > resource > ConnectionManagerImpl


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: ConnectionManagerImpl.java,v 1.52 2005/07/22 11:34:59 durieuxp Exp $
23  * --------------------------------------------------------------------------
24  */

25
26
27 package org.objectweb.jonas.resource;
28
29 import java.io.PrintWriter JavaDoc;
30 import java.sql.Connection JavaDoc;
31 import java.sql.PreparedStatement JavaDoc;
32 import java.sql.ResultSet JavaDoc;
33 import java.sql.SQLException JavaDoc;
34 import java.util.Enumeration JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.Hashtable JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Properties JavaDoc;
39 import java.util.Set JavaDoc;
40 import java.util.Vector JavaDoc;
41
42 import javax.naming.Context JavaDoc;
43 import javax.naming.NamingException JavaDoc;
44 import javax.resource.ResourceException JavaDoc;
45 import javax.resource.spi.ConnectionEvent JavaDoc;
46 import javax.resource.spi.ConnectionEventListener JavaDoc;
47 import javax.resource.spi.ConnectionManager JavaDoc;
48 import javax.resource.spi.ConnectionRequestInfo JavaDoc;
49 import javax.resource.spi.ManagedConnection JavaDoc;
50 import javax.resource.spi.ManagedConnectionFactory JavaDoc;
51 import javax.resource.spi.ResourceAllocationException JavaDoc;
52 import javax.resource.spi.ValidatingManagedConnectionFactory JavaDoc;
53 import javax.security.auth.Subject JavaDoc;
54 import javax.transaction.RollbackException JavaDoc;
55 import javax.transaction.Transaction JavaDoc;
56 import javax.transaction.xa.XAResource JavaDoc;
57
58 import org.objectweb.jonas.resource.pool.api.Pool;
59 import org.objectweb.jonas.resource.pool.api.PoolMatchFactory;
60 import org.objectweb.jonas.resource.pool.lib.HArrayPool;
61 import org.objectweb.jotm.Current;
62 import org.objectweb.jotm.TransactionResourceManager;
63 import org.objectweb.transaction.jta.ResourceManagerEventListener;
64 import org.objectweb.transaction.jta.TransactionManager;
65 import org.objectweb.util.monolog.api.BasicLevel;
66 import org.objectweb.util.monolog.api.Logger;
67 import org.objectweb.util.monolog.api.LoggerFactory;
68 import org.objectweb.util.monolog.wrapper.printwriter.LoggerImpl;
69
70 /**
71  * Description of the ConnectionManagerImpl
72  *
73  *@author chassand
74  *created 15 novembre 2001
75  */

76 public class ConnectionManagerImpl implements ConnectionEventListener JavaDoc, ConnectionManager JavaDoc,
77                                               PoolMatchFactory, SQLManager,
78                                               TransactionResourceManager {
79
80     /**
81      * Main logger
82      */

83     protected static Logger trace = null;
84     /**
85      * Pool infomation logger
86      */

87     protected static Logger poolTrace = null;
88
89     /**
90      * Used by the server to register connections when no
91      * transactionnal context exists
92      */

93     protected ResourceManagerEventListener rmel = null;
94
95     /**
96      * Holds the resource bundle name
97      */

98     private String JavaDoc resourceBundleName = null;
99
100     /**
101      * The transaction manager in server
102      */

103     protected TransactionManager tm;
104
105     /**
106      * This hashtable allows to find the list of connection handle associated to a
107      * ManagedConnection
108      */

109     protected Hashtable JavaDoc mc2mci = null;
110
111     /**
112      * The max pool size of ManagedConnection. The default value is -1.
113      */

114     private int mcMaxPoolSize = -1;
115
116     /**
117      * The min pool size of ManagedConnection. The default value is 0
118      */

119     private int mcMinPoolSize = 0;
120
121     /**
122      * The ManagedConnectionFactory instance which represents the resource
123      * adapter.
124      */

125     private ManagedConnectionFactory JavaDoc mcf;
126     /**
127      * The ValidatingManagedConnectionFactory instance which represents the resource
128      * adapter.
129      */

130     private ValidatingManagedConnectionFactory JavaDoc vmcf = null;
131
132     /**
133      * The pool of ManagedConnections associated to a ManagedConnectionFactory
134      */

135     protected Pool poolMCs = null;
136
137     /**
138      * The list of used ManagedConnections key = transaction reference value =
139      * MCInfo
140      */

141     protected Hashtable JavaDoc usedMCs = null;
142
143     /**
144      * The default max pool size of pstmts per ManagedConnection.
145      */

146     static final int MAX_PSTMT_SIZE = 10;
147
148     /**
149      * PrepareStatement cache max pool size
150      */

151     private int maxPstmtPoolSize = MAX_PSTMT_SIZE;
152
153     /**
154      * JDBC connection level value
155      */

156     private int jdbcConnLevel = 0;
157     /**
158      * JDBC connection level value
159      */

160     private String JavaDoc jdbcConnTestStmt = "";
161
162     /**
163      * The list of managedConnection used without transaction
164      */

165     protected Vector JavaDoc mcs = new Vector JavaDoc();
166
167     /**
168      * The list of Synchronisation instance managed in this ConnectionManager
169      */

170     protected Vector JavaDoc synchros = new Vector JavaDoc();
171
172     /**
173      * This is a cache to the last instance of ResourceSpec used by the
174      * ConnectionManager. Indeed this instance is always the same.
175      */

176     private ResourceSpec rs = null;
177
178     /**
179      * The holds the transaction support level for the associated RAR file
180      */

181     private String JavaDoc transSupport = null;
182
183     /**
184      * This constant is used in the by the init method
185      */

186     public final static String JavaDoc RESOURCE_BUNDLE_NAME = "resourceBundleName";
187     /**
188      * This constant is used in the by the init method
189      */

190     public final static String JavaDoc LOGGER = "org.objectweb.util.monolog.logger";
191     /**
192      * This constant is used in the by the init method
193      */

194     public final static String JavaDoc POOL_LOGGER = "org.objectweb.util.monolog.logger_pool";
195     /**
196      * This constant is used in the by the init method
197      */

198     public final static String JavaDoc LOGGER_FACTORY = "org.objectweb.util.monolog.loggerFactory";
199     /**
200      * This constant is used in the by the init method
201      */

202     public final static String JavaDoc TRANSACTION_MANAGER = "transactionManager";
203     /**
204      * This constant is used in the by the init method
205      */

206     public final static String JavaDoc RESOURCE_MANAGER_EVENT_LISTENER = "resourceManagerEventListener";
207     /**
208      * This constant is used in the by the init method
209      */

210     public final static String JavaDoc RESOURCE_ADAPTER = "resourceAdapter";
211     /**
212      * This constant is used in the by the init method
213      */

214     public final static String JavaDoc PRINT_WRITER = "printWriter";
215
216     /*
217      * These constants define the different transaction support values
218      */

219     /**
220      * Rar doesn't support transactions
221      */

222     public final static String JavaDoc NO_TRANS_SUPPORT = "NoTransaction";
223     /**
224      * Rar supports local transactions
225      */

226     public final static String JavaDoc LOCAL_TRANS_SUPPORT = "LocalTransaction";
227     /**
228      * Rar supports XA transactions
229      */

230     public final static String JavaDoc XA_TRANS_SUPPORT = "XATransaction";
231
232     /**
233      * Constants to determine which PreparedStatement types to call
234      *
235      */

236     public final static int PSWRAP_1 = 1;
237     public final static int PSWRAP_2 = 2;
238     public final static int PSWRAP_3 = 3;
239     public final static int PSWRAP_4 = 4;
240     public final static int PSWRAP_5 = 5;
241
242     // JOTM variables
243
/**
244      * ManagedConnection used with JOTM recovery
245      */

246     private ManagedConnection JavaDoc jotmMc = null;
247     /**
248      * XAResource used with JOTM recovery
249      */

250     private XAResource JavaDoc jotmXar = null;
251     /**
252      * XA Name used with JOTM recovery
253      */

254     private String JavaDoc xaName = null;
255
256     /**
257      * Debug is enabled ?
258      */

259     private boolean isEnabledDebug = false;
260
261
262     /**
263      * ConnectionManagerImpl constructor
264      * @param transSupport String defining level of support needed
265      */

266     public ConnectionManagerImpl(String JavaDoc transSupport) {
267         if (transSupport.length() == 0) {
268             transSupport = NO_TRANS_SUPPORT;
269         } else {
270             this.transSupport = transSupport;
271         }
272     }
273
274     /**
275      * Setters method to initialize the ConnectionManager The logger instance
276      * where events are logged
277      *
278      *@param l The new Logger value
279      */

280     public void setLogger(Logger l) {
281         trace = l;
282         isEnabledDebug = trace.isLoggable(BasicLevel.DEBUG);
283     }
284
285
286     /**
287      * Setters method to initialize the ConnectionManager A logger factory to
288      * obtain a logger
289      *
290      *@param lf The new LoggerFactory value
291      */

292     public void setLoggerFactory(LoggerFactory lf) {
293         trace = lf.getLogger("org.objectweb.resource.server");
294         isEnabledDebug = trace.isLoggable(BasicLevel.DEBUG);
295     }
296
297
298     /**
299      * Setters method to initialize the ConnectionManager The printwriter where
300      * event are logged
301      *
302      *@param pw The new PrintWriter value
303      */

304     public void setPrintWriter(PrintWriter JavaDoc pw) {
305         trace = new LoggerImpl(pw);
306     }
307
308
309     /**
310      * Setters method to initialize the ConnectionManager The logger instance
311      * where events are logged
312      *
313      *@param rmel The new ResourceManagerEventListener value
314      */

315     public void setResourceManagerEventListener(
316             ResourceManagerEventListener rmel) {
317         this.rmel = rmel;
318     }
319
320
321     /**
322      * Setters method to initialize the ConnectionManager The Transaction manager
323      * linked to this resource managed
324      *
325      *@param tm TransactionManager value
326      */

327     public void setTransactionManager(TransactionManager tm) {
328         this.tm = tm;
329     }
330
331
332     /**
333      * Setters method to initialize the ConnectionManager The
334      * managedConnectionFactory instance of the resource which must be managed by
335      * this connectionManager
336      *
337      *@param tmcf The new ResourceAdapter value
338      *@exception Exception Description of Exception
339      */

340     public void setResourceAdapter(ManagedConnectionFactory JavaDoc tmcf)
341             throws Exception JavaDoc {
342         setResourceAdapter(tmcf, new ConnectionManagerPoolParams());
343     }
344
345     /**
346      * Setters method to initialize the ConnectionManager The
347      * managedConnectionFactory instance of the resource which must be maneged by
348      * this connectionManager
349      *
350      *@param tmcf The ManagedConnectionFactory object
351      *@param cmpp The pool parameters
352      *@exception Exception Description of Exception
353      */

354     public void setResourceAdapter(ManagedConnectionFactory JavaDoc tmcf,
355                                    ConnectionManagerPoolParams cmpp)
356             throws Exception JavaDoc {
357
358         // set the max/min pool values
359
if (cmpp.getPoolMax() != 0) {
360             mcMaxPoolSize = cmpp.getPoolMax();
361         }
362         if (cmpp.getPoolMin() > 0) {
363             mcMinPoolSize = cmpp.getPoolMin();
364         }
365
366         // set the jdbc connection info
367
jdbcConnLevel = cmpp.getJdbcConnLevel();
368         jdbcConnTestStmt = cmpp.getJdbcConnTestStmt();
369
370         mcf = tmcf;
371         if (mcf instanceof ValidatingManagedConnectionFactory JavaDoc) {
372             vmcf = (ValidatingManagedConnectionFactory JavaDoc) mcf;
373         }
374
375         poolMCs = new HArrayPool(poolTrace);
376         poolMCs.setMatchFactory(this);
377         poolMCs.setMaxSize(mcMaxPoolSize);
378         poolMCs.setMinSize(mcMinPoolSize);
379         poolMCs.setInitSize(cmpp.getPoolInit());
380
381         if (cmpp.getPoolMaxAge() > 0) {
382             int min = (int) (cmpp.getPoolMaxAge() / 60);
383             poolMCs.setMaxAge(min);
384         } else {
385             poolMCs.setMaxAge(cmpp.getPoolMaxAgeMinutes());
386         }
387
388         if (cmpp.getPoolMaxOpentime() > 0) {
389             poolMCs.setMaxOpentime(cmpp.getPoolMaxOpentime());
390         }
391         poolMCs.setMaxWaiters(cmpp.getPoolMaxWaiters());
392         if (cmpp.getPoolMaxWaittime() > 0) {
393             poolMCs.setMaxWaitTime(cmpp.getPoolMaxWaittime());
394         }
395
396         poolMCs.startMonitor();
397         poolMCs.setSamplingPeriod(cmpp.getPoolSamplingPeriod());
398         maxPstmtPoolSize = cmpp.getPstmtMax();
399
400         usedMCs = new Hashtable JavaDoc();
401         rs = new ResourceSpec(null, null);
402
403         if (isEnabledDebug) {
404             trace.log(BasicLevel.DEBUG, "");
405         }
406     }
407
408
409     /**
410      * This method permits to initialize the ConnectionManager with the following
411      * parameter: RESOURCE_BUNDLE_NAME: The name of the resource bundle in order
412      * to internationalize the logging LOGGER: The logger instance where events
413      * are logged LOGGER_FACTORY: A logger factory to obtain a logger
414      * PRINT_WRITER: The printwriter where event are logged TRANSACTION_MANAGER:
415      * The Transaction manager linked to this resource manager
416      * RESOURCE_MANAGER_EVENT_LISTENER: The resource manage event listener which
417      * subscribed to later connection enlistement. RESOURCE_ADAPTER: The
418      * managedConnectionFactory instance of the resource which must be maneged by
419      * this connectionManager
420      *
421      *@param ctx Description of Parameter
422      *@exception Exception Description of Exception
423      */

424     public void init(Context JavaDoc ctx) throws Exception JavaDoc {
425         mc2mci = new Hashtable JavaDoc();
426
427         // Get the resource bundle name to internationalise the log
428
// Optional
429
String JavaDoc resourceBundleName = null;
430         try {
431             resourceBundleName = (String JavaDoc) ctx.lookup(RESOURCE_BUNDLE_NAME);
432         } catch (NamingException JavaDoc e) {
433         }
434
435         // Get the logger or the logger factory or the printwriter
436
try {
437             trace = (Logger) ctx.lookup(LOGGER);
438             poolTrace = (Logger) ctx.lookup(POOL_LOGGER);
439         } catch (NamingException JavaDoc e) {
440         }
441
442         if (trace == null) {
443             try {
444                 setLoggerFactory((LoggerFactory) ctx.lookup(LOGGER_FACTORY));
445             } catch (NamingException JavaDoc e2) {
446             }
447         }
448         if (trace == null) {
449             PrintWriter JavaDoc pw = null;
450             try {
451                 pw = (PrintWriter JavaDoc) ctx.lookup(PRINT_WRITER);
452             } catch (NamingException JavaDoc e3) {
453             }
454             setPrintWriter(pw);
455         }
456
457         if (!transSupport.equalsIgnoreCase(NO_TRANS_SUPPORT)) {
458             // Get the transaction manager
459
tm = (TransactionManager) ctx.lookup(TRANSACTION_MANAGER);
460         }
461
462         // Get the set of connection
463
try {
464             rmel = (ResourceManagerEventListener)
465                     ctx.lookup(RESOURCE_MANAGER_EVENT_LISTENER);
466         } catch (NamingException JavaDoc ne) {
467         }
468
469         // Get the managedConnectionFactory instance which represents the resource
470
// adapter
471
try {
472             setResourceAdapter(
473                     (ManagedConnectionFactory JavaDoc) ctx.lookup(RESOURCE_ADAPTER));
474         } catch (NamingException JavaDoc ne) {
475         }
476     }
477
478
479     /**
480      * Description of the Method
481      *
482      *@exception ResourceException Description of Exception
483      */

484     public void cleanResourceAdapter() throws ResourceException JavaDoc {
485         // Delete the PreparedStatements
486
PreparedStatementWrapper pw = null;
487         while (mcs != null && mcs.size() > 0) {
488             MCInfo mci = (MCInfo) mcs.remove(0);
489             mci.usedCs.clear();
490             synchronized (mci.pStmts) {
491                 // Remove the PreparedStatements on the MC
492
while (mci.pStmts != null && mci.pStmts.size() > 0) {
493                     pw = (PreparedStatementWrapper) mci.pStmts.remove(0);
494                     try {
495                         pw.destroy();
496                     } catch (Exception JavaDoc ex) {
497                     }
498                 }
499             }
500             try {
501                 mc2mci.remove(mci.mc);
502                 mci.mc.destroy();
503             } catch (Exception JavaDoc ex) {
504             }
505         }
506         if (usedMCs != null) {
507             for (Enumeration JavaDoc en = usedMCs.keys(); en.hasMoreElements();) {
508                 Transaction JavaDoc tx = (Transaction JavaDoc) en.nextElement();
509                 MCInfo mci = (MCInfo) usedMCs.get(tx);
510                 if (mci == null) {
511                     continue;
512                 }
513                 if (mci.rmeCalled) {
514                     mci.rme.isValid = false;
515                     rmel.connectionClosed(mci.rme);
516                     mci.rmeCalled = false;
517                 }
518                 mci.usedCs.clear();
519                 // Remove the PreparedStatements on the MC
520
synchronized (mci.pStmts) {
521                     while (mci.pStmts != null && mci.pStmts.size() > 0) {
522                         pw = (PreparedStatementWrapper) mci.pStmts.remove(0);
523                         try {
524                             pw.destroy();
525                         } catch (Exception JavaDoc ex) {
526                         }
527                     }
528                 }
529                 try {
530                     mc2mci.remove(mci.mc);
531                     mci.mc.destroy();
532                 } catch (Exception JavaDoc ex) {
533                 }
534             }
535         }
536         while (synchros != null && synchros.size() > 0) {
537             MCInfo mci = (MCInfo) synchros.remove(0);
538             mci.usedCs.clear();
539             // Remove the PreparedStatements on the MC
540
synchronized (mci.pStmts) {
541                 while (mci.pStmts != null && mci.pStmts.size() > 0) {
542                     pw = (PreparedStatementWrapper) mci.pStmts.remove(0);
543                     try {
544                         pw.destroy();
545                     } catch (Exception JavaDoc ex) {
546                     }
547                 }
548             }
549             try {
550                 mc2mci.remove(mci.mc);
551                 mci.mc.destroy();
552             } catch (Exception JavaDoc ex) {
553             }
554         }
555     }
556
557
558     /**
559      *
560      * The method allocateConnection gets called by the resource adapter's
561      * connection factory instance.
562      *
563      * @see javax.resource.cci.ConnectionManager
564      */

565     public Object JavaDoc allocateConnection(ManagedConnectionFactory JavaDoc pMcf, ConnectionRequestInfo JavaDoc cxRequestInfo)
566             throws ResourceException JavaDoc {
567
568         MCInfo mci = null;
569         Transaction JavaDoc currentTx = null;
570         Object JavaDoc connection = null;
571         int retries = 0;
572         Subject JavaDoc subject = null;
573
574         while (connection == null && retries < 20) {
575             if (mcf != pMcf) {
576                 throw new ResourceException JavaDoc(
577                         "This ConnectionManager doesn't manage this RA:" + mcf);
578             }
579
580             currentTx = null;
581             try {
582                 if (tm != null) {
583                     currentTx = tm.getTransaction();
584                 }
585             } catch (Exception JavaDoc e) {
586                 trace.log(BasicLevel.ERROR,
587                         "Impossible to get the current transaction", e,
588                         "ConnectionManagerImpl", "allocateConnection");
589             }
590
591             //if there is a transaction check if a MC is already associated
592
mci = (currentTx == null ? null : (MCInfo) usedMCs.get(currentTx));
593             if (mci != null) {
594                 if (mci.mc != null) {
595                     // There are connections, try to match with the
596
// ManagedConnectionFactory
597
if (isEnabledDebug) {
598                         trace.log(BasicLevel.DEBUG, "MC (" + mci.mc + ") associated to the current Tx (" + currentTx + ") found");
599                     }
600                     Set JavaDoc s = new HashSet JavaDoc();
601                     s.add(mci.mc);
602                     if (mci.mc != mcf.matchManagedConnections(s, null, cxRequestInfo)) {
603                         throw new ResourceException JavaDoc(
604                                 "ConnectionManagerImpl.allocateConnection: illegal state : no mc is matched by mcf");
605                     }
606                     if (isEnabledDebug) {
607                         trace.log(BasicLevel.DEBUG, "XA Resource " + mci.getXAResource()
608                                                 + " is already enlisted in Tx:" + mci.ctx);
609                     }
610                 } else {
611                     // This connection occurred an error before
612
trace.log(BasicLevel.INFO, "remnant of an old failed connection");
613                     mci.ctx = null;
614                     mci = null;
615                     usedMCs.remove(currentTx);
616                 }
617             }
618
619             if (mci == null) {
620                 // No managed connection found => get a free ManagedConnection
621
// from the right pool
622

623                 //ri.rs.subject = null; // Never set => already at null
624
rs.cxRequestInfo = cxRequestInfo;
625                 if (subject == null && cxRequestInfo != null) {
626                     // Create a subject to pass on
627
}
628                 try {
629                     ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) poolMCs.getResource(rs);
630                     if (mc == null) {
631                         throw new ResourceException JavaDoc("ConnectionManagerImpl.allocateConnection: cannot allocate a ManagedConnection");
632                     }
633                     mci = (MCInfo) mc2mci.get(mc);
634                     if (mci == null) {
635                         mci = new MCInfo(mc);
636                         mc2mci.put(mc, mci);
637                     }
638                     if (isEnabledDebug) {
639                         trace.log(BasicLevel.DEBUG, "get a MC from the ra pool, mc=" + mci.mc);
640                     }
641                     if (transSupport.equalsIgnoreCase(LOCAL_TRANS_SUPPORT)) {
642                         if (mci.lw == null) {
643                             mci.lw = new LocalXAWrapper(mci.mc.getLocalTransaction(), trace);
644                         }
645                     } else if (mci.lw != null) {
646                         mci.lw = null;
647                     }
648                     if (!mci.connectionEventListener) {
649                         mci.mc.addConnectionEventListener(this);
650                         mci.connectionEventListener = true;
651                     }
652                     mci.synchro = null;
653                     // If a global transaction is already started then enlist the
654
// ManagedConnection instance
655
if (currentTx != null) {
656                         if (isEnabledDebug) {
657                             trace.log(BasicLevel.DEBUG, "Enlist the XA Resource "
658                                                     + mci.getXAResource() + " in Tx:"
659                                                     + currentTx);
660                         }
661                         currentTx.enlistResource(mci.getXAResource());
662                         usedMCs.put(currentTx, mci);
663                         mci.ctx = currentTx;
664                     } else {
665                         // There are not Transaction at the moment but the user can
666
// start a transaction after the getConnection call.
667
mci.ctx = null;
668                         // must be clean
669
mcs.add(mci);
670                         // NoTransaction is specified, so don't register the MC
671
if (!transSupport.equalsIgnoreCase(NO_TRANS_SUPPORT)) {
672                             mci.rme = new RMEImpl(mci, trace);
673                             if (isEnabledDebug) {
674                                 trace.log(BasicLevel.DEBUG, "Register the managed connection (no tx)");
675                             }
676                             // Always put in list, fix bug on connection late enlistment
677
if (!mci.rmeCalled) {
678                                 mci.rme.isValid = true;
679                                 rmel.connectionOpened(mci.rme);
680                                 mci.rmeCalled = true;
681                             }
682                         }
683                     }
684                 } catch (ResourceException JavaDoc re) {
685                     trace.log(BasicLevel.ERROR, re.getMessage(), re);
686                     throw re;
687                 } catch (Exception JavaDoc e) {
688                     String JavaDoc err = "Error related allocation of ManagedConnection";
689                     trace.log(BasicLevel.ERROR, err, e);
690                     throw new ResourceException JavaDoc(err, e);
691                 }
692
693             }
694
695             //Fetch a free Connection from the ManagedConnection
696
connection = mci.mc.getConnection(null, cxRequestInfo);
697             // Want to add the non-wrapped Connection object
698
mci.usedCs.add(connection);
699             if (connection instanceof java.sql.Connection JavaDoc) {
700                 try {
701                     // Need a wrapper for non JOnAS jdbc ConnectionImpl
702
if (connection instanceof org.objectweb.jonas.jdbc.ConnectionImpl) {
703                         ((org.objectweb.jonas.jdbc.ConnectionImpl) connection).setJonasInfo(mci, this);
704                     } else {
705                         connection = JonasSQLWrapper.createSQLWrapper(connection, mci, this, trace);
706                     }
707                     // Check the connection before reusing it
708
if (jdbcConnLevel > 0) {
709                         try {
710                             if (isEnabledDebug) {
711                                 trace.log(BasicLevel.DEBUG, "Check the JDBC connection");
712                             }
713                             boolean isClosed = true;
714                             // Used for logical testing of connection
715
if (connection instanceof org.objectweb.jonas.jdbc.ConnectionImpl) {
716                                 isClosed = ((org.objectweb.jonas.jdbc.ConnectionImpl) connection).isPhysicallyClosed();
717                             } else {
718                                 isClosed = ((Connection JavaDoc) connection).isClosed();
719                             }
720                             if (isClosed) {
721                                 connectionErrorOccurred(new ConnectionEvent JavaDoc(mci.mc,
722                                         ConnectionEvent.CONNECTION_ERROR_OCCURRED));
723                                 connection = null;
724                                 retries++;
725                                 continue;
726                             }
727                             if (jdbcConnLevel > 1 && jdbcConnTestStmt != null
728                                     && jdbcConnTestStmt.length() > 0) {
729                                 if (isEnabledDebug) {
730                                     trace.log(BasicLevel.DEBUG, "retrying connection: " + jdbcConnTestStmt);
731                                 }
732                                 java.sql.Statement JavaDoc stmt = ((Connection JavaDoc) connection).createStatement();
733                                 stmt.execute(jdbcConnTestStmt);
734                                 stmt.close();
735                             }
736                         } catch (Exception JavaDoc e) {
737                             trace.log(BasicLevel.ERROR, "Error on connection: removing invalid managed connection " + mci.mc + ": ", e);
738                             connectionErrorOccurred(new ConnectionEvent JavaDoc(mci.mc,
739                                     ConnectionEvent.CONNECTION_ERROR_OCCURRED));
740                             connection = null;
741                             retries++;
742                             continue;
743                         }
744                     }
745                 } catch (Exception JavaDoc ex) {
746                     trace.log(BasicLevel.ERROR, ex.getMessage(), ex);
747                     throw new ResourceException JavaDoc(ex);
748                 }
749             }
750
751         }
752         if (isEnabledDebug) {
753             trace.log(BasicLevel.DEBUG, "get a logical connection on MC:" + connection);
754         }
755
756         if (connection == null) {
757             if (retries > 0) {
758                 throw new ResourceAllocationException JavaDoc(
759                         "Unable to obtain a connection object. Check the validity of the jdbc-test-statement");
760             } else {
761                 throw new ResourceAllocationException JavaDoc("Unable to obtain a connection object");
762             }
763         }
764
765         return connection;
766     }
767
768
769     /**
770      * All method of the pool match to the right type of ManagedConnection because
771      * there is one pool by ManagedConnectionFactory.
772      *
773      * @see org.objectweb.util.pool.api.PoolMatchFactory
774      */

775     public boolean matchResource(Object JavaDoc res, Object JavaDoc hints) {
776         return true;
777     }
778
779     /**
780      * All method of the pool match to the right type of ManagedConnection because
781      * there is one pool by ManagedConnectionFactory.
782      *
783      * @see org.objectweb.util.pool.api.PoolMatchFactory
784      */

785     public Object JavaDoc matchResource(Set JavaDoc res, Object JavaDoc hints) throws Exception JavaDoc {
786         ResourceSpec spec = (hints != null) ? (ResourceSpec) hints : new ResourceSpec(null, null);
787         return mcf.matchManagedConnections(res, null, spec.cxRequestInfo);
788     }
789
790
791     /**
792      * Call the ManagedConnectionFactory in order to create a new instance. of
793      * ManagedConnection. The Object is a ManagedConnection instance. The hints is a
794      * local structure: ResourceSpec
795      *
796      * @see org.objectweb.util.pool.api.PoolMatchFactory
797      */

798     public Object JavaDoc createResource(Object JavaDoc hints) throws Exception JavaDoc {
799         ResourceSpec spec = (hints != null) ? (ResourceSpec) hints : new ResourceSpec(null, null);
800         ManagedConnection JavaDoc mc = mcf.createManagedConnection(spec.subject,
801                 spec.cxRequestInfo);
802         if (isEnabledDebug) {
803             trace.log(BasicLevel.DEBUG, "Created MC: " + mc);
804         }
805         return mc;
806     }
807
808     /**
809      * If supported, call the ManagedConnectionFactory to validate the ManagedConnections
810      *
811      * @see org.objectweb.util.pool.api.PoolMatchFactory
812      */

813     public void validateResource(Set JavaDoc res) throws Exception JavaDoc {
814         if (vmcf == null) {
815             return;
816         }
817         try {
818             Set JavaDoc invMcs = vmcf.getInvalidConnections(res);
819             Iterator JavaDoc it = invMcs.iterator();
820             while (it.hasNext()) {
821                 Object JavaDoc obj = it.next();
822                 poolMCs.releaseResource(obj, true, true);
823             }
824         } catch (Exception JavaDoc ex) {
825             if (isEnabledDebug) {
826                 trace.log(BasicLevel.DEBUG, "Error trying to validate Connections for " + mcf, ex);
827             }
828         }
829     }
830
831
832     /** IMPLEMENTATION OF INTERFACE SQLManager
833      */

834     public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo, Object JavaDoc conn, String JavaDoc user, String JavaDoc sql)
835             throws SQLException JavaDoc {
836         return getPStatement(mcinfo, conn, user, sql, ResultSet.TYPE_FORWARD_ONLY,
837                              ResultSet.CONCUR_READ_ONLY, -1, -1, null, null, PSWRAP_1);
838
839     }
840
841     public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo, Object JavaDoc conn, String JavaDoc user, String JavaDoc sql,
842                                            int resultSetType, int resultSetConcurrency)
843             throws SQLException JavaDoc {
844         return getPStatement(mcinfo, conn, user, sql, resultSetType, resultSetConcurrency,
845                              -1, -1, null, null, PSWRAP_1);
846     }
847
848     // JDBC 3.0
849
public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo,
850                                            Object JavaDoc conn,
851                                            String JavaDoc user, String JavaDoc sql,
852                                            int resultSetType,
853                                            int resultSetConcurrency,
854                                            int resultSetHoldability)
855             throws SQLException JavaDoc {
856               return getPStatement(mcinfo, conn, user, sql, resultSetType, resultSetConcurrency,
857                       resultSetHoldability, -1, null, null, PSWRAP_2);
858     }
859
860     // JDBC 3.0
861
public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo,
862                                            Object JavaDoc conn,
863                                            String JavaDoc user, String JavaDoc sql,
864                                            int autoGeneratedKeys)
865             throws SQLException JavaDoc {
866                 return getPStatement(mcinfo, conn, user, sql, -1, -1, -1,
867                         autoGeneratedKeys, null, null, PSWRAP_3);
868     }
869
870     // JDBC 3.0
871
public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo,
872                                            Object JavaDoc conn,
873                                            String JavaDoc user, String JavaDoc sql,
874                                            int[] columnIndexes)
875             throws SQLException JavaDoc {
876               return getPStatement(mcinfo, conn, user, sql, -1, -1, -1, -1,
877                       columnIndexes, null, PSWRAP_4);
878     }
879
880     // JDBC 3.0
881
public PreparedStatement JavaDoc getPStatement(MCInfo mcinfo,
882                                            Object JavaDoc conn,
883                                            String JavaDoc user, String JavaDoc sql,
884                                            String JavaDoc[] columnNames)
885             throws SQLException JavaDoc {
886               return getPStatement(mcinfo, conn, user, sql, -1, -1, -1, -1,
887                       null, columnNames, PSWRAP_5);
888     }
889
890
891     private PreparedStatement JavaDoc getPStatement(MCInfo mcinfo,
892                                             Object JavaDoc conn,
893                                             String JavaDoc user,
894                                             String JavaDoc sql,
895                                             int resultSetType,
896                                             int resultSetConcurrency,
897                                             int resultSetHoldability,
898                                             int autoGeneratedKeys,
899                                             int [] columnIndexes,
900                                             String JavaDoc [] columnNames,
901                                             int pswrapType)
902             throws SQLException JavaDoc {
903
904         if (isEnabledDebug) {
905             trace.log(BasicLevel.DEBUG, "Sql: " + sql + " User: " + user);
906         }
907         // Use for the equals test
908
PreparedStatementWrapper psw = null;
909         switch (pswrapType) {
910             case PSWRAP_1:
911                 psw = new PreparedStatementWrapper(user, sql,
912                                                    resultSetType,
913                                                    resultSetConcurrency,
914                                                    trace,
915                                                    isEnabledDebug);
916                 break;
917             case PSWRAP_2:
918                 psw = new PreparedStatementWrapper(user, sql,
919                                                    resultSetType,
920                                                    resultSetConcurrency,
921                                                    resultSetHoldability,
922                                                    trace,
923                                                    isEnabledDebug);
924                 break;
925             case PSWRAP_3:
926                 psw = new PreparedStatementWrapper(user, sql,
927                                                    autoGeneratedKeys,
928                                                    trace,
929                                                    isEnabledDebug);
930                 break;
931             case PSWRAP_4:
932                 psw = new PreparedStatementWrapper(user, sql,
933                                                    columnIndexes,
934                                                    trace,
935                                                    isEnabledDebug);
936                 break;
937             case PSWRAP_5:
938                 psw = new PreparedStatementWrapper(user, sql,
939                                                    columnNames,
940                                                    trace,
941                                                    isEnabledDebug);
942                 break;
943             default:
944                 break;
945         }
946
947         synchronized (mcinfo.pStmts) {
948             if (isEnabledDebug) {
949                 trace.log(BasicLevel.DEBUG, "MC pStmts: " + mcinfo.pStmts);
950             }
951             //Check if statement matches ManagedConnection list & valid
952
// use lastIndexOf as when a statement is found, it is put at the end.
953
int indexPstmt = mcinfo.pStmts.lastIndexOf(psw);
954             if (indexPstmt != -1) {
955                 PreparedStatementWrapper ps = (PreparedStatementWrapper) mcinfo.pStmts.remove(indexPstmt);
956                 ps.clearPstmtValues();
957                 mcinfo.pStmts.add(ps); // add last
958
return ps;
959             } else if (isEnabledDebug) {
960                 trace.log(BasicLevel.DEBUG, "No statement in cache, need to build a new one");
961             }
962
963             //If not in either, call con.prepareStatement, wrap the returned one
964
// and add it to MC pool
965
PreparedStatement JavaDoc ps = null;
966             switch (pswrapType) {
967                 case PSWRAP_1:
968                     ps = ((java.sql.Connection JavaDoc) conn).
969                            prepareStatement(sql, resultSetType, resultSetConcurrency);
970                     break;
971                 case PSWRAP_2:
972                     ps = ((java.sql.Connection JavaDoc) conn).
973                            prepareStatement(sql, resultSetType, resultSetConcurrency,
974                                             resultSetHoldability);
975                     break;
976                 case PSWRAP_3:
977                     ps = ((java.sql.Connection JavaDoc) conn).
978                            prepareStatement(sql, autoGeneratedKeys);
979                     break;
980                 case PSWRAP_4:
981                     ps = ((java.sql.Connection JavaDoc) conn).
982                            prepareStatement(sql, columnIndexes);
983                     break;
984                 case PSWRAP_5:
985                     ps = ((java.sql.Connection JavaDoc) conn).
986                            prepareStatement(sql, columnNames);
987                     break;
988                 default:
989                     break;
990             }
991             if (maxPstmtPoolSize < 0) {
992                 // No prepared statement pool
993
if (isEnabledDebug) {
994                     trace.log(BasicLevel.DEBUG, "Pooling is disabled");
995                 }
996                 return ps;
997             } else if (maxPstmtPoolSize == 0 || mcinfo.pStmts.size() < maxPstmtPoolSize) {
998                 psw.setPreparedStatement(ps);
999                 mcinfo.pStmts.add(psw);
1000                if (isEnabledDebug) {
1001                    trace.log(BasicLevel.DEBUG, "Adding PStmt: " + psw);
1002                }
1003                return psw;
1004            } else {
1005                int offset = mcinfo.findFreeStmt();
1006                if (offset >= 0) {
1007                    // Remove that entry from the current pool
1008
PreparedStatementWrapper pw = (PreparedStatementWrapper) mcinfo.pStmts.remove(offset);
1009                    pw.destroy();
1010                    psw.setPreparedStatement(ps);
1011                    mcinfo.pStmts.add(psw);
1012                    if (isEnabledDebug) {
1013                        trace.log(BasicLevel.DEBUG, "Replacing " + pw + " with " + psw);
1014                    }
1015                    return psw;
1016                } else {
1017                    // No room for the Wrapped statement just return the PreparedStatement
1018
if (isEnabledDebug) {
1019                        trace.log(BasicLevel.DEBUG, "No room in pool");
1020                    }
1021                    return ps;
1022                }
1023            }
1024        }
1025    }
1026
1027
1028    /**
1029     * Release the ManagedConnection object resource
1030     * @param rMc Object to release
1031     * @throws Exception if an Exception occurs
1032     */

1033    public void releaseResource(Object JavaDoc rMc) throws Exception JavaDoc {
1034        if (isEnabledDebug) {
1035            trace.log(BasicLevel.DEBUG, "MC: " + rMc);
1036        }
1037        if (rMc instanceof ManagedConnection JavaDoc) {
1038            ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) rMc;
1039            MCInfo mcinfo = (MCInfo) mc2mci.remove(mc);
1040            if (mcinfo != null) {
1041                destroyPStmts(mcinfo);
1042            }
1043        }
1044    }
1045
1046    /**
1047     * Destroying of the PreparedStatement objects of the Pool
1048     * @param mcinfo ManagedConnection information
1049     * @throws Exception Exception
1050     */

1051    public void destroyPStmts(MCInfo mcinfo) throws Exception JavaDoc {
1052        if (isEnabledDebug) {
1053            trace.log(BasicLevel.DEBUG, "MCInfo: " + mcinfo);
1054        }
1055        synchronized (mcinfo.pStmts) {
1056            if (mcinfo.pStmts.size() <= 0) {
1057                return;
1058            }
1059            int stmtSize = mcinfo.pStmts.size();
1060            try {
1061                for (int i = 0; i < stmtSize; i++) {
1062                    PreparedStatementWrapper psw = (PreparedStatementWrapper)
1063                            mcinfo.pStmts.remove(0);
1064                    psw.closePstmt();
1065                }
1066            } catch (Exception JavaDoc ex) {
1067                throw ex;
1068            }
1069        }
1070    }
1071
1072    /**
1073     * IMPLEMENTATION OF INTERFACE ConnectionEventListener *
1074     *
1075     * A ManagedConnection instance calls the connectionClosed method to notify
1076     * its registered set of listeners when an application component closes a
1077     * connection handle. The application server uses this connection close event
1078     * to make a decision on whether or not to put the ManagedConnection instance
1079     * back into the connection pool.
1080     *
1081     * @see javax.resource.spi.ConnectionEventListener
1082     */

1083    public void connectionClosed(ConnectionEvent JavaDoc event) {
1084        ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) event.getSource();
1085        if (mc == null) {
1086            trace.log(BasicLevel.ERROR, "no mc found in Event!");
1087        }
1088
1089        MCInfo mci = (MCInfo) mc2mci.get(mc);
1090        if (mci == null) {
1091            trace.log(BasicLevel.ERROR, "no mci found!");
1092            return;
1093        }
1094
1095        if (isEnabledDebug) {
1096            trace.log(BasicLevel.DEBUG, "enter\n" + getState("\t"));
1097        }
1098
1099        mci.usedCs.remove(event.getConnectionHandle());
1100
1101        if (mci.usedCs.isEmpty()) {
1102            if (isEnabledDebug) {
1103                trace.log(BasicLevel.DEBUG, "Last Connection has just been removed");
1104            }
1105
1106            try {
1107                Transaction JavaDoc currentTx = null;
1108                if (tm != null) {
1109                    currentTx = tm.getTransaction();
1110                }
1111
1112                if (mci.localTransaction && currentTx == null) {
1113                    trace.log(BasicLevel.ERROR, "The managed connection is being closed while a localtransaction is not finished");
1114                }
1115
1116                if (currentTx != null) {
1117                    mci.ctx = currentTx;
1118
1119                    if (mci.synchro == null) {
1120                        try {
1121                            currentTx.registerSynchronization(
1122                                    new MySynchro(this, mci));
1123                            if (isEnabledDebug) {
1124                                trace.log(BasicLevel.DEBUG, "registerSynchro mc=" + mci.mc);
1125                            }
1126                        } catch (RollbackException JavaDoc e) {
1127                            // The transaction has been marked as rollbackOnly
1128
// but the synchronization is registered.
1129
trace.log(BasicLevel.INFO, "registerSynchronization on transaction marked as Rollback only, mc=" + mci.mc);
1130                        }
1131                    }
1132                } else if (mci.localTransaction) {
1133                    if (isEnabledDebug) {
1134                        trace.log(BasicLevel.DEBUG, "MC isn't released because local transaction is not finished");
1135                    }
1136
1137                } else {
1138                    if (isEnabledDebug) {
1139                        trace.log(BasicLevel.DEBUG, "no currentTx");
1140                    }
1141
1142                    mcs.remove(mci);
1143
1144                    if (mci.ctx != null) {
1145                        usedMCs.remove(mci.ctx);
1146                        mci.ctx = null;
1147                    }
1148
1149                    mci.mc.cleanup();
1150
1151                    // Free up the PreparedStatements
1152
// mci.stmtHash.clear();
1153

1154                    // Release the MC from its pool
1155
poolMCs.releaseResource(mci.mc, false, true);
1156
1157                }
1158                if (mci.rmeCalled) {
1159                    //Signal to the RessourceManagerEventListener mc is released
1160
mci.rme.isValid = false;
1161                    rmel.connectionClosed(mci.rme);
1162                    mci.rmeCalled = false;
1163                }
1164            } catch (Exception JavaDoc e) {
1165                trace.log(BasicLevel.ERROR,
1166                        "an error during delisting of ManagedConection: ", e);
1167            }
1168            if (isEnabledDebug) {
1169                trace.log(BasicLevel.DEBUG, "exit\n" + getState("\t"));
1170            }
1171        }
1172    }
1173
1174
1175    /**
1176     * The connectionErrorOccurred method indicates that the associated
1177     * ManagedConnection instance is now invalid and unusable. The application
1178     * server handles the connection error event notification by initiating
1179     * application server-specific cleanup (for example, removing
1180     * ManagedConnection instance from the connection pool) and then calling
1181     * ManagedConnection.destroy method to destroy the physical connection..
1182     *
1183     * @see javax.resource.spi.ConnectionEventListener
1184     */

1185    public void connectionErrorOccurred(ConnectionEvent JavaDoc event) {
1186        ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) event.getSource();
1187        if (mc == null) {
1188            trace.log(BasicLevel.ERROR, "no mc found in Event!");
1189        }
1190
1191        MCInfo mci = (MCInfo) mc2mci.get(mc);
1192        if (mci == null) {
1193            trace.log(BasicLevel.ERROR, "no mci found!");
1194            return;
1195        }
1196
1197        if (poolTrace.isLoggable(BasicLevel.DEBUG)) {
1198            poolTrace.log(BasicLevel.DEBUG, "enter\n" + getState("\t"));
1199        }
1200
1201        mci.usedCs.clear();
1202
1203        try {
1204            if (mci.rmeCalled) {
1205                //Signal to the RessourceManagerEventListener mc is released
1206
mci.rme.isValid = false;
1207                rmel.connectionErrorOccured(mci.rme);
1208                mci.rmeCalled = false;
1209            }
1210            // Detach the connectionManager from the mc
1211
mc.removeConnectionEventListener(this);
1212            // Remove the association (transaction ctx / mc)
1213
if (mci.ctx != null) {
1214                usedMCs.remove(mci.ctx);
1215                mci.ctx = null;
1216            } else {
1217                mcs.remove(mci);
1218            }
1219
1220            if (isEnabledDebug) {
1221                trace.log(BasicLevel.DEBUG, "Destroying managed connection (" + mc + ")");
1222            }
1223            // Destroy the PreparedStatements
1224
destroyPStmts(mci);
1225
1226            poolMCs.releaseResource(mc, true, false);
1227            if (poolTrace.isLoggable(BasicLevel.DEBUG)) {
1228                poolTrace.log(BasicLevel.DEBUG, "enter\n" + getState("\t"));
1229            }
1230
1231            mc2mci.remove(mc);
1232
1233        } catch (Exception JavaDoc e) {
1234            trace.log(BasicLevel.ERROR,
1235                    "an error related during delisting of ManagedConection");
1236        }
1237    }
1238
1239
1240    /**
1241     * Notifies that a Resource Manager Local Transaction was committed on the
1242     * ManagedConnection instance.
1243     *
1244     * @see javax.resource.spi.ConnectionEventListener
1245     */

1246    public void localTransactionCommitted(ConnectionEvent JavaDoc event) {
1247        ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) event.getSource();
1248        if (mc == null) {
1249            trace.log(BasicLevel.ERROR, "no mc found in Event!");
1250        }
1251
1252        MCInfo mci = (MCInfo) mc2mci.get(mc);
1253        if (mci == null) {
1254            trace.log(BasicLevel.ERROR, "no mci found!");
1255            return;
1256        }
1257        mci.localTransaction = false;
1258
1259        if (mci.usedCs.isEmpty()) {
1260            if (isEnabledDebug) {
1261                trace.log(BasicLevel.DEBUG, "Close the managed connection");
1262            }
1263
1264            if (mci.rmeCalled) {
1265                //Signal to the RessourceManagerEventListener mc is released
1266
mci.rme.isValid = false;
1267                rmel.connectionClosed(mci.rme);
1268                mci.rmeCalled = false;
1269            }
1270
1271            if (mci.synchro == null) {
1272                mcs.remove(mci);
1273                if (mci.ctx != null) {
1274                    usedMCs.remove(mci.ctx);
1275                    mci.ctx = null;
1276                }
1277
1278                try {
1279                    mci.mc.cleanup();
1280
1281                    // Release the MC from its pool
1282
poolMCs.releaseResource(mci.mc, false, true);
1283                } catch (Exception JavaDoc e) {
1284                    trace.log(BasicLevel.ERROR,
1285                            "an error related ManagedConection release",
1286                            e, "ConnectionManagerImpl", "localTransactionCommitted");
1287                }
1288            }
1289        }
1290    }
1291
1292
1293    /**
1294     * Notifies that a Resource Manager Local Transaction was rolled back on the
1295     * ManagedConnection instance.
1296     *
1297     * @see javax.resource.spi.ConnectionEventListener
1298     */

1299    public void localTransactionRolledback(ConnectionEvent JavaDoc event) {
1300        ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) event.getSource();
1301        if (mc == null) {
1302            trace.log(BasicLevel.ERROR, "no mc found in Event!");
1303        }
1304
1305        MCInfo mci = (MCInfo) mc2mci.get(mc);
1306        if (mci == null) {
1307            trace.log(BasicLevel.ERROR, "no mci found!");
1308            return;
1309        }
1310        mci.localTransaction = false;
1311
1312        if (mci.usedCs.isEmpty()) {
1313            if (isEnabledDebug) {
1314                trace.log(BasicLevel.DEBUG, "Close the managed connection");
1315            }
1316
1317            if (mci.rmeCalled) {
1318                //Signal to the ResourceManagerEventListener mc is released
1319
mci.rme.isValid = false;
1320                rmel.connectionClosed(mci.rme);
1321                mci.rmeCalled = false;
1322            }
1323
1324            if (mci.synchro == null) {
1325                mcs.remove(mci);
1326                if (mci.ctx != null) {
1327                    usedMCs.remove(mci.ctx);
1328                    mci.ctx = null;
1329                }
1330
1331                try {
1332                    mci.mc.cleanup();
1333
1334                    // Release the MC from its pool
1335
poolMCs.releaseResource(mci.mc, false, true);
1336                } catch (Exception JavaDoc e) {
1337                    trace.log(BasicLevel.ERROR,
1338                            "an error related during ManagedConection release:",
1339                            e, "ConnectionManagerImpl", "localTransactionRolledback");
1340                }
1341            }
1342        }
1343    }
1344
1345
1346    /**
1347     * Notifies that a Resource Manager Local Transaction was started on the
1348     * ManagedConnection instance.
1349     *
1350     * @see javax.resource.spi.ConnectionEventListener
1351     */

1352    public void localTransactionStarted(ConnectionEvent JavaDoc event) {
1353        ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) event.getSource();
1354        if (mc == null) {
1355            trace.log(BasicLevel.ERROR, "no mc found in Event!");
1356        }
1357
1358        MCInfo mci = (MCInfo) mc2mci.get(mc);
1359        if (mci == null) {
1360            trace.log(BasicLevel.ERROR, "no mci found!");
1361            return;
1362        }
1363        mci.localTransaction = true;
1364    }
1365
1366
1367    /**
1368     * Description of the Method
1369     *
1370     *@return Description of the Returned Value
1371     */

1372    public String JavaDoc toString() {
1373        String JavaDoc m = super.toString();
1374        // remove package name
1375
int c1 = 0;
1376        int current = m.indexOf(".");
1377        while (current != -1) {
1378            c1 = current;
1379            current = m.indexOf(".", current + 1);
1380        }
1381        return m.substring(c1 + 1, m.length());
1382    }
1383
1384
1385    /**
1386     * Gets the State attribute of the ConnectionManagerImpl object
1387     *
1388     *@param prefix Description of Parameter
1389     *@return The State value
1390     */

1391    protected String JavaDoc getState(String JavaDoc prefix) {
1392        String JavaDoc res = prefix + "mcf=" + mcf + "\n";
1393        res += prefix + "ResourceSpec=" + rs.toString() + "\n";
1394        res += prefix + "size of MC pool:" + poolMCs.getSize() + "\n";
1395        res += prefix + "size of usedMCs:" + usedMCs.size() + "\n";
1396        res += prefix + "mcs attached to a tx:\n";
1397        for (Enumeration JavaDoc en = usedMCs.keys(); en.hasMoreElements();) {
1398            Object JavaDoc tx = en.nextElement();
1399            MCInfo mci = (MCInfo) usedMCs.get(tx);
1400            res += prefix + "MCI : tx=" + tx + "\n";
1401            res += mci.getState(prefix + "\t");
1402        }
1403        res += prefix + "mcs not attached to a tx:\n";
1404        for (Enumeration JavaDoc en = mcs.elements(); en.hasMoreElements();) {
1405            MCInfo mci = (MCInfo) en.nextElement();
1406            res += mci.getState(prefix + "\t");
1407        }
1408        res += prefix + "mcs waiting for tx commit or rollback:\n";
1409        for (Enumeration JavaDoc en = synchros.elements(); en.hasMoreElements();) {
1410            MCInfo mci = (MCInfo) en.nextElement();
1411            res += mci.getState(prefix + "\t");
1412        }
1413        return res;
1414    }
1415
1416    /**
1417     * Set the XAName to use
1418     * @param xanm String of XA Name
1419     */

1420    public void setXAName(String JavaDoc xanm) {
1421        xaName = xanm;
1422    }
1423
1424    /**
1425     * Get the XAName to use
1426     * @return String of XA Name
1427     */

1428    public String JavaDoc getXAName() {
1429        return (xaName);
1430    }
1431
1432    /**
1433     * Register an XAResource with JOTM for recovery
1434     */

1435    public void registerXAResource(Properties JavaDoc tmProp) {
1436        // If no RM or the RAR doesn't support XA, then just return
1437
if (tm == null) {
1438            return;
1439        }
1440        if (!transSupport.equalsIgnoreCase(XA_TRANS_SUPPORT)) {
1441            return;
1442        }
1443
1444        // Find an entry in free pool
1445
// If none, then create one
1446
MCInfo mci = null;
1447        XAResource JavaDoc xar = null;
1448        try {
1449            ManagedConnection JavaDoc mc = (ManagedConnection JavaDoc) poolMCs.getResource(rs);
1450            if (mc == null) {
1451                if (isEnabledDebug) {
1452                    trace.log(BasicLevel.DEBUG, "Cannot allocate a ManagedConnection for registerXAResource");
1453                }
1454                return;
1455            }
1456
1457            mci = (MCInfo) mc2mci.get(mc);
1458            if (mci == null) {
1459                mci = new MCInfo(mc);
1460                mc2mci.put(mc, mci);
1461            }
1462
1463            xar = mc.getXAResource();
1464            if (isEnabledDebug) {
1465                trace.log(BasicLevel.DEBUG, "got a MC from the ra pool, mc=" + mci.mc
1466                        + " xar=" + xar);
1467            }
1468
1469            if (!mci.connectionEventListener) {
1470                mci.mc.addConnectionEventListener(this);
1471                mci.connectionEventListener = true;
1472            }
1473
1474            mci.synchro = null;
1475
1476        } catch (ResourceException JavaDoc re) {
1477            return;
1478        } catch (Exception JavaDoc e) {
1479            trace.log(BasicLevel.ERROR, e.getMessage(), e);
1480            return;
1481        }
1482
1483        // Setup globals so it can be returned to the pool
1484
jotmMc = mci.mc;
1485        jotmXar = xar;
1486
1487        // Call to register it
1488
try {
1489            if (isEnabledDebug) {
1490                trace.log(BasicLevel.DEBUG, "Registering name = " + xaName + " xar = " + jotmXar);
1491            }
1492            ((Current) tm).getTransactionRecovery().registerResourceManager(xaName, jotmXar, "", tmProp, this);
1493       } catch (Exception JavaDoc ex) {
1494            trace.log(BasicLevel.ERROR, ex.getMessage(), ex);
1495            returnXAResource(xaName, jotmXar);
1496        }
1497    }
1498
1499    /**
1500     * Called from JOTM to free the XAResource and associated Managed Connection
1501     * when recovery is complete
1502     *
1503     * @param rmName The Resource Manager to be unregistered.
1504     * @param rmXares XAResource to be returned
1505     */

1506    public void returnXAResource(String JavaDoc rmName, XAResource JavaDoc rmXares) {
1507        // Get the associated MC
1508
// Clean it up and return it to the free pool
1509
if (isEnabledDebug) {
1510            trace.log(BasicLevel.DEBUG, "Removing name = " + xaName + " xar = " + jotmXar);
1511        }
1512        if (jotmXar == null) {
1513            return;
1514        }
1515        if (!rmXares.equals(jotmXar)) {
1516            trace.log(BasicLevel.ERROR, "XAResource of " + rmXares + " and "
1517                                        + jotmXar + " not equal!");
1518            return;
1519        }
1520
1521        MCInfo mci = (MCInfo) mc2mci.get(jotmMc);
1522        if (mci == null) {
1523            trace.log(BasicLevel.ERROR, "no mci found for " + jotmMc);
1524            return;
1525        }
1526
1527        try {
1528            mci.mc.cleanup();
1529
1530            // Release the MC from its pool
1531
poolMCs.releaseResource(mci.mc, false, true);
1532        } catch (Exception JavaDoc ex) {
1533            trace.log(BasicLevel.ERROR, ex.getMessage(), ex);
1534        }
1535
1536        jotmMc = null;
1537        jotmXar = null;
1538    }
1539
1540    // JSR 77 (JCAConnectionFactory methods)
1541

1542    public Pool getPool() {
1543        return poolMCs;
1544    }
1545
1546    public int getCheckLevel() {
1547        return jdbcConnLevel;
1548    }
1549
1550    public void setCheckLevel(int level) {
1551        jdbcConnLevel = level;
1552    }
1553
1554    public String JavaDoc getTestStatement() {
1555        return jdbcConnTestStmt;
1556    }
1557
1558    public void setTestStatement(String JavaDoc stmt) {
1559        jdbcConnTestStmt = stmt;
1560    }
1561
1562    public int getCurrentInTx() {
1563        return usedMCs.size();
1564    }
1565}
Popular Tags