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