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