001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.mq;
023:
024: import javax.transaction.xa.XAException;
025: import javax.transaction.xa.XAResource;
026: import javax.transaction.xa.Xid;
027:
028: import org.jboss.logging.Logger;
029:
030: /**
031: * This class implements the XAResource interface for used with an XASession.
032: *
033: * @author Hiram Chirino (Cojonudo14@hotmail.com)
034: * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
035: * @version $Revision: 57198 $
036: */
037: public class SpyXAResource implements XAResource {
038: /** The log */
039: private static final Logger log = Logger
040: .getLogger(SpyXAResource.class);
041:
042: /** Whether trace is enabled */
043: private static boolean trace = log.isTraceEnabled();
044:
045: /** The session */
046: SpySession session;
047:
048: /**
049: * Create a new SpyXAResource
050: *
051: * @param session the session
052: */
053: SpyXAResource(SpySession session) {
054: trace = log.isTraceEnabled();
055:
056: this .session = session;
057:
058: if (trace)
059: log.trace("Created " + this );
060: }
061:
062: public boolean setTransactionTimeout(int arg1) throws XAException {
063: return false;
064: }
065:
066: public int getTransactionTimeout() throws XAException {
067: return 0;
068: }
069:
070: public boolean isSameRM(XAResource arg1) throws XAException {
071: if (!(arg1 instanceof SpyXAResource))
072: return false;
073: return ((SpyXAResource) arg1).session.connection.spyXAResourceManager == session.connection.spyXAResourceManager;
074: }
075:
076: public void commit(Xid xid, boolean onePhase) throws XAException {
077: if (trace)
078: log.trace("Commit xid=" + xid + ", onePhase=" + onePhase
079: + " " + this );
080:
081: xid = convertXid(xid);
082: try {
083: session.connection.spyXAResourceManager.commit(xid,
084: onePhase);
085: } catch (Throwable t) {
086: throw SpyXAException.getAsXAException(
087: "Resource manager error during commit", t);
088: }
089: }
090:
091: public void end(Xid xid, int flags) throws XAException {
092: if (trace)
093: log.trace("End xid=" + xid + ", flags=" + flags + " "
094: + this );
095:
096: xid = convertXid(xid);
097: synchronized (session.runLock) {
098:
099: switch (flags) {
100: case TMSUSPEND:
101: session.unsetCurrentTransactionId(xid);
102: session.connection.spyXAResourceManager.suspendTx(xid);
103: break;
104: case TMFAIL:
105: session.unsetCurrentTransactionId(xid);
106: session.connection.spyXAResourceManager.endTx(xid,
107: false);
108: break;
109: case TMSUCCESS:
110: session.unsetCurrentTransactionId(xid);
111: session.connection.spyXAResourceManager
112: .endTx(xid, true);
113: break;
114: }
115: }
116: }
117:
118: public void forget(Xid xid) throws XAException {
119: if (trace)
120: log.trace("Forget xid=" + xid + " " + this );
121:
122: xid = convertXid(xid);
123: try {
124: session.connection.spyXAResourceManager.forget(xid);
125: } catch (Throwable t) {
126: throw SpyXAException.getAsXAException(
127: "Resource manager error during forget", t);
128: }
129: }
130:
131: public int prepare(Xid xid) throws XAException {
132: if (trace)
133: log.trace("Prepare xid=" + xid + " " + this );
134:
135: xid = convertXid(xid);
136: try {
137: return session.connection.spyXAResourceManager.prepare(xid);
138: } catch (Throwable t) {
139: throw SpyXAException.getAsXAException(
140: "Resource manager error during prepare", t);
141: }
142: }
143:
144: public Xid[] recover(int arg1) throws XAException {
145: if (trace)
146: log.trace("Recover arg1=" + arg1 + " " + this );
147:
148: try {
149: return session.connection.spyXAResourceManager
150: .recover(arg1);
151: } catch (Throwable t) {
152: throw SpyXAException.getAsXAException(
153: "Resource manager error during recover", t);
154: }
155: }
156:
157: public void rollback(Xid xid) throws XAException {
158: if (trace)
159: log.trace("Rollback xid=" + xid + " " + this );
160:
161: xid = convertXid(xid);
162: try {
163: session.connection.spyXAResourceManager.rollback(xid);
164: } catch (Throwable t) {
165: throw SpyXAException.getAsXAException(
166: "Resource manager error during rollback", t);
167: }
168: }
169:
170: public void start(Xid xid, int flags) throws XAException {
171: if (trace)
172: log.trace("Start xid=" + xid + ", flags=" + flags + " "
173: + this );
174:
175: xid = convertXid(xid);
176:
177: boolean convertTx = false;
178: if (session.getCurrentTransactionId() != null) {
179: if (flags == TMNOFLAGS
180: && session.getCurrentTransactionId() instanceof Long) {
181: convertTx = true;
182: } else {
183: XAException e = new XAException("Attempt to enlist in "
184: + xid
185: + " with TMNOFLAGS when already enlisted "
186: + session.getCurrentTransactionId());
187: e.errorCode = XAException.XAER_OUTSIDE; // REVIEW: Is this the correct error code?
188: throw e;
189: }
190: }
191:
192: synchronized (session.runLock) {
193:
194: switch (flags) {
195: case TMNOFLAGS:
196: if (convertTx) {
197: // it was an anonymous TX, TM is now taking control over it.
198: // convert it over to a normal XID tansaction.
199: session
200: .setCurrentTransactionId(session.connection.spyXAResourceManager
201: .convertTx((Long) session
202: .getCurrentTransactionId(),
203: xid));
204: } else {
205: session
206: .setCurrentTransactionId(session.connection.spyXAResourceManager
207: .startTx(xid));
208: }
209: break;
210: case TMJOIN:
211: session
212: .setCurrentTransactionId(session.connection.spyXAResourceManager
213: .joinTx(xid));
214: break;
215: case TMRESUME:
216: session
217: .setCurrentTransactionId(session.connection.spyXAResourceManager
218: .resumeTx(xid));
219: break;
220: }
221: session.runLock.notify();
222: }
223: }
224:
225: public String toString() {
226: return "SpyXAResource[session=" + session + ']';
227: }
228:
229: /**
230: * Convert the external xid to our internal one
231: *
232: * @param xid the xid
233: * @return our internal xid
234: * @throws XAException for a null xid
235: */
236: protected Xid convertXid(Xid xid) throws XAException {
237: if (xid == null) {
238: XAException e = new XAException("Null xid");
239: e.errorCode = XAException.XAER_NOTA;
240: throw e;
241: }
242:
243: if (xid instanceof JBossMQXid)
244: return xid;
245:
246: return new JBossMQXid(xid);
247: }
248: }
|