1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.jdbc.xa;
12
13 import org.mule.config.i18n.CoreMessages;
14 import org.mule.transaction.IllegalTransactionStateException;
15 import org.mule.transaction.TransactionCoordination;
16 import org.mule.transaction.XaTransaction;
17 import org.mule.umo.UMOTransaction;
18
19 import java.lang.reflect.Proxy;
20 import java.sql.CallableStatement;
21 import java.sql.Connection;
22 import java.sql.DatabaseMetaData;
23 import java.sql.PreparedStatement;
24 import java.sql.SQLException;
25 import java.sql.SQLWarning;
26 import java.sql.Savepoint;
27 import java.sql.Statement;
28 import java.util.Map;
29
30 import javax.sql.XAConnection;
31 import javax.transaction.xa.XAResource;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36
37
38
39 public class ConnectionWrapper implements Connection, XaTransaction.MuleXaObject
40 {
41 private final XAConnection xaConnection;
42 private Connection connection;
43 private volatile boolean enlisted = false;
44 protected static final transient Log logger = LogFactory.getLog(ConnectionWrapper.class);
45 private volatile boolean reuseObject = false;
46
47 public ConnectionWrapper(XAConnection xaCon) throws SQLException
48 {
49 this.xaConnection = xaCon;
50 this.connection = xaCon.getConnection();
51 }
52
53
54
55
56
57
58
59 public int getHoldability() throws SQLException
60 {
61 return connection.getHoldability();
62 }
63
64
65
66
67
68
69 public int getTransactionIsolation() throws SQLException
70 {
71 return connection.getTransactionIsolation();
72 }
73
74
75
76
77
78
79 public void clearWarnings() throws SQLException
80 {
81 connection.clearWarnings();
82 }
83
84
85
86
87
88
89 public void close() throws SQLException
90 {
91 connection.close();
92 }
93
94
95
96
97
98
99 public void commit() throws SQLException
100 {
101 connection.commit();
102 }
103
104
105
106
107
108
109 public void rollback() throws SQLException
110 {
111 connection.rollback();
112 }
113
114
115
116
117
118
119 public boolean getAutoCommit() throws SQLException
120 {
121 return connection.getAutoCommit();
122 }
123
124
125
126
127
128
129 public boolean isClosed() throws SQLException
130 {
131 return connection.isClosed();
132 }
133
134
135
136
137
138
139 public boolean isReadOnly() throws SQLException
140 {
141 return connection.isReadOnly();
142 }
143
144
145
146
147
148
149 public void setHoldability(int holdability) throws SQLException
150 {
151 connection.setHoldability(holdability);
152 }
153
154
155
156
157
158
159 public void setTransactionIsolation(int level) throws SQLException
160 {
161 connection.setTransactionIsolation(level);
162 }
163
164
165
166
167
168
169 public void setAutoCommit(boolean autoCommit) throws SQLException
170 {
171 connection.setAutoCommit(autoCommit);
172 }
173
174
175
176
177
178
179 public void setReadOnly(boolean readOnly) throws SQLException
180 {
181 connection.setReadOnly(readOnly);
182 }
183
184
185
186
187
188
189 public String getCatalog() throws SQLException
190 {
191 return connection.getCatalog();
192 }
193
194
195
196
197
198
199 public void setCatalog(String catalog) throws SQLException
200 {
201 connection.setCatalog(catalog);
202 }
203
204
205
206
207
208
209 public DatabaseMetaData getMetaData() throws SQLException
210 {
211 return connection.getMetaData();
212 }
213
214
215
216
217
218
219 public SQLWarning getWarnings() throws SQLException
220 {
221 return connection.getWarnings();
222 }
223
224
225
226
227
228
229 public Savepoint setSavepoint() throws SQLException
230 {
231 return connection.setSavepoint();
232 }
233
234
235
236
237
238
239 public void releaseSavepoint(Savepoint savepoint) throws SQLException
240 {
241 connection.releaseSavepoint(savepoint);
242 }
243
244
245
246
247
248
249 public void rollback(Savepoint savepoint) throws SQLException
250 {
251 connection.rollback();
252 }
253
254
255
256
257
258
259 public Statement createStatement() throws SQLException
260 {
261 Statement st = connection.createStatement();
262 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
263 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
264 }
265
266
267
268
269
270
271 public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
272 {
273 Statement st = connection.createStatement(resultSetType, resultSetConcurrency);
274 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
275 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
276 }
277
278
279
280
281
282
283 public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
284 throws SQLException
285 {
286 Statement st = connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
287 return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
288 new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
289 }
290
291
292
293
294
295
296 public Map getTypeMap() throws SQLException
297 {
298 return connection.getTypeMap();
299 }
300
301
302
303
304
305
306 public void setTypeMap(Map map) throws SQLException
307 {
308 connection.setTypeMap(map);
309 }
310
311
312
313
314
315
316 public String nativeSQL(String sql) throws SQLException
317 {
318 return connection.nativeSQL(sql);
319 }
320
321
322
323
324
325
326 public CallableStatement prepareCall(String sql) throws SQLException
327 {
328 CallableStatement cs = connection.prepareCall(sql);
329 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
330 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
331 }
332
333
334
335
336
337
338 public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
339 throws SQLException
340 {
341 CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency);
342 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
343 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
344 }
345
346
347
348
349
350
351 public CallableStatement prepareCall(String sql,
352 int resultSetType,
353 int resultSetConcurrency,
354 int resultSetHoldability) throws SQLException
355 {
356 CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
357 return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
358 new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
359 }
360
361
362
363
364
365
366 public PreparedStatement prepareStatement(String sql) throws SQLException
367 {
368 PreparedStatement ps = connection.prepareStatement(sql);
369 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
370 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
371 }
372
373
374
375
376
377
378 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
379 {
380 PreparedStatement ps = connection.prepareStatement(sql, autoGeneratedKeys);
381 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
382 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
383 }
384
385
386
387
388
389
390 public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
391 throws SQLException
392 {
393 PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
394 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
395 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
396 }
397
398
399
400
401
402
403 public PreparedStatement prepareStatement(String sql,
404 int resultSetType,
405 int resultSetConcurrency,
406 int resultSetHoldability) throws SQLException
407 {
408 PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency,
409 resultSetHoldability);
410 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
411 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
412 }
413
414
415
416
417
418
419 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
420 {
421 PreparedStatement ps = connection.prepareStatement(sql, columnIndexes);
422 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
423 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
424 }
425
426
427
428
429
430
431 public Savepoint setSavepoint(String name) throws SQLException
432 {
433 return connection.setSavepoint(name);
434 }
435
436
437
438
439
440
441
442 public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
443 {
444 PreparedStatement ps = connection.prepareStatement(sql, columnNames);
445 return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
446 new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
447 }
448
449 protected void enlist() throws Exception
450 {
451 if (isEnlisted())
452 {
453 return;
454 }
455 if (logger.isDebugEnabled())
456 {
457 logger.debug("Enlistment request: " + this);
458 }
459
460 UMOTransaction transaction = TransactionCoordination.getInstance().getTransaction();
461 if (transaction == null)
462 {
463 throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
464 }
465 if (!(transaction instanceof XaTransaction))
466 {
467 throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
468 }
469 if (!isEnlisted())
470 {
471 final XAResource xaResource = xaConnection.getXAResource();
472 if (logger.isDebugEnabled())
473 {
474 logger.debug("Enlisting resource " + xaResource + " in xa transaction " + transaction);
475 }
476
477 enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
478 }
479 }
480
481 public boolean delist() throws Exception
482 {
483 if (!isEnlisted())
484 {
485 return false;
486 }
487 if (logger.isDebugEnabled())
488 {
489 logger.debug("Delistment request: " + this);
490 }
491
492 UMOTransaction transaction = TransactionCoordination.getInstance().getTransaction();
493 if (transaction == null)
494 {
495 throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
496 }
497 if (!(transaction instanceof XaTransaction))
498 {
499 throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
500 }
501 if (isEnlisted())
502 {
503 final XAResource xaResource = xaConnection.getXAResource();
504 if (logger.isDebugEnabled())
505 {
506 logger.debug("Delisting resource " + xaResource + " in xa transaction " + transaction);
507 }
508
509 enlisted = !((XaTransaction) transaction).delistResource(xaResource, XAResource.TMSUCCESS);
510 }
511 return !isEnlisted();
512 }
513
514
515 public boolean isEnlisted()
516 {
517 return enlisted;
518 }
519
520 public void setEnlisted(boolean enlisted)
521 {
522 this.enlisted = enlisted;
523 }
524
525 public boolean isReuseObject()
526 {
527 return reuseObject;
528 }
529
530 public void setReuseObject(boolean reuseObject)
531 {
532 this.reuseObject = reuseObject;
533 }
534
535 public Object getTargetObject()
536 {
537 return xaConnection;
538 }
539 }