1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.geronimo.transaction.manager;
18
19 import java.util.Collection;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23 import javax.resource.spi.XATerminator;
24 import javax.transaction.InvalidTransactionException;
25 import javax.transaction.Status;
26 import javax.transaction.SystemException;
27 import javax.transaction.Transaction;
28 import javax.transaction.xa.XAException;
29 import javax.transaction.xa.XAResource;
30 import javax.transaction.xa.Xid;
31
32
33
34
35 public class GeronimoTransactionManager extends TransactionManagerImpl implements XATerminator, XAWork {
36 private final Map importedTransactions = new HashMap();
37 private boolean isInRecovery = false;
38
39 public GeronimoTransactionManager() throws XAException {
40 }
41
42 public GeronimoTransactionManager(int defaultTransactionTimeoutSeconds) throws XAException {
43 super(defaultTransactionTimeoutSeconds);
44 }
45
46 public GeronimoTransactionManager(int defaultTransactionTimeoutSeconds, TransactionLog transactionLog) throws XAException {
47 super(defaultTransactionTimeoutSeconds, transactionLog);
48 }
49
50 public GeronimoTransactionManager(int defaultTransactionTimeoutSeconds, XidFactory xidFactory, TransactionLog transactionLog) throws XAException {
51 super(defaultTransactionTimeoutSeconds, xidFactory, transactionLog);
52 }
53
54
55
56
57 public void commit(Xid xid, boolean onePhase) throws XAException {
58 Transaction importedTransaction;
59 synchronized (importedTransactions) {
60 importedTransaction = (Transaction) importedTransactions.remove(xid);
61 }
62 if (importedTransaction == null) {
63 throw new XAException("No imported transaction for xid: " + xid);
64 }
65
66 try {
67 int status = importedTransaction.getStatus();
68 assert status == Status.STATUS_ACTIVE || status == Status.STATUS_PREPARED: "invalid status: " + status;
69 } catch (SystemException e) {
70 throw (XAException)new XAException().initCause(e);
71 }
72 commit(importedTransaction, onePhase);
73 }
74
75
76
77
78 public void forget(Xid xid) throws XAException {
79 Transaction importedTransaction;
80 synchronized (importedTransactions) {
81 importedTransaction = (Transaction) importedTransactions.remove(xid);
82 }
83 if (importedTransaction == null) {
84 throw new XAException("No imported transaction for xid: " + xid);
85 }
86
87
88
89
90
91
92
93 forget(importedTransaction);
94 }
95
96
97
98
99 public int prepare(Xid xid) throws XAException {
100 Transaction importedTransaction;
101 synchronized (importedTransactions) {
102 importedTransaction = (Transaction) importedTransactions.get(xid);
103 }
104 if (importedTransaction == null) {
105 throw new XAException("No imported transaction for xid: " + xid);
106 }
107 try {
108 int status = importedTransaction.getStatus();
109 assert status == Status.STATUS_ACTIVE;
110 } catch (SystemException e) {
111 throw (XAException)new XAException().initCause(e);
112 }
113 return prepare(importedTransaction);
114 }
115
116
117
118
119 public Xid[] recover(int flag) throws XAException {
120 if (!isInRecovery) {
121 if ((flag & XAResource.TMSTARTRSCAN) == 0) {
122 throw new XAException(XAException.XAER_PROTO);
123 }
124 isInRecovery = true;
125 }
126 if ((flag & XAResource.TMENDRSCAN) != 0) {
127 isInRecovery = false;
128 }
129
130
131 if ((flag & XAResource.TMSTARTRSCAN) != 0) {
132 Map recoveredXidMap = getExternalXids();
133 Xid[] recoveredXids = new Xid[recoveredXidMap.size()];
134 int i = 0;
135 synchronized (importedTransactions) {
136 for (Iterator iterator = recoveredXidMap.entrySet().iterator(); iterator.hasNext();) {
137 Map.Entry entry = (Map.Entry) iterator.next();
138 Xid xid = (Xid) entry.getKey();
139 recoveredXids[i++] = xid;
140 Transaction transaction = (Transaction) entry.getValue();
141 importedTransactions.put(xid, transaction);
142 }
143 }
144 return recoveredXids;
145 } else {
146 return new Xid[0];
147 }
148 }
149
150
151
152
153 public void rollback(Xid xid) throws XAException {
154 Transaction importedTransaction;
155 synchronized (importedTransactions) {
156 importedTransaction = (Transaction) importedTransactions.remove(xid);
157 }
158 if (importedTransaction == null) {
159 throw new XAException("No imported transaction for xid: " + xid);
160 }
161 try {
162 int status = importedTransaction.getStatus();
163 assert status == Status.STATUS_ACTIVE || status == Status.STATUS_PREPARED;
164 } catch (SystemException e) {
165 throw (XAException)new XAException().initCause(e);
166 }
167 rollback(importedTransaction);
168 }
169
170
171
172 public void begin(Xid xid, long txTimeoutMillis) throws XAException, InvalidTransactionException, SystemException, ImportedTransactionActiveException {
173 Transaction importedTransaction;
174 synchronized (importedTransactions) {
175 importedTransaction = (Transaction) importedTransactions.get(xid);
176 if (importedTransaction == null) {
177
178 importedTransaction = importXid(xid, txTimeoutMillis);
179 importedTransactions.put(xid, importedTransaction);
180 }
181
182 try {
183 resume(importedTransaction);
184 } catch (InvalidTransactionException e) {
185
186 throw (ImportedTransactionActiveException)new ImportedTransactionActiveException(xid).initCause(e);
187 }
188 }
189 }
190
191 public void end(Xid xid) throws XAException, SystemException {
192 synchronized (importedTransactions) {
193 Transaction importedTransaction = (Transaction) importedTransactions.get(xid);
194 if (importedTransaction == null) {
195 throw new XAException("No imported transaction for xid: " + xid);
196 }
197 if (importedTransaction != getTransaction()) {
198 throw new XAException("Imported transaction is not associated with the curren thread xid: " + xid);
199 }
200 suspend();
201 }
202 }
203 }