1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.jdbc.xa;
12
13 import org.mule.api.transaction.Transaction;
14 import org.mule.api.transaction.TransactionException;
15 import org.mule.config.i18n.CoreMessages;
16 import org.mule.transaction.IllegalTransactionStateException;
17 import org.mule.transaction.TransactionCoordination;
18 import org.mule.transaction.XaTransaction;
19
20 import java.lang.reflect.Proxy;
21 import java.sql.CallableStatement;
22 import java.sql.Connection;
23 import java.sql.DatabaseMetaData;
24 import java.sql.PreparedStatement;
25 import java.sql.SQLException;
26 import java.sql.SQLWarning;
27 import java.sql.Savepoint;
28 import java.sql.Statement;
29 import java.util.Map;
30
31 import javax.sql.XAConnection;
32 import javax.transaction.xa.XAResource;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37
38
39
40 public class ConnectionWrapper implements Connection, XaTransaction.MuleXaObject
41 {
42 private final XAConnection xaConnection;
43 private Connection connection;
44 private volatile boolean enlisted = false;
45 protected static final transient Log logger = LogFactory.getLog(ConnectionWrapper.class);
46 private volatile boolean reuseObject = false;
47
48 public ConnectionWrapper(XAConnection xaCon) throws SQLException
49 {
50 this.xaConnection = xaCon;
51 this.connection = xaCon.getConnection();
52 }
53
54 public int getHoldability() throws SQLException
55 {
56 return connection.getHoldability();
57 }
58
59 public int getTransactionIsolation() throws SQLException
60 {
61 return connection.getTransactionIsolation();
62 }
63
64 public void clearWarnings() throws SQLException
65 {
66 connection.clearWarnings();
67 }
68
69 public void close() throws SQLException
70 {
71 connection.close();
72 }
73
74 public void commit() throws SQLException
75 {
76 connection.commit();
77 }
78
79 public void rollback() throws SQLException
80 {
81 connection.rollback();
82 }
83
84 public boolean getAutoCommit() throws SQLException
85 {
86 return connection.getAutoCommit();
87 }
88
89 public boolean isClosed() throws SQLException
90 {
91 return connection.isClosed();
92 }
93
94 public boolean isReadOnly() throws SQLException
95 {
96 return connection.isReadOnly();
97 }
98
99 public void setHoldability(int holdability) throws SQLException
100 {
101 connection.setHoldability(holdability);
102 }
103
104 public void setTransactionIsolation(int level) throws SQLException
105 {
106 connection.setTransactionIsolation(level);
107 }
108
109 public void setAutoCommit(boolean autoCommit) throws SQLException
110 {
111 connection.setAutoCommit(autoCommit);
112 }
113
114 public void setReadOnly(boolean readOnly) throws SQLException
115 {
116 connection.setReadOnly(readOnly);
117 }
118
119 public String getCatalog() throws SQLException
120 {
121 return connection.getCatalog();
122 }
123
124 public void setCatalog(String catalog) throws SQLException
125 {
126 connection.setCatalog(catalog);
127 }
128
129 public DatabaseMetaData getMetaData() throws SQLException
130 {
131 return connection.getMetaData();
132 }
133
134 public SQLWarning getWarnings() throws SQLException
135 {
136 return connection.getWarnings();
137 }
138
139 public Savepoint setSavepoint() throws SQLException
140 {
141 return connection.setSavepoint();
142 }
143
144 public void releaseSavepoint(Savepoint savepoint) throws SQLException
145 {
146 connection.releaseSavepoint(savepoint);
147 }
148
149 public void rollback(Savepoint savepoint) throws SQLException
150 {
151 connection.rollback();
152 }
153
154 public Statement createStatement() throws SQLException
155 {
156 Statement st = connection.createStatement();
157 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
158 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
159 }
160
161 public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
162 {
163 Statement st = connection.createStatement(resultSetType, resultSetConcurrency);
164 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
165 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
166 }
167
168 public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
169 throws SQLException
170 {
171 Statement st = connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
172 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
173 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
174 }
175
176 public Map getTypeMap() throws SQLException
177 {
178 return connection.getTypeMap();
179 }
180
181 public void setTypeMap(Map map) throws SQLException
182 {
183 connection.setTypeMap(map);
184 }
185
186 public String nativeSQL(String sql) throws SQLException
187 {
188 return connection.nativeSQL(sql);
189 }
190
191 public CallableStatement prepareCall(String sql) throws SQLException
192 {
193 CallableStatement cs = connection.prepareCall(sql);
194 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
195 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
196 }
197
198 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
199 throws SQLException
200 {
201 CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency);
202 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
203 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
204 }
205
206 public CallableStatement prepareCall(String sql,
207 int resultSetType,
208 int resultSetConcurrency,
209 int resultSetHoldability) throws SQLException
210 {
211 CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
212 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
213 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
214 }
215
216 public PreparedStatement prepareStatement(String sql) throws SQLException
217 {
218 PreparedStatement ps = connection.prepareStatement(sql);
219 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
220 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
221 }
222
223 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
224 {
225 PreparedStatement ps = connection.prepareStatement(sql, autoGeneratedKeys);
226 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
227 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
228 }
229
230 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
231 throws SQLException
232 {
233 PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
234 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
235 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
236 }
237
238 public PreparedStatement prepareStatement(String sql,
239 int resultSetType,
240 int resultSetConcurrency,
241 int resultSetHoldability) throws SQLException
242 {
243 PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency,
244 resultSetHoldability);
245 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
246 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
247 }
248
249 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
250 {
251 PreparedStatement ps = connection.prepareStatement(sql, columnIndexes);
252 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
253 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
254 }
255
256 public Savepoint setSavepoint(String name) throws SQLException
257 {
258 return connection.setSavepoint(name);
259 }
260
261 public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
262 {
263 PreparedStatement ps = connection.prepareStatement(sql, columnNames);
264 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
265 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
266 }
267
268 public boolean enlist() throws TransactionException
269 {
270 try
271 {
272 connection.setAutoCommit(false);
273 }
274 catch (SQLException e)
275 {
276 throw new TransactionException(e);
277 }
278
279 if (isEnlisted())
280 {
281 return false;
282 }
283 if (logger.isDebugEnabled())
284 {
285 logger.debug("Enlistment request: " + this);
286 }
287
288 Transaction transaction = TransactionCoordination.getInstance().getTransaction();
289 if (transaction == null)
290 {
291 throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
292 }
293 if (!(transaction instanceof XaTransaction))
294 {
295 throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
296 }
297 if (!isEnlisted())
298 {
299 final XAResource xaResource;
300 try
301 {
302 xaResource = xaConnection.getXAResource();
303 }
304 catch (SQLException e)
305 {
306 throw new TransactionException(e);
307 }
308
309 enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
310 }
311
312 return enlisted;
313 }
314
315 public boolean delist() throws Exception
316 {
317 if (!isEnlisted())
318 {
319 return false;
320 }
321 if (logger.isDebugEnabled())
322 {
323 logger.debug("Delistment request: " + this);
324 }
325
326 Transaction transaction = TransactionCoordination.getInstance().getTransaction();
327 if (transaction == null)
328 {
329 throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
330 }
331 if (!(transaction instanceof XaTransaction))
332 {
333 throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
334 }
335 if (isEnlisted())
336 {
337 enlisted = !((XaTransaction) transaction).delistResource(xaConnection.getXAResource(), XAResource.TMSUCCESS);
338 }
339 return !isEnlisted();
340 }
341
342
343 public boolean isEnlisted()
344 {
345 return enlisted;
346 }
347
348 public void setEnlisted(boolean enlisted)
349 {
350 this.enlisted = enlisted;
351 }
352
353 public boolean isReuseObject()
354 {
355 return reuseObject;
356 }
357
358 public void setReuseObject(boolean reuseObject)
359 {
360 this.reuseObject = reuseObject;
361 }
362
363 public Object getTargetObject()
364 {
365 return xaConnection;
366 }
367 }