001: /*
002: * @(#) XATerminatorImpl.java 1.2 02/01/15
003: *
004: * JOTM: Java Open Transaction Manager
005: *
006: * This module was originally developed by
007: *
008: * - Bull S.A. as part of the JOnAS application server code released in
009: * July 1999 (www.bull.com)
010: *
011: * --------------------------------------------------------------------------
012: * The original code and portions created by Bull SA are
013: * Copyright (c) 1999 BULL SA
014: * All rights reserved.
015: *
016: * Redistribution and use in source and binary forms, with or without
017: * modification, are permitted provided that the following conditions are met:
018: *
019: * -Redistributions of source code must retain the above copyright notice, this
020: * list of conditions and the following disclaimer.
021: *
022: * -Redistributions in binary form must reproduce the above copyright notice,
023: * this list of conditions and the following disclaimer in the documentation
024: * and/or other materials provided with the distribution.
025: *
026: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
027: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
028: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
029: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
030: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
031: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
032: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
033: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
034: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
035: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
036: * POSSIBILITY OF SUCH DAMAGE.
037: * --------------------------------------------------------------------------
038: *
039: * Contributor:
040: * 04/01/15 Tony Ortiz
041: *
042: * --------------------------------------------------------------------------
043: * $Id: XATerminatorImpl.java,v 1.5 2004/11/05 19:54:59 tonyortiz Exp $
044: * --------------------------------------------------------------------------
045: */
046: package org.objectweb.jotm;
047:
048: import javax.transaction.xa.Xid;
049:
050: import javax.resource.spi.XATerminator;
051:
052: import javax.transaction.xa.XAException;
053:
054: /**
055: * Implementation of the object that represents an inflow transaction.
056: *
057: */
058:
059: public class XATerminatorImpl implements XATerminator {
060:
061: // Must be init at null, for clients that do not get UserTransaction
062: private transient static XATerminatorImpl unique = null;
063:
064: // ------------------------------------------------------------------
065: // Constructors
066: // ------------------------------------------------------------------
067:
068: /**
069: * @serial
070: */
071: private TransactionImpl iftx = null;
072: /**
073: * @serial
074: */
075: private Xid xid;
076: /**
077: * @serial
078: */
079: private Log mylog;
080:
081: // XAException values
082:
083: private int errorCode;
084: private final static int XA_RBBASE = 100;
085: private final static int XA_RBROLLBACK = XA_RBBASE;
086: private final static int XA_RBCOMMFAIL = XA_RBBASE + 1;
087: private final static int XA_RBDEADLOCK = XA_RBBASE + 2;
088: private final static int XA_RBINTEGRITY = XA_RBBASE + 3;
089: private final static int XA_RBOTHER = XA_RBBASE + 4;
090: private final static int XA_RBPROTO = XA_RBBASE + 5;
091: private final static int XA_RBRBTIMEOUT = XA_RBBASE + 6;
092: private final static int XA_RBTRANSIENT = XA_RBBASE + 7;
093: private final static int XA_RBEND = XA_RBTRANSIENT;
094: private final static int XA_NOMIGRATE = 9;
095: private final static int XA_HEURHAZ = 8;
096: private final static int XA_HEURCOM = 7;
097: private final static int XA_HEURRB = 6;
098: private final static int XA_HEURMIX = 5;
099: private final static int XA_NOTUSED1 = 4;
100: private final static int XA_RDONLY = 3;
101: // Error Codes
102: private final static int XAER_RMERR = -3;
103: private final static int XAER_NOTA = -4;
104: private final static int XAER_INVAL = -5;
105: private final static int XAER_PROTO = -6;
106: private final static int XAER_RMFAIL = -7;
107: private final static int XAER_DUPID = -8;
108: private final static int XAER_OUTSIDE = -9;
109:
110: // ---------------------------------------------------------------
111: // Constructors
112: // ---------------------------------------------------------------
113:
114: /**
115: * Constructor for create
116: *
117: */
118:
119: public XATerminatorImpl() throws XAException {
120:
121: if (TraceTm.jotm.isDebugEnabled()) {
122: TraceTm.jotm.debug("create XATerminator");
123: }
124:
125: unique = this ;
126: }
127:
128: // ------------------------------------------------------------------
129: // Inflow Transaction implementation
130: // ------------------------------------------------------------------
131:
132: /**
133: * Gets a String that represents the inflow transaction name.
134: *
135: * @return Transaction Name
136: */
137:
138: public String get_transaction_name() throws XAException {
139:
140: TraceTm.jotm.debug("XATerminatorImpl.get_transaction_name()");
141:
142: return xid.toString();
143: }
144:
145: /**
146: * Commits the global transaction specified by xid.
147: *
148: * @param xid A global transaction identifier
149: * @param onePhase If true, the resource manager should use one-phase commit protocol
150: * to commit the work done on behalf of xid.
151: *
152: * @exception XAException An error has occurred. Possible XAExceptions
153: * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
154: * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
155: *
156: * If the resouce manager did not commit the transaction and the parameter onePhase is set to
157: * true, the resource manager may throw one of the XA_RB* exceptions. Upon return, the
158: * resource manager has rolled back the branch's work and has released all help resources.
159: */
160:
161: public void commit(Xid xid, boolean onePhase) throws XAException {
162:
163: if (TraceTm.jotm.isDebugEnabled()) {
164: TraceTm.jotm.debug("commit xid=" + xid + "onePhase="
165: + onePhase);
166: }
167:
168: // get the transaction associated with the passed Xid
169: // if the Xid passed was not corrected the commit will fail
170:
171: XidImpl myxid = new XidImpl(xid);
172: iftx = Current.getCurrent().getTxByXid(myxid);
173:
174: if (iftx == null) {
175: TraceTm.jotm
176: .error("XATerminatorImpl.commit(): unknown xid "
177: + xid);
178: throw new XAException(XAER_NOTA);
179: }
180:
181: try {
182: iftx.commit();
183: } catch (Exception e) {
184: TraceTm.jotm
185: .error(
186: "XATerminatorImpl.commit(): commit raised exception ",
187: e);
188: }
189: }
190:
191: /**
192: * Informs the resource manager to roll back work done on behalf of a transaction branch.
193: *
194: * @param xid A global transaction identifier.
195: *
196: * @exception XAException An error has occurred. Possible XAExceptions
197: * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
198: * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
199: *
200: * If the transaction branch is already marked rollback-only the resource manager may throw
201: * one of the XA_RB* exceptions. Upon return, the resource manager has rolled back the
202: * branch's work and has released all held resources.
203: */
204:
205: public void rollback(Xid xid) throws XAException {
206:
207: if (TraceTm.jotm.isDebugEnabled()) {
208: TraceTm.jotm.debug("rollback xid=" + xid);
209: }
210:
211: // get the transaction associated with the passed Xid
212: // if the Xid passed was not corrected the rollback will fail
213:
214: XidImpl myxid = new XidImpl(xid);
215: iftx = Current.getCurrent().getTxByXid(myxid);
216:
217: if (iftx == null) {
218: TraceTm.jotm
219: .error("XATerminatorImpl.rollback(): unknown xid "
220: + xid);
221: throw new XAException(XAER_NOTA);
222: }
223:
224: try {
225: iftx.rollback();
226: } catch (Exception e) {
227: TraceTm.jotm
228: .error(
229: "XATerminatorImpl.rollback(): rollback raised exception ",
230: e);
231: }
232: }
233:
234: /**
235: * Ask the resource manager to prepare for a transaction commit of the transaction specified in xid.
236: *
237: * @param xid A global transaction identifier.
238: *
239: * @exception XAException An error has occurred. Possible XAExceptions
240: * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
241: * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
242: *
243: * @return A value indicating the resource manager's vote on the outcome of the transaction. The
244: * possible values are: XA_RDONLY or XA_OK. These constants are defined in
245: * javax.transaction.xa.XAResource interface. If the resource manager wants to roll back
246: * the transaction, it should do so by raising an appropriate XAException in the prepare
247: * method.
248: */
249:
250: public int prepare(Xid xid) throws XAException {
251:
252: int ret = 0;
253:
254: if (TraceTm.jotm.isDebugEnabled()) {
255: TraceTm.jotm.debug("prepare xid=" + xid);
256: }
257:
258: // get the transaction associated with the passed Xid
259: // if the Xid passed was not corrected the prepare will fail
260:
261: XidImpl myxid = new XidImpl(xid);
262: iftx = Current.getCurrent().getTxByXid(myxid);
263:
264: if (iftx == null) {
265: TraceTm.jotm
266: .error("XATerminatorImpl.prepare(): unknown xid "
267: + xid);
268: throw new XAException(XAER_NOTA);
269: }
270:
271: try {
272: ret = iftx.prepare();
273: } catch (Exception e) {
274: TraceTm.jotm
275: .error(
276: "XATerminatorImpl.prepare(): prepare raised exception ",
277: e);
278: }
279:
280: return ret;
281: }
282:
283: /**
284: * Tells the resource manager to forget about a heuristically completed transaction branch.
285: *
286: * @param xid A global transaction identifier.
287: *
288: * @exception XAException An error has occurred. Possible XAExceptions
289: * are XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
290: */
291:
292: public void forget(Xid xid) throws XAException {
293:
294: TraceTm.jotm.debug("XATerminatorImpl.forget()");
295:
296: // get the transaction associated with the passed Xid
297: // if the Xid passed was not corrected the forget will fail
298:
299: XidImpl myxid = new XidImpl(xid);
300:
301: try {
302: Current.getCurrent().forgetTx(myxid);
303: } catch (Exception e) {
304: TraceTm.jotm
305: .error(
306: "XATerminatorImpl.forget(): forget raised exception ",
307: e);
308: }
309: }
310:
311: /**
312: * Obtains a list of prepared transaction branches from a resource manager. The transaction manager
313: * calls this method during recovery to obtain the list of transaction branches that are currently in
314: * prepared or heuristically completed states.
315: *
316: * @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMHOFLAGS must
317: * be used when no other flags are set in the parameter. These constants are defined in
318: * javax.transaction.xa.XAResource interface.
319: *
320: * @exception XAException An error has occurred. Possible values
321: * are XAER_RMERR, XAER_RMFAIL, XAER_INVAL, or XAER_PROTO.
322: *
323: * @return The resource manager returns zero or more XIDs of the transaction branches that are
324: * currently in a prepared or heuristically completed state. If an error occurs during the
325: * operation, the resource manager should throw the appropriate XAException.
326: */
327:
328: public Xid[] recover(int flag) throws XAException {
329:
330: TraceTm.jotm.debug("XATerminatorImpl.recover()");
331:
332: // get a list of transaction in the prepared or heuristically complete states
333:
334: return (Xid[]) Current.getCurrent().getPreparedHeuristicXid();
335:
336: }
337:
338: }
|