001: /**
002: * perseus/connector: this is an implementation of some JCA-related technologies
003: * (resource adapters and managers) for the ObjectWeb consortium.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * Contact: speedo@objectweb.org
021: *
022: */package org.objectweb.speedo.jca;
023:
024: import org.objectweb.speedo.api.Debug;
025: import org.objectweb.speedo.api.ExceptionHelper;
026: import org.objectweb.speedo.pm.api.POManagerItf;
027: import org.objectweb.speedo.workingset.api.TransactionItf;
028: import org.objectweb.util.monolog.api.BasicLevel;
029: import org.objectweb.util.monolog.api.Logger;
030:
031: import javax.jdo.JDOFatalException;
032: import javax.resource.ResourceException;
033: import javax.resource.cci.Connection;
034: import javax.resource.spi.*;
035: import javax.security.auth.Subject;
036: import javax.transaction.RollbackException;
037: import javax.transaction.TransactionManager;
038: import javax.transaction.xa.XAException;
039: import javax.transaction.xa.XAResource;
040: import javax.transaction.xa.Xid;
041: import java.io.PrintWriter;
042: import java.util.ArrayList;
043: import java.util.Iterator;
044:
045: /**
046: * @author P. Dechamboux
047: */
048: public class SpeedoManagedConnection implements ManagedConnection,
049: javax.resource.spi.LocalTransaction,
050: javax.resource.cci.LocalTransaction, XAResource,
051: ManagedConnectionMetaData {
052:
053: public final static String EIS_PRODUCT_NAME = "Speedo Resource Adapter";
054: public final static String EIS_PRODUCT_VERSION = "1.0";
055: public final static String USER_NAME = "No user name needed to use the Speedo driver";
056:
057: /**
058: * The logger into which traces about SpeedoManagedConnection are produced.
059: */
060: private Logger logger;
061:
062: /**
063: * The ManagedConnectionFactory that have requested the allocation of this
064: * ManagedConnection.
065: */
066: private SpeedoManagedConnectionFactory mcf;
067:
068: /**
069: * The logical Connections associated with this ManagedConnection. Always
070: * at least one connection except when the MC is in the pool.
071: */
072: private ArrayList logicalConnections = new ArrayList(1);
073:
074: /**
075: * The ConnectionEventListener list associated with this ManagedConnection.
076: */
077: private ArrayList listeners = null;
078:
079: /**
080: * It is set if the ManagedConnection execute within a LocalTransaction.
081: */
082: private POManagerItf localTransactionPM = null;
083:
084: /**
085: * It is the current SpeedoXAContext. It is not null when the ManagedConnection
086: * is used in a XA transaction through the XAResource interface.
087: */
088: public SpeedoXAContext xac;
089:
090: /**
091: * It is set if Speedo operation occurs outside any explicit (LocalTransaction)
092: * or implicit (XAResource) transaction context.
093: */
094: private POManagerItf defaultPM = null;
095:
096: protected SpeedoConnectionSpec cri = null;
097:
098: /**
099: * Constructs a SpeedoManagedConnection.
100: * @param el The logger into which to produce ManagedConnection-related
101: * traces.
102: * @param fmcf The ManagedConnectionFactory that has requested the
103: * ManagedConnection creation.
104: */
105: SpeedoManagedConnection(Logger el,
106: SpeedoManagedConnectionFactory fmcf) {
107: logger = el;
108: if (Debug.ON && logger != null)
109: logger.log(BasicLevel.DEBUG,
110: "Constructs a new SpeedoManagedConnection");
111: mcf = fmcf;
112: listeners = null;
113: }
114:
115: /**
116: * Retrieves the right POManagerItf in according the managed connection
117: * state (in a local transaction, in a XA transaction or out of transaction)
118: *
119: * @return a POManagerItf instance (never null).
120: */
121: public POManagerItf getPOManager() {
122: if (localTransactionPM != null) {
123: if (Debug.ON && logger != null
124: && logger.isLoggable(BasicLevel.DEBUG)) {
125: logger.log(BasicLevel.DEBUG,
126: "return localTransactionPM: "
127: + localTransactionPM);
128: }
129: return localTransactionPM;
130: }
131: if (xac != null) {
132: if (Debug.ON && logger != null
133: && logger.isLoggable(BasicLevel.DEBUG)) {
134: logger.log(BasicLevel.DEBUG, "xac.status= "
135: + xac.status + "xac.xid= " + xac.xid);
136: }
137: if (xac.status != SpeedoXAContext.STARTED) {
138: throw new JDOFatalException(
139: "XA context should have been started here: xac.status= "
140: + xac.status + "xac.xid= " + xac.xid);
141: }
142: if (xac.pm == null) {
143: synchronized (xac) {
144: if (xac.pm == null) {
145: xac.pm = (POManagerItf) mcf.pmf.getPOManager();
146: if (Debug.ON && logger != null
147: && logger.isLoggable(BasicLevel.DEBUG)) {
148: logger
149: .log(
150: BasicLevel.DEBUG,
151: "Creates a PersistenceManager ("
152: + xac.pm
153: + ") associated to the XID: "
154: + xac.xid);
155: }
156: }
157: }
158: }
159: if (!xac.synchroRegistred) {
160: //Register the PersistenceManager on the first use
161: try {
162: registerSynchronization();
163: } catch (XAException ex) {
164: JDOFatalException e = new JDOFatalException(
165: "Problem while registering a synchronization.",
166: ex);
167: if (logger != null) {
168: logger
169: .log(BasicLevel.ERROR, e.getMessage(),
170: ex);
171: }
172: throw e;
173: }
174: }
175: return xac.pm;
176: }
177: if (defaultPM == null) {
178: defaultPM = (POManagerItf) mcf.pmf.getPOManager();
179: }
180: if (Debug.ON && logger != null
181: && logger.isLoggable(BasicLevel.DEBUG)) {
182: logger.log(BasicLevel.DEBUG,
183: "return the default persistence manager: "
184: + defaultPM);
185: }
186: return defaultPM;
187: }
188:
189: /**
190: * find the SpeedoXAContext matching an Xid.
191: * @param flag indicates expecting behavior:<UL>
192: * <LI>0: create the SpeedoXAContext if it does not already exist</LI>
193: * <LI>1: return an existing SpeedoXAContext</LI>
194: * <LI>otherwise: return an SpeedoXAContext or null it is not found</LI>
195: * </UL>
196: */
197: public SpeedoXAContext getXAContext(Xid xid, int flag)
198: throws XAException {
199: if (mcf == null) {
200: //The MC has been destroyed, and the contexts has beean rolled back
201: return null;
202: }
203: SpeedoXAContext _xac = mcf.getXAContext(xid);
204: if (_xac == null) {
205: if (flag == 0) { //create it
206: try {
207: _xac = mcf.createXAContext(xid);
208: } catch (RuntimeException fe) {
209: Exception ie = ExceptionHelper.getNested(fe);
210: XAException e = new XAException(
211: "Error during the creation of the XA context with the xid: "
212: + xid + ", error message:"
213: + ie.getMessage());
214: if (logger != null) {
215: logger.log(BasicLevel.ERROR, ie.getMessage(),
216: ie);
217: }
218: throw e;
219: }
220: } else if (flag == 1) { // throw an exception
221: XAException e = new XAException(
222: "No XA context found for the xid=" + xid);
223: if (logger != null) {
224: logger.log(BasicLevel.ERROR, e.getMessage(), e);
225: }
226: throw e;
227: } // else return null
228: }
229: return _xac;
230: }
231:
232: /**
233: * Registers the POManagerItf of the current SpeedoXAContext to the current
234: * transaction, if it is not already done.
235: *
236: * @throws XAException if the registering is not possible:
237: * - TM not availlable
238: * - Pr
239: */
240: public synchronized void registerSynchronization()
241: throws XAException {
242: if (xac.synchroRegistred) {
243: return;
244: }
245: TransactionItf tx = xac.pm.getSpeedoTransaction();
246: if (tx.isActive() && logger != null) {
247: logger
248: .log(
249: BasicLevel.WARN,
250: "Speedo TransactionItf started and the "
251: + "PersistenceManager is not marked as registered to "
252: + "the XA transaction");
253: }
254: if (Debug.ON && logger != null
255: && logger.isLoggable(BasicLevel.DEBUG)) {
256: logger.log(BasicLevel.DEBUG, "registerSynchronization");
257: }
258: TransactionManager tm = mcf.tm;
259: if (tm == null) {
260: String msg = "Impossible to register the Speedo "
261: + "container as synchronization on the current transaction: "
262: + (tm == null ? "The transaction manager has not found with the JNDI name: "
263: + mcf.getTransactionManagerJNDIName()
264: : "The TransactionItf object of the Speedo implementation does not implement javax.transaction.Synchronization");
265: if (logger != null) {
266: logger.log(BasicLevel.ERROR, msg);
267: }
268: throw new XAException(msg);
269: }
270: try {
271: tm.getTransaction().registerSynchronization(xac.pm);
272: if (!tx.isActive()) {
273: tx.begin();
274: }
275: xac.synchroRegistred = true;
276: } catch (RollbackException e) {
277: //The JDO container cannot be registered then the transaction
278: // must be rolledback
279: if (tx.isActive()) {
280: tx.rollback();
281: }
282: } catch (Exception e) {
283: String msg = "Impossible to register the Speedo "
284: + "container as synchronization on the current"
285: + " transaction: " + e.getMessage();
286: if (logger != null) {
287: logger.log(BasicLevel.ERROR, msg, e);
288: }
289: throw new XAException(msg);
290: }
291: }
292:
293: /**
294: * Specifies if this ManagedConnection still has an active LocalTransaction.
295: * @return true if a LocalTransaction is still active.
296: */
297: public boolean localTransactionTerminated() {
298: return localTransactionPM == null;
299: }
300:
301: /**
302: * Dissociates a Connection from the ones that are associated to this
303: * ManagedConnection.
304: * @param conn The Connection to be dissociated.
305: */
306: public synchronized void dissociateConnection(Object conn)
307: throws ResourceException {
308: int ind = logicalConnections.indexOf(conn);
309: if (ind == -1) {
310: throw new ResourceException(
311: "Speedo Connector: cannot dissociate an unknown Connection:"
312: + conn + "\n among " + logicalConnections);
313: }
314: if (Debug.ON && logger != null
315: && logger.isLoggable(BasicLevel.DEBUG)) {
316: logger.log(BasicLevel.DEBUG, "Dissociates Connection ("
317: + ind + "): " + conn);
318: }
319: logicalConnections.remove(ind);
320: ConnectionEvent ce = new ConnectionEvent(this ,
321: ConnectionEvent.CONNECTION_CLOSED);
322: ce.setConnectionHandle(conn);
323: if (listeners != null) {
324: synchronized (this ) {
325: for (int i = 0; i < listeners.size();) {
326: ConnectionEventListener cel = (ConnectionEventListener) listeners
327: .get(i);
328: cel.connectionClosed(ce);
329: if (i < listeners.size() && cel == listeners.get(i)) {
330: i++;
331: }// else the listeners has been removed
332: }
333: }
334: }
335: }
336:
337: // IMPLEMENTATION OF METHODS FROM THE (cci)ManagedConnectionMetaData INTERFACE
338:
339: public String getEISProductName() throws ResourceException {
340: return EIS_PRODUCT_NAME;
341: }
342:
343: public String getEISProductVersion() throws ResourceException {
344: return EIS_PRODUCT_VERSION;
345: }
346:
347: public int getMaxConnections() throws ResourceException {
348: // TODO: analysis of ra.xml values
349: return 10;
350: }
351:
352: public String getUserName() throws ResourceException {
353: return USER_NAME;
354: }
355:
356: // IMPLEMENTATION OF METHODS FROM THE (cci)ManagedConnection INTERFACE //
357: //---------------------------------------------------------------------//
358:
359: /**
360: * Delegates the creation of a Connection to the ConnectionFactory.
361: * "subject" and "info" parameters are ignored.
362: */
363: public Object getConnection(Subject subject,
364: ConnectionRequestInfo info) throws ResourceException {
365: SpeedoConnection rac = (SpeedoConnection) mcf.connectionFactory
366: .createConnection();
367: rac.initialize(this );
368: associateConnection(rac);
369: return rac;
370: }
371:
372: /**
373: * Cleans up the connection.
374: */
375: public void cleanup() throws ResourceException {
376: if (Debug.ON && logger != null)
377: logger.log(BasicLevel.DEBUG, "Cleans up ManagedConnection");
378: int s = (logicalConnections == null ? 0 : logicalConnections
379: .size());
380: if (s > 0) {
381: s -= 1;
382: for (int i = s; i >= 0; i--) {
383: ((Connection) logicalConnections.get(i)).close();
384: }
385: }
386: if (localTransactionPM != null) {
387: localTransactionPM.closePOManager();
388: localTransactionPM = null;
389: }
390: if (defaultPM != null) {
391: defaultPM.closePOManager();
392: defaultPM = null;
393: }
394: //The specification requires to keep the XAResource associated to MC
395: }
396:
397: /**
398: * Called when ManagedConnection is removed.
399: */
400: public void destroy() throws ResourceException {
401: cleanup();
402: logger = null;
403: mcf = null;
404: logicalConnections = null;
405: listeners = null;
406: localTransactionPM = null;
407: }
408:
409: /**
410: * Associates a new Connection to this ManagedConnection. Nothing is done
411: * if it has already been associated (enforces no duplicate).
412: */
413: public synchronized void associateConnection(Object o)
414: throws ResourceException {
415: if (Debug.ON && logger != null)
416: logger.log(BasicLevel.DEBUG, "Associates Connection: " + o
417: + " to the MC " + this );
418: if (!logicalConnections.contains(o))
419: logicalConnections.add(o);
420: else if (logger != null)
421: logger.log(BasicLevel.WARN, "Connection: " + o
422: + "has already been associated: ignored!");
423: }
424:
425: /**
426: * Adds a listener to the listeners list if it has not
427: * already been done. This means that duplicates are ignored.
428: * It first creates this list if needed (creation at first add).
429: */
430: public synchronized void addConnectionEventListener(
431: ConnectionEventListener listener) {
432: if (listeners == null)
433: listeners = new ArrayList();
434: if (Debug.ON && logger != null)
435: logger.log(BasicLevel.DEBUG,
436: "Associates ConnectionEventListener: " + listener);
437: if (!listeners.contains(listener))
438: listeners.add(listener);
439: else if (logger != null)
440: logger.log(BasicLevel.WARN, "ConnectionEventListener: "
441: + listener
442: + "has already been associated: ignored!");
443: }
444:
445: /**
446: * Removes a listener from the listeners list. If the list does
447: * not eist (null), or if this listener does not belong to this list,
448: * nothing is done.
449: */
450: public synchronized void removeConnectionEventListener(
451: ConnectionEventListener listener) {
452: if (listeners == null) {
453: if (logger != null) {
454: logger
455: .log(BasicLevel.WARN,
456: "No associated ConnectionEventListener: ignored!");
457: }
458: return;
459: }
460: int ind = listeners.indexOf(listener);
461: if (Debug.ON && logger != null)
462: logger.log(BasicLevel.DEBUG, "Index within the listeners: "
463: + ind);
464: if (ind == -1 && logger != null)
465: logger.log(BasicLevel.WARN, "ConnectionEventListener"
466: + listener + "not associated here: ignored!");
467: else
468: listeners.remove(ind);
469: }
470:
471: /**
472: * Retrieves an XA resource. Switches running mode to XA.
473: */
474: public synchronized XAResource getXAResource()
475: throws ResourceException {
476: if (logger != null) {
477: logger.log(BasicLevel.DEBUG, "getXAResource()");
478: }
479: if (localTransactionPM != null) {
480: throw new ResourceException(
481: "Try switching to XA mode while running a LocalTransaction.");
482: }
483: if (defaultPM != null) {
484: defaultPM.closePOManager();
485: defaultPM = null;
486: }
487: return this ;
488: }
489:
490: public LocalTransaction getLocalTransaction()
491: throws ResourceException {
492: return this ;
493: }
494:
495: public ManagedConnectionMetaData getMetaData()
496: throws ResourceException {
497: return this ;
498: }
499:
500: /**
501: * Not supported yet.
502: */
503: public void setLogWriter(PrintWriter writer)
504: throws ResourceException {
505: throw new ResourceException(
506: "Speedo Connector: logging to PrintWriter not supported yet.");
507: }
508:
509: /**
510: * Not supported yet.
511: */
512: public PrintWriter getLogWriter() throws ResourceException {
513: throw new ResourceException(
514: "Speedo Connector: logging to PrintWriter not supported yet.");
515: }
516:
517: // IMPLEMENTATION OF METHODS FROM THE (cci)LocalTransaction INTERFACE //
518: //--------------------------------------------------------------------//
519:
520: /**
521: * Begins the LocalTransaction if it has not already been started.
522: */
523: public synchronized void begin() throws ResourceException {
524: if (localTransactionPM != null) {
525: throw new ResourceException(
526: "Speedo Connector: a LocalTransaction has already begun.");
527: }
528: try {
529: if (defaultPM != null) {
530: defaultPM.closePOManager();
531: defaultPM = null;
532: }
533: localTransactionPM = (POManagerItf) mcf.pmf.getPOManager();
534: localTransactionPM.getSpeedoTransaction().begin();
535: if (Debug.ON && logger != null)
536: logger.log(BasicLevel.DEBUG,
537: "LocalTransaction begin - txContext: "
538: + localTransactionPM);
539: if (xac != null && logger != null)
540: logger
541: .log(BasicLevel.WARN,
542: "Begins a LocalTransaction on a ManagedConnection that runs in XA mode!");
543: ConnectionEvent ce = new ConnectionEvent(this ,
544: ConnectionEvent.LOCAL_TRANSACTION_STARTED);
545: if (listeners != null) {
546: synchronized (this ) {
547: for (Iterator it = listeners.iterator(); it
548: .hasNext();) {
549: ((ConnectionEventListener) it.next())
550: .localTransactionStarted(ce);
551: }
552: }
553: }
554: } catch (RuntimeException fe) {
555: ResourceException re = new ResourceException(
556: "Speedo Connector: cannot begin LocalTransaction [nested exception].");
557: re.setLinkedException(fe);
558: throw re;
559: }
560: }
561:
562: /**
563: * Commits the LocalTransaction if it is active.
564: */
565: public synchronized void commit() throws ResourceException {
566: if (localTransactionPM == null)
567: throw new ResourceException(
568: "Speedo Connector: no LocalTransaction has been begun.");
569: if (Debug.ON && logger != null)
570: logger.log(BasicLevel.DEBUG,
571: "LocalTransaction commit - txContext: "
572: + localTransactionPM);
573: try {
574: localTransactionPM.getSpeedoTransaction().commit();
575: ConnectionEvent ce = new ConnectionEvent(this ,
576: ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
577: if (listeners != null) {
578: synchronized (this ) {
579: for (Iterator it = listeners.iterator(); it
580: .hasNext();) {
581: ((ConnectionEventListener) it.next())
582: .localTransactionCommitted(ce);
583: }
584: }
585: }
586: } catch (RuntimeException fe) {
587: ResourceException re = new ResourceException(
588: "Speedo Connector: cannot commit LocalTransaction [nested exception].");
589: re.setLinkedException(fe);
590: throw re;
591: } finally {
592: localTransactionPM.closePOManager();
593: localTransactionPM = null;
594: }
595: }
596:
597: /**
598: * Rollbacks the LocalTransaction if it is active.
599: */
600: public synchronized void rollback() throws ResourceException {
601: if (localTransactionPM == null)
602: throw new ResourceException(
603: "Speedo Connector: no LocalTransaction has been begun.");
604: if (Debug.ON && logger != null)
605: logger.log(BasicLevel.DEBUG,
606: "LocalTransaction rollback - txContext: "
607: + localTransactionPM);
608: try {
609: localTransactionPM.getSpeedoTransaction().rollback();
610: ConnectionEvent ce = new ConnectionEvent(this ,
611: ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
612: if (listeners != null) {
613: synchronized (this ) {
614: for (Iterator it = listeners.iterator(); it
615: .hasNext();) {
616: ((ConnectionEventListener) it.next())
617: .localTransactionRolledback(ce);
618: }
619: }
620: }
621: } catch (RuntimeException fe) {
622: ResourceException re = new ResourceException(
623: "Speedo Connector: cannot rollback LocalTransaction [nested exception].");
624: re.setLinkedException(fe);
625: throw re;
626: } finally {
627: localTransactionPM.closePOManager();
628: localTransactionPM = null;
629: }
630: }
631:
632: // IMPLEMENTATION OF METHODS FROM THE (jta)XAResource INTERFACE //
633: //--------------------------------------------------------------//
634:
635: /**
636: * Assigns an actual Speedo transaction context to the XAResource
637: * within the give DTP context.
638: */
639: public void start(Xid xid, int i) throws XAException {
640: try {
641: switch (i) {
642: case XAResource.TMRESUME:
643: if (Debug.ON && logger != null
644: && logger.isLoggable(BasicLevel.DEBUG)) {
645: logger.log(BasicLevel.DEBUG, "start(" + xid
646: + ", TMRESUME)");
647: }
648: xac = getXAContext(xid, 1);
649: if (xac.pm != null) {
650: mcf.pmf.bindPM2Thread(xac.pm);
651: }
652: break;
653: case XAResource.TMJOIN:
654: if (Debug.ON && logger != null
655: && logger.isLoggable(BasicLevel.DEBUG)) {
656: logger.log(BasicLevel.DEBUG, "start(" + xid
657: + ", TMJOIN)");
658: }
659: xac = getXAContext(xid, 1);
660: break;
661: case XAResource.TMNOFLAGS:
662: if (Debug.ON && logger != null
663: && logger.isLoggable(BasicLevel.DEBUG)) {
664: logger.log(BasicLevel.DEBUG, "start(" + xid
665: + ", TMNOFLAGS)");
666: }
667: xac = getXAContext(xid, 0);
668: break;
669: default:
670: String msg = "Unexpected flag: " + i;
671: if (logger != null) {
672: logger.log(BasicLevel.ERROR, msg);
673: }
674: throw new XAException(msg);
675: }
676: xac.status = SpeedoXAContext.STARTED;
677: } catch (XAException e) {
678: if (logger != null) {
679: logger.log(BasicLevel.ERROR,
680: "Error in the Jdo XAResource starting (" + i
681: + ")", e);
682: }
683: throw e;
684: } catch (RuntimeException e) {
685: if (logger != null) {
686: logger.log(BasicLevel.ERROR,
687: "Error in the Jdo XAResource starting (" + i
688: + ")", e);
689: }
690: throw e;
691: }
692: }
693:
694: /**
695: * Unbind this instance to the PersistenceManager.
696: */
697: public void end(Xid xid, int i) throws XAException {
698: if (Debug.ON && logger != null
699: && logger.isLoggable(BasicLevel.DEBUG)) {
700: logger.log(BasicLevel.DEBUG, "xid=" + xid);
701: }
702: SpeedoXAContext _xac = getXAContext(xid, 2);
703: if (_xac != null) {
704: _xac.status = SpeedoXAContext.ENDED;
705: if (xac == _xac) {
706: xac = null;
707: }
708: } // else the XAcontext has been committed or rolled back before the end
709: }
710:
711: /**
712: * Used by JTA in order to verify that it has not already registered a
713: * XAResource to manage this transaction context from this RM. If it is the
714: * case, both XAResource are warned of this fact (endWithNoSameRM = false).
715: * This means that these XAResource will be released at "end" time.
716: * @param resource The resource to be compared against this one wrt RM.
717: */
718: public boolean isSameRM(XAResource resource) throws XAException {
719: boolean res = (resource instanceof SpeedoManagedConnection)
720: && ((SpeedoManagedConnection) resource).mcf == mcf;
721: if (Debug.ON && logger != null
722: && logger.isLoggable(BasicLevel.DEBUG)) {
723: logger.log(BasicLevel.DEBUG, "isSameRM(" + resource + "): "
724: + res);
725: }
726: return res;
727: }
728:
729: // Management of transaction termination: prepare, commit, rollback
730:
731: /**
732: * Prepares the underlying JdoTxContext (prepare phase of the 2PC).
733: */
734: public int prepare(Xid xid) throws XAException {
735: if (Debug.ON && logger != null
736: && logger.isLoggable(BasicLevel.DEBUG)) {
737: logger.log(BasicLevel.DEBUG, "prepare(" + xid + ")");
738: }
739: SpeedoXAContext _xac = getXAContext(xid, 1);
740: if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) {
741: if (_xac.pm == null) {
742: logger.log(BasicLevel.DEBUG, "prepare(" + xid
743: + "): no PersistenceManager");
744: } else {
745: logger.log(BasicLevel.DEBUG, "prepare(" + xid
746: + "): speedo Tx status="
747: + _xac.pm.getSpeedoTransaction().getStatus());
748: }
749: }
750: return XAResource.XA_OK;
751: }
752:
753: /**
754: * Unbind the PersistenceManager to the xid. The real commit is done by the
755: * PersistenceManager registered as a Synchronization.
756: */
757: public void commit(Xid xid, boolean b) throws XAException {
758: if (Debug.ON && logger != null
759: && logger.isLoggable(BasicLevel.DEBUG)) {
760: logger.log(BasicLevel.DEBUG, "commit(" + xid + ", 1PC: "
761: + b + ")");
762: }
763: SpeedoXAContext _xac = mcf.releaseXAContext(xid, true);
764: if (xac == _xac) {
765: this .xac = null;
766: }
767: }
768:
769: /**
770: * Unbind the PersistenceManager to the xid. The real commit is done by the
771: * PersistenceManager registered as a Synchronization.
772: */
773: public void rollback(Xid xid) throws XAException {
774: if (Debug.ON && logger != null
775: && logger.isLoggable(BasicLevel.DEBUG)) {
776: logger.log(BasicLevel.DEBUG, "rollback(" + xid + ")");
777: }
778: SpeedoXAContext _xac = mcf.releaseXAContext(xid, true);
779: if (xac == _xac) {
780: this .xac = null;
781: }
782: }
783:
784: public void forget(Xid xid) throws XAException {
785: SpeedoXAContext _xac = mcf.releaseXAContext(xid, false);
786: if (xac == _xac) {
787: this .xac = null;
788: }
789: }
790:
791: /**
792: * Gets the Xid of distributed transactions to be recovered from the Speedo
793: * manager.
794: */
795: public Xid[] recover(int i) throws XAException {
796: return new Xid[0];
797: }
798:
799: public int getTransactionTimeout() throws XAException {
800: return 0;
801: }
802:
803: public boolean setTransactionTimeout(int i) throws XAException {
804: return false;
805: }
806: }
|