1
2
3
4
5
6
7 package org.mule.util.xa;
8
9 import javax.transaction.Status;
10 import javax.transaction.xa.XAException;
11 import javax.transaction.xa.XAResource;
12 import javax.transaction.xa.Xid;
13
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16
17
18
19
20 public class DefaultXASession implements XAResource
21 {
22
23
24
25
26 protected transient Log logger = LogFactory.getLog(getClass());
27
28 protected AbstractTransactionContext localContext;
29 protected Xid localXid;
30 protected AbstractXAResourceManager resourceManager;
31
32 public DefaultXASession(AbstractXAResourceManager resourceManager)
33 {
34 this.localContext = null;
35 this.localXid = null;
36 this.resourceManager = resourceManager;
37 }
38
39 public XAResource getXAResource()
40 {
41 return this;
42 }
43
44 public Object getResourceManager()
45 {
46 return resourceManager;
47 }
48
49
50
51
52 public void begin() throws ResourceManagerException
53 {
54 if (localXid != null)
55 {
56 throw new IllegalStateException(
57 "Cannot start local transaction. An XA transaction is already in progress.");
58 }
59 if (localContext != null)
60 {
61 throw new IllegalStateException(
62 "Cannot start local transaction. A local transaction already in progress.");
63 }
64 localContext = resourceManager.createTransactionContext(this);
65 resourceManager.beginTransaction(localContext);
66 }
67
68 public void commit() throws ResourceManagerException
69 {
70 if (localXid != null)
71 {
72 throw new IllegalStateException(
73 "Cannot commit local transaction as an XA transaction is in progress.");
74 }
75 if (localContext == null)
76 {
77 throw new IllegalStateException("Cannot commit local transaction as no transaction was begun");
78 }
79 resourceManager.commitTransaction(localContext);
80 localContext = null;
81 }
82
83 public void rollback() throws ResourceManagerException
84 {
85 if (localXid != null)
86 {
87 throw new IllegalStateException(
88 "Cannot rollback local transaction as an XA transaction is in progress.");
89 }
90 if (localContext == null)
91 {
92 throw new IllegalStateException("Cannot commit local transaction as no transaction was begun");
93 }
94 resourceManager.rollbackTransaction(localContext);
95 localContext = null;
96 }
97
98
99
100
101
102 public boolean isSameRM(XAResource xares) throws XAException
103 {
104 return xares instanceof DefaultXASession
105 && ((DefaultXASession) xares).getResourceManager().equals(resourceManager);
106 }
107
108 public Xid[] recover(int flag) throws XAException
109 {
110 return null;
111 }
112
113 public void start(Xid xid, int flags) throws XAException
114 {
115 if (logger.isDebugEnabled())
116 {
117 logger.debug(new StringBuffer(128).append("Thread ").append(Thread.currentThread()).append(
118 flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes").append(
119 " work on behalf of transaction branch ").append(xid).toString());
120 }
121
122 if (this.localContext != null)
123 {
124 throw new XAException(XAException.XAER_PROTO);
125 }
126
127 if (this.localXid != null)
128 {
129 throw new XAException(XAException.XAER_PROTO);
130 }
131 switch (flags)
132 {
133
134 case TMNOFLAGS :
135 case TMJOIN :
136 default :
137 try
138 {
139 localContext = resourceManager.createTransactionContext(this);
140 resourceManager.beginTransaction(localContext);
141 }
142 catch (Exception e)
143 {
144
145 logger.error("Could not create new transactional resource", e);
146 throw (XAException) new XAException(e.getMessage()).initCause(e);
147 }
148 break;
149 case TMRESUME :
150 localContext = resourceManager.getSuspendedTransactionalResource(xid);
151 if (localContext == null)
152 {
153 throw new XAException(XAException.XAER_NOTA);
154 }
155
156 resourceManager.removeSuspendedTransactionalResource(xid);
157 break;
158 }
159 localXid = xid;
160 resourceManager.addActiveTransactionalResource(localXid, localContext);
161 }
162
163 public void end(Xid xid, int flags) throws XAException
164 {
165 if (logger.isDebugEnabled())
166 {
167 logger.debug(new StringBuffer(128).append("Thread ").append(Thread.currentThread()).append(
168 flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends").append(
169 " work on behalf of transaction branch ").append(xid).toString());
170 }
171
172 if (localContext == null)
173 {
174 throw new XAException(XAException.XAER_NOTA);
175 }
176
177 if (localXid == null || !localXid.equals(xid))
178 {
179 throw new XAException(XAException.XAER_PROTO);
180 }
181
182 try
183 {
184 switch (flags)
185 {
186 case TMSUSPEND :
187
188 resourceManager.addSuspendedTransactionalResource(localXid, localContext);
189 resourceManager.removeActiveTransactionalResource(localXid);
190 break;
191 case TMFAIL :
192 resourceManager.setTransactionRollbackOnly(localContext);
193 break;
194 case TMSUCCESS :
195 default :
196 break;
197 }
198 }
199 catch (ResourceManagerException e)
200 {
201 throw (XAException) new XAException(XAException.XAER_RMERR).initCause(e);
202 }
203 localXid = null;
204 localContext = null;
205 }
206
207 public void commit(Xid xid, boolean onePhase) throws XAException
208 {
209 if (xid == null)
210 {
211 throw new XAException(XAException.XAER_PROTO);
212 }
213 AbstractTransactionContext context = resourceManager.getActiveTransactionalResource(xid);
214 if (context == null)
215 {
216 throw new XAException(XAException.XAER_NOTA);
217 }
218 if (logger.isDebugEnabled())
219 {
220 logger.debug("Committing transaction branch " + xid);
221 }
222 if (context.status == Status.STATUS_MARKED_ROLLBACK)
223 {
224 throw new XAException(XAException.XA_RBROLLBACK);
225 }
226
227 try
228 {
229 if (context.status != Status.STATUS_PREPARED)
230 {
231 if (onePhase)
232 {
233 resourceManager.prepareTransaction(context);
234 }
235 else
236 {
237 throw new XAException(XAException.XAER_PROTO);
238 }
239 }
240 resourceManager.commitTransaction(context);
241 }
242 catch (ResourceManagerException e)
243 {
244 throw (XAException) new XAException(XAException.XAER_RMERR).initCause(e);
245 }
246 resourceManager.removeActiveTransactionalResource(xid);
247 resourceManager.removeSuspendedTransactionalResource(xid);
248 }
249
250 public void rollback(Xid xid) throws XAException
251 {
252 if (xid == null)
253 {
254 throw new XAException(XAException.XAER_PROTO);
255 }
256 AbstractTransactionContext context = resourceManager.getActiveTransactionalResource(xid);
257 if (context == null)
258 {
259 throw new XAException(XAException.XAER_NOTA);
260 }
261 if (logger.isDebugEnabled())
262 {
263 logger.debug("Rolling back transaction branch " + xid);
264 }
265 try
266 {
267 resourceManager.rollbackTransaction(context);
268 }
269 catch (ResourceManagerException e)
270 {
271 throw (XAException) new XAException(XAException.XAER_RMERR).initCause(e);
272 }
273 resourceManager.removeActiveTransactionalResource(xid);
274 resourceManager.removeSuspendedTransactionalResource(xid);
275 }
276
277 public int prepare(Xid xid) throws XAException
278 {
279 if (xid == null)
280 {
281 throw new XAException(XAException.XAER_PROTO);
282 }
283
284 AbstractTransactionContext context = resourceManager.getTransactionalResource(xid);
285 if (context == null)
286 {
287 throw new XAException(XAException.XAER_NOTA);
288 }
289
290 if (logger.isDebugEnabled())
291 {
292 logger.debug("Preparing transaction branch " + xid);
293 }
294
295 if (context.status == Status.STATUS_MARKED_ROLLBACK)
296 {
297 throw new XAException(XAException.XA_RBROLLBACK);
298 }
299
300 try
301 {
302 return resourceManager.prepareTransaction(context);
303 }
304 catch (ResourceManagerException e)
305 {
306 throw (XAException) new XAException(XAException.XAER_RMERR).initCause(e);
307 }
308 }
309
310 public void forget(Xid xid) throws XAException
311 {
312 if (logger.isDebugEnabled())
313 {
314 logger.debug("Forgetting transaction branch " + xid);
315 }
316 AbstractTransactionContext context = resourceManager.getTransactionalResource(xid);
317 if (context == null)
318 {
319 throw new XAException(XAException.XAER_NOTA);
320 }
321 resourceManager.removeActiveTransactionalResource(xid);
322 resourceManager.removeSuspendedTransactionalResource(xid);
323 }
324
325 public int getTransactionTimeout() throws XAException
326 {
327 return (int)(resourceManager.getDefaultTransactionTimeout() / 1000);
328 }
329
330 public boolean setTransactionTimeout(int timeout) throws XAException
331 {
332 resourceManager.setDefaultTransactionTimeout(timeout * 1000);
333 return false;
334 }
335
336 }