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: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.transaction;
030:
031: import com.caucho.log.Log;
032: import com.caucho.util.L10N;
033:
034: import javax.naming.InitialContext;
035: import javax.transaction.Status;
036: import javax.transaction.Transaction;
037: import javax.transaction.TransactionManager;
038: import javax.transaction.UserTransaction;
039: import java.util.logging.Level;
040: import java.util.logging.Logger;
041:
042: /**
043: * Transaction identifier implementation.
044: */
045: public class TransactionContainer {
046: private static final L10N L = new L10N(TransactionContainer.class);
047: private static final Logger log = Log
048: .open(TransactionContainer.class);
049:
050: private static TransactionContainer _container;
051:
052: private UserTransaction _userTM;
053: private TransactionManager _tm;
054:
055: public static TransactionContainer getTransactionContainer() {
056: if (_container == null) {
057: _container = new TransactionContainer();
058:
059: try {
060: InitialContext ic = new InitialContext();
061:
062: UserTransaction userTM;
063: userTM = (UserTransaction) ic
064: .lookup("java:comp/UserTransaction");
065:
066: _container.setUserTransaction(userTM);
067:
068: TransactionManager tm;
069: tm = (TransactionManager) ic
070: .lookup("java:comp/TransactionManager");
071:
072: _container.setTransactionManager(tm);
073: } catch (Throwable e) {
074: log.log(Level.WARNING, e.toString(), e);
075: }
076: }
077:
078: return _container;
079: }
080:
081: /**
082: * Sets the user transaction.
083: */
084: public void setUserTransaction(UserTransaction userTM) {
085: _userTM = userTM;
086: }
087:
088: /**
089: * Sets the transaction manager.
090: */
091: public void setTransactionManager(TransactionManager tm) {
092: _tm = tm;
093: }
094:
095: /**
096: * Returns a transaction context for the "required" transaction. If
097: * there's already an active transaction, use it. Otherwise create a
098: * new transaction.
099: *
100: * @return the current transaction context
101: */
102: public Transaction beginRequired() {
103: try {
104: Transaction currentTrans = _tm.getTransaction();
105:
106: if (currentTrans != null)
107: return currentTrans;
108:
109: // _userTransaction.setTransactionTimeout((int) (_transactionTimeout / 1000L));
110: _userTM.begin();
111:
112: return null;
113: } catch (RuntimeException e) {
114: throw e;
115: } catch (Exception e) {
116: throw new TransactionRuntimeException(e);
117: }
118: }
119:
120: /**
121: * Returns a transaction context for the "RequiresNew" transaction.
122: * Always creates a new transaction, suspending any old one.
123: *
124: * @return the current transaction context
125: */
126: public Transaction beginRequiresNew() {
127: try {
128: Transaction oldTrans = _tm.getTransaction();
129:
130: if (oldTrans != null)
131: oldTrans = _tm.suspend();
132:
133: // _userTransaction.setTransactionTimeout((int) (_transactionTimeout / 1000L));
134: _userTM.begin();
135:
136: return oldTrans;
137: } catch (RuntimeException e) {
138: throw e;
139: } catch (Exception e) {
140: throw new TransactionRuntimeException(e);
141: }
142: }
143:
144: /**
145: * Require a transaction, throwing an exception if none exists.
146: *
147: * @return the current transaction context
148: */
149: public void beginMandatory() {
150: try {
151: Transaction oldTrans = _tm.getTransaction();
152:
153: if (oldTrans == null)
154: throw new TransactionRuntimeException(
155: L
156: .l("'Mandatory' transaction boundary requires a transaction."));
157: } catch (RuntimeException e) {
158: throw e;
159: } catch (Exception e) {
160: throw new TransactionRuntimeException(e);
161: }
162: }
163:
164: /**
165: * Require no transactions, throwing an exception if one exists.
166: */
167: public void beginNever() {
168: try {
169: Transaction oldTrans = _tm.getTransaction();
170:
171: if (oldTrans != null)
172: throw new TransactionRuntimeException(
173: L
174: .l("'Never' transaction boundary must not have a transaction."));
175: } catch (RuntimeException e) {
176: throw e;
177: } catch (Exception e) {
178: throw new TransactionRuntimeException(e);
179: }
180: }
181:
182: /**
183: * Suspends any active transaction.
184:
185: * @return the current transaction context
186: */
187: public Transaction beginSuspend() {
188: try {
189: Transaction oldTrans = _tm.getTransaction();
190:
191: if (oldTrans != null)
192: oldTrans = _tm.suspend();
193:
194: return oldTrans;
195: } catch (RuntimeException e) {
196: throw e;
197: } catch (Exception e) {
198: throw new TransactionRuntimeException(e);
199: }
200: }
201:
202: /**
203: * Sets a rollback-only transaction.
204: */
205: public void setRollbackOnly(Throwable e) {
206: }
207:
208: /**
209: * Commits the transaction (rolling back if rollback only)
210: */
211: public void commit(Transaction oldTransaction) {
212: try {
213: Transaction currentTrans = _tm.getTransaction();
214:
215: if (currentTrans == null) {
216: } else if (currentTrans.getStatus() != Status.STATUS_MARKED_ROLLBACK)
217: _userTM.commit();
218: else
219: _userTM.rollback();
220: } catch (RuntimeException e) {
221: throw e;
222: } catch (Exception e) {
223: throw new TransactionRuntimeException(e);
224: } finally {
225: if (oldTransaction != null) {
226: try {
227: _tm.resume(oldTransaction);
228: } catch (Exception e) {
229: throw new TransactionRuntimeException(e);
230: }
231: }
232: }
233: }
234:
235: /**
236: * Rolls back any existing transaction.
237: */
238: public void rollback(Transaction oldTransaction) {
239: try {
240: Transaction currentTrans = _tm.getTransaction();
241:
242: if (currentTrans != null)
243: _userTM.rollback();
244: } catch (RuntimeException e) {
245: throw e;
246: } catch (Exception e) {
247: throw new TransactionRuntimeException(e);
248: } finally {
249: if (oldTransaction != null) {
250: try {
251: _tm.resume(oldTransaction);
252: } catch (Exception e) {
253: throw new TransactionRuntimeException(e);
254: }
255: }
256: }
257: }
258: }
|