1
2
3
4
5
6
7
8
9
10
11 package org.mule.transaction;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.transaction.TransactionException;
15 import org.mule.config.i18n.CoreMessages;
16
17 import java.lang.reflect.Field;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import javax.transaction.Status;
23
24 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
25
26
27
28
29
30 public abstract class AbstractSingleResourceTransaction extends AbstractTransaction
31 {
32
33
34
35
36
37
38 protected static Map<Integer, String> txStatusMappings = new HashMap<Integer, String>(10);
39
40 protected volatile Object key;
41 protected volatile Object resource;
42
43 protected final AtomicBoolean started = new AtomicBoolean(false);
44 protected final AtomicBoolean committed = new AtomicBoolean(false);
45 protected final AtomicBoolean rolledBack = new AtomicBoolean(false);
46 protected final AtomicBoolean rollbackOnly = new AtomicBoolean(false);
47
48 static
49 {
50 Field[] fields = Status.class.getFields();
51 for (Field field : fields)
52 {
53 try
54 {
55 txStatusMappings.put(field.getInt(Status.class), field.getName());
56 }
57 catch (IllegalAccessException e)
58 {
59
60 }
61 }
62
63 txStatusMappings = Collections.unmodifiableMap(txStatusMappings);
64 }
65
66 protected AbstractSingleResourceTransaction(MuleContext muleContext)
67 {
68 super(muleContext);
69 }
70
71 public void begin() throws TransactionException
72 {
73 super.begin();
74 started.compareAndSet(false, true);
75 }
76
77 public void commit() throws TransactionException
78 {
79 super.commit();
80 committed.compareAndSet(false, true);
81 }
82
83 public void rollback() throws TransactionException
84 {
85 super.rollback();
86 rolledBack.compareAndSet(false, true);
87 }
88
89 public int getStatus() throws TransactionStatusException
90 {
91 if (rolledBack.get())
92 {
93 return STATUS_ROLLEDBACK;
94 }
95 if (committed.get())
96 {
97 return STATUS_COMMITTED;
98 }
99 if (rollbackOnly.get())
100 {
101 return STATUS_MARKED_ROLLBACK;
102 }
103 if (started.get())
104 {
105 return STATUS_ACTIVE;
106 }
107 return STATUS_NO_TRANSACTION;
108 }
109
110 public Object getResource(Object key)
111 {
112 return key != null && this.key == key ? this.resource : null;
113 }
114
115 public boolean hasResource(Object key)
116 {
117 return key != null && this.key == key;
118 }
119
120 public void bindResource(Object key, Object resource) throws TransactionException
121 {
122 if (key == null)
123 {
124 throw new IllegalTransactionStateException(CoreMessages.transactionCannotBindToNullKey());
125 }
126 if (resource == null)
127 {
128 throw new IllegalTransactionStateException(CoreMessages.transactionCannotBindNullResource());
129 }
130 if (this.key != null)
131 {
132 throw new IllegalTransactionStateException(CoreMessages.transactionSingleResourceOnly());
133 }
134
135 if (logger.isDebugEnabled())
136 {
137 logger.debug("Binding " + resource + " to " + key);
138 }
139
140 this.key = key;
141 this.resource = resource;
142 }
143
144 public void setRollbackOnly()
145 {
146 rollbackOnly.set(true);
147 }
148
149 @Override
150 public String toString()
151 {
152 int status;
153 try
154 {
155 status = getStatus();
156 }
157 catch (TransactionException e)
158 {
159 status = -1;
160 }
161
162
163
164 String statusName = txStatusMappings.get(status);
165 if (statusName == null)
166 {
167 statusName = "*undefined*";
168 }
169
170 return new StringBuilder().append(getClass().getName())
171 .append('@').append(id)
172 .append("[status=").append(statusName)
173 .append(", key=").append(key)
174 .append(", resource=").append(resource)
175 .append("]").toString();
176 }
177 }