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.test.tm.resource;
023:
024: import java.io.Serializable;
025: import java.util.HashMap;
026:
027: import javax.naming.InitialContext;
028: import javax.transaction.Status;
029: import javax.transaction.Transaction;
030: import javax.transaction.TransactionManager;
031:
032: import org.jboss.logging.Logger;
033:
034: /**
035: * Operations
036: * @author Adrian@jboss.org
037: * @version $Revision: 57211 $
038: */
039: public class Operation implements Serializable {
040: static final long serialVersionUID = 6263843332702708629L;
041: public static final int BEGIN = -1;
042: public static final int COMMIT = -2;
043: public static final int ROLLBACK = -3;
044: public static final int SUSPEND = -4;
045: public static final int RESUME = -5;
046: public static final int SETROLLBACK = -6;
047: public static final int STATUS = -7;
048: public static final int STATE = 0;
049: public static final int CREATE = 1;
050: public static final int ENLIST = 2;
051: public static final int DIFFRM = 3;
052: public static final int SETSTATUS = 4;
053: public static final int CREATE_LOCAL = 5;
054: public static final int FAIL_LOCAL = 6;
055:
056: static HashMap resources = new HashMap();
057: static HashMap transactions = new HashMap();
058:
059: static Logger log;
060:
061: static TransactionManager tm = null;
062:
063: Integer id;
064: int op;
065: int status;
066: Throwable throwable;
067:
068: public Operation(int op, int id) {
069: this (op, id, 0);
070: }
071:
072: public Operation(int op, int id, int status) {
073: this (op, id, status, null);
074: }
075:
076: public Operation(int op, int id, int status, Throwable throwable) {
077: this .id = new Integer(id);
078: this .op = op;
079: this .status = status;
080: this .throwable = throwable;
081: }
082:
083: public void perform() throws Exception {
084: Throwable caught = null;
085: try {
086: switch (op) {
087: case BEGIN:
088: begin();
089: break;
090: case COMMIT:
091: commit();
092: break;
093: case ROLLBACK:
094: rollback();
095: break;
096: case SUSPEND:
097: suspend();
098: break;
099: case RESUME:
100: resume();
101: break;
102: case SETROLLBACK:
103: setRollbackOnly();
104: break;
105: case STATUS:
106: checkStatus();
107: break;
108: case STATE:
109: checkState();
110: break;
111: case CREATE:
112: create();
113: break;
114: case CREATE_LOCAL:
115: createLocal();
116: break;
117: case FAIL_LOCAL:
118: failLocal();
119: break;
120: case ENLIST:
121: enlist();
122: break;
123: case DIFFRM:
124: differentRM();
125: break;
126: case SETSTATUS:
127: setStatus();
128: break;
129: default:
130: throw new IllegalArgumentException("Invalid operation "
131: + op);
132: }
133: } catch (Throwable t) {
134: caught = t;
135: }
136: if (throwable != null && caught == null)
137: throw new Exception("Expected throwable " + throwable);
138: if (throwable != null
139: && (throwable.getClass().isAssignableFrom(caught
140: .getClass())) == false) {
141: caught.printStackTrace();
142: throw new Exception("Expected throwable " + throwable
143: + " was " + caught);
144: }
145: if (throwable == null && caught != null) {
146: caught.printStackTrace();
147: throw new Exception("Unexpected throwable " + caught);
148: }
149: }
150:
151: public void begin() throws Exception {
152: log.info("BEGIN " + id);
153: getTM().begin();
154: Transaction tx = getTM().getTransaction();
155: transactions.put(id, tx);
156: log.info("BEGUN " + tx);
157: }
158:
159: public void commit() throws Exception {
160: log.info("COMMIT " + id);
161: assertTx(id);
162: getTM().commit();
163: int status = getTM().getStatus();
164: if (Status.STATUS_NO_TRANSACTION != status)
165: throw new Exception(
166: "Expected no thread association after commit status="
167: + status);
168: log.info("COMMITTED " + id);
169: }
170:
171: public void rollback() throws Exception {
172: log.info("ROLLBACK " + id);
173: assertTx(id);
174: getTM().rollback();
175: int status = getTM().getStatus();
176: if (Status.STATUS_NO_TRANSACTION != status)
177: throw new Exception(
178: "Expected no thread association after rollback status="
179: + status);
180: log.info("ROLLEDBACK " + id);
181: }
182:
183: public void suspend() throws Exception {
184: log.info("SUSPEND " + id);
185: assertTx(id);
186: getTM().suspend();
187: log.info("SUSPENDED " + id);
188: }
189:
190: public void resume() throws Exception {
191: log.info("RESUME " + id);
192: getTM().resume(getTx(id));
193: assertTx(id);
194: log.info("RESUMED " + id);
195: }
196:
197: public void setRollbackOnly() throws Exception {
198: log.info("SETROLLBACK " + id);
199: getTx(id).setRollbackOnly();
200: log.info("SETTEDROLLBACK " + id);
201: }
202:
203: public void checkStatus() throws Exception {
204: log.info("CHECKSTATUS " + id);
205: int actualStatus = getTx(id).getStatus();
206: log.info("CHECKINGSTATUS " + id + " Expected " + status
207: + " was " + actualStatus);
208: if (actualStatus != status)
209: throw new Exception("Transaction " + id
210: + " Expected status " + status + " was "
211: + actualStatus);
212: }
213:
214: public void checkState() throws Exception {
215: log.info("CHECKSTATE " + id);
216: int actualStatus = getRes(id).getStatus();
217: log.info("CHECKINGSTATE " + id + " Expected " + status
218: + " was " + actualStatus);
219: if (actualStatus != status)
220: throw new Exception("Resource " + id + " Expected state "
221: + status + " was " + actualStatus);
222: }
223:
224: public void create() throws Exception {
225: log.info("CREATE " + id);
226: Resource res = new Resource(id);
227: resources.put(id, res);
228: log.info("CREATED " + res);
229: }
230:
231: public void createLocal() throws Exception {
232: log.info("CREATE_LOCAL " + id);
233: Resource res = new LocalResource(id);
234: resources.put(id, res);
235: log.info("CREATED_LOCAL " + res);
236: }
237:
238: public void enlist() throws Exception {
239: log.info("ENLIST " + id);
240: Transaction tx = getTM().getTransaction();
241: if (tx.enlistResource(getRes(id)) == false)
242: throw new Exception("Unable to enlist resource");
243: log.info("ENLISTED " + id + " " + tx);
244: }
245:
246: public void differentRM() throws Exception {
247: log.info("DIFFRM " + id);
248: getRes(id).newResourceManager();
249: }
250:
251: public void failLocal() throws Exception {
252: log.info("FAIL_LOCAL " + id);
253: LocalResource resource = (LocalResource) getRes(id);
254: resource.failLocal();
255: }
256:
257: public void setStatus() throws Exception {
258: log.info("SETSTATUS " + id + " " + status);
259: getRes(id).setStatus(status);
260: log.info("SETTEDSTATUS " + id + " " + status);
261: }
262:
263: public static void start(Logger log) throws Exception {
264: Operation.log = log;
265: if (getTM().getTransaction() != null)
266: throw new IllegalStateException(
267: "Invalid thread association "
268: + getTM().getTransaction());
269: reset();
270: }
271:
272: public static void end() {
273: reset();
274: }
275:
276: public static void reset() {
277: resources.clear();
278: transactions.clear();
279: }
280:
281: public static void tidyUp() {
282: try {
283: if (getTM().getStatus() != Status.STATUS_NO_TRANSACTION) {
284: log.warn("TIDYING UP AFTER BROKEN TEST!");
285: getTM().rollback();
286: }
287: } catch (Exception ignored) {
288: }
289: }
290:
291: public Resource getRes(Integer id) {
292: Resource res = (Resource) resources.get(id);
293: if (res == null)
294: throw new IllegalStateException("No resource: " + id);
295: return res;
296: }
297:
298: public Transaction getTx(Integer id) {
299: Transaction tx = (Transaction) transactions.get(id);
300: if (tx == null)
301: throw new IllegalStateException("No transaction: " + id);
302: return tx;
303: }
304:
305: public void assertTx(Integer id) throws Exception {
306: Transaction tx = getTx(id);
307: Transaction current = getTM().getTransaction();
308: log.info("Asserting tx " + tx + " current " + current);
309: if (tx.equals(current) == false)
310: throw new IllegalStateException("Expected tx " + tx
311: + " was " + current);
312: }
313:
314: public static TransactionManager getTM() throws Exception {
315: if (tm == null)
316: tm = (TransactionManager) new InitialContext()
317: .lookup("java:/TransactionManager");
318: return tm;
319: }
320: }
|