001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb3.xa;
031:
032: import com.caucho.jca.*;
033: import com.caucho.transaction.*;
034: import com.caucho.util.*;
035:
036: import java.util.logging.*;
037: import javax.ejb.*;
038: import javax.transaction.*;
039: import javax.transaction.xa.*;
040:
041: /**
042: * Manages XA for bean methods.
043: */
044: public class XAManager {
045: private static L10N L = new L10N(XAManager.class);
046: private static Logger log = Logger.getLogger(XAManager.class
047: .getName());
048:
049: private UserTransactionProxy _ut;
050:
051: public XAManager() {
052: _ut = UserTransactionProxy.getInstance();
053: }
054:
055: /**
056: * Enlists a resource
057: */
058: public void enlist(XAResource xaResource) {
059: try {
060: TransactionManagerImpl tm = TransactionManagerImpl
061: .getLocal();
062:
063: Transaction xa = tm.getTransaction();
064:
065: if (xa != null && xaResource != null)
066: xa.enlistResource(xaResource);
067: } catch (RuntimeException e) {
068: throw e;
069: } catch (Exception e) {
070: throw new EJBException(e);
071: }
072: }
073:
074: /**
075: * Enlists a resource
076: */
077: public void registerSynchronization(SessionSynchronization sync) {
078: try {
079: TransactionManagerImpl tm = TransactionManagerImpl
080: .getLocal();
081:
082: Transaction xa = tm.getTransaction();
083:
084: if (xa != null && sync != null) {
085: sync.afterBegin();
086:
087: xa.registerSynchronization(new SynchronizationAdapter(
088: sync));
089: }
090: } catch (RuntimeException e) {
091: throw e;
092: } catch (Exception e) {
093: throw new EJBException(e);
094: }
095: }
096:
097: /**
098: * Begins a manadatory transaction.
099: */
100: public void beginMandatory() {
101: try {
102: TransactionManagerImpl tm = TransactionManagerImpl
103: .getLocal();
104:
105: Transaction xa = tm.getTransaction();
106:
107: if (xa == null)
108: throw new EJBTransactionRequiredException(
109: L
110: .l("Transaction required for for 'Mandatory' TransactionAttribute"));
111: } catch (RuntimeException e) {
112: throw e;
113: } catch (Exception e) {
114: throw new EJBException(e);
115: }
116: }
117:
118: /**
119: * Begins a never transaction.
120: */
121: public void beginNever() {
122: try {
123: TransactionManagerImpl tm = TransactionManagerImpl
124: .getLocal();
125:
126: Transaction xa = tm.getTransaction();
127:
128: if (xa != null)
129: throw new EJBException(
130: L
131: .l("Transaction forbidden for 'Never' TransactionAttribute"));
132: } catch (RuntimeException e) {
133: throw e;
134: } catch (Exception e) {
135: throw new EJBException(e);
136: }
137: }
138:
139: /**
140: * Begins a required transaction.
141: *
142: * @return the current transaction if it exists
143: */
144: public Transaction beginRequired() {
145: try {
146: TransactionManagerImpl tm = TransactionManagerImpl
147: .getLocal();
148:
149: Transaction xa = tm.getTransaction();
150:
151: if (xa != null)
152: return xa;
153:
154: _ut.begin();
155:
156: return null;
157: } catch (RuntimeException e) {
158: throw e;
159: } catch (Exception e) {
160: throw new EJBException(e);
161: }
162: }
163:
164: /**
165: * Begins a requires-new transaction.
166: *
167: * @return the current transaction if it exists
168: */
169: public Transaction beginRequiresNew() {
170: try {
171: TransactionManagerImpl tm = TransactionManagerImpl
172: .getLocal();
173:
174: Transaction xa = tm.suspend();
175:
176: _ut.begin();
177:
178: return xa;
179: } catch (RuntimeException e) {
180: throw e;
181: } catch (Exception e) {
182: throw new EJBException(e);
183: }
184: }
185:
186: /**
187: * Begins a requires-new transaction.
188: *
189: * @return the current transaction if it exists
190: */
191: public void endRequiresNew(Transaction xa) {
192: try {
193: _ut.commit();
194: } catch (RuntimeException e) {
195: throw e;
196: } catch (Exception e) {
197: throw new EJBException(e);
198: } finally {
199: try {
200: if (xa != null) {
201: TransactionManagerImpl tm = TransactionManagerImpl
202: .getLocal();
203:
204: tm.resume(xa);
205: }
206: } catch (RuntimeException e) {
207: throw e;
208: } catch (Exception e) {
209: throw new EJBException(e);
210: }
211: }
212: }
213:
214: /**
215: * Begins a not-supported transaction, i.e. suspend any current transaction.
216: *
217: * @return the current transaction if it exists
218: */
219: public Transaction beginNotSupported() {
220: try {
221: TransactionManagerImpl tm = TransactionManagerImpl
222: .getLocal();
223:
224: return tm.suspend();
225: } catch (RuntimeException e) {
226: throw e;
227: } catch (Exception e) {
228: throw new EJBException(e);
229: }
230: }
231:
232: /**
233: * Mark the transaction for rollback
234: */
235: public void markRollback(Exception e) {
236: _ut.setRollbackOnly(e);
237: }
238:
239: /**
240: * Commits transaction.
241: */
242: public void commit() {
243: try {
244: _ut.commit();
245: } catch (RuntimeException e) {
246: throw e;
247: } catch (RollbackException e) {
248: throw new TransactionRolledbackLocalException(e
249: .getMessage(), e);
250: } catch (HeuristicMixedException e) {
251: throw new TransactionRolledbackLocalException(e
252: .getMessage(), e);
253: } catch (HeuristicRollbackException e) {
254: throw new TransactionRolledbackLocalException(e
255: .getMessage(), e);
256: } catch (Exception e) {
257: throw new EJBException(e);
258: }
259: }
260:
261: /**
262: * Resumes transaction.
263: */
264: public void resume(Transaction xa) {
265: try {
266: TransactionManagerImpl tm = TransactionManagerImpl
267: .getLocal();
268:
269: tm.resume(xa);
270: } catch (RuntimeException e) {
271: throw e;
272: } catch (Exception e) {
273: throw new EJBException(e);
274: }
275: }
276:
277: public static class SynchronizationAdapter implements
278: Synchronization {
279: private final SessionSynchronization _sync;
280:
281: SynchronizationAdapter(SessionSynchronization sync) {
282: _sync = sync;
283: }
284:
285: public void beforeCompletion() {
286: try {
287: _sync.beforeCompletion();
288: } catch (RuntimeException e) {
289: throw e;
290: } catch (Exception e) {
291: throw new EJBException(e);
292: }
293: }
294:
295: public void afterCompletion(int status) {
296: try {
297: _sync
298: .afterCompletion(status == Status.STATUS_COMMITTED);
299: } catch (RuntimeException e) {
300: throw e;
301: } catch (Exception e) {
302: throw new EJBException(e);
303: }
304: }
305:
306: public String toString() {
307: return getClass().getSimpleName() + "[" + _sync + "]";
308: }
309: }
310:
311: public String toString() {
312: return "XAManager[]";
313: }
314: }
|