View Javadoc

1   /*
2    * $Id: ConnectionWrapper.java 10465 2008-01-22 20:17:19Z akuzmin $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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   * Using for unification XAConnection and Connection
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      * (non-Javadoc)
55      *
56      * @see java.sql.Connection#getHoldability()
57      */
58  
59      public int getHoldability() throws SQLException
60      {
61          return connection.getHoldability();
62      }
63  
64      /*
65       * (non-Javadoc)
66       *
67       * @see java.sql.Connection#getTransactionIsolation()
68       */
69      public int getTransactionIsolation() throws SQLException
70      {
71          return connection.getTransactionIsolation();
72      }
73  
74      /*
75       * (non-Javadoc)
76       *
77       * @see java.sql.Connection#clearWarnings()
78       */
79      public void clearWarnings() throws SQLException
80      {
81          connection.clearWarnings();
82      }
83  
84      /*
85       * (non-Javadoc)
86       *
87       * @see java.sql.Connection#close()
88       */
89      public void close() throws SQLException
90      {
91          connection.close();
92      }
93  
94      /*
95       * (non-Javadoc)
96       *
97       * @see java.sql.Connection#commit()
98       */
99      public void commit() throws SQLException
100     {
101         connection.commit();
102     }
103 
104     /*
105      * (non-Javadoc)
106      *
107      * @see java.sql.Connection#rollback()
108      */
109     public void rollback() throws SQLException
110     {
111         connection.rollback();
112     }
113 
114     /*
115      * (non-Javadoc)
116      *
117      * @see java.sql.Connection#getAutoCommit()
118      */
119     public boolean getAutoCommit() throws SQLException
120     {
121         return connection.getAutoCommit();
122     }
123 
124     /*
125      * (non-Javadoc)
126      *
127      * @see java.sql.Connection#isClosed()
128      */
129     public boolean isClosed() throws SQLException
130     {
131         return connection.isClosed();
132     }
133 
134     /*
135      * (non-Javadoc)
136      *
137      * @see java.sql.Connection#isReadOnly()
138      */
139     public boolean isReadOnly() throws SQLException
140     {
141         return connection.isReadOnly();
142     }
143 
144     /*
145      * (non-Javadoc)
146      *
147      * @see java.sql.Connection#setHoldability(int)
148      */
149     public void setHoldability(int holdability) throws SQLException
150     {
151         connection.setHoldability(holdability);
152     }
153 
154     /*
155      * (non-Javadoc)
156      *
157      * @see java.sql.Connection#setTransactionIsolation(int)
158      */
159     public void setTransactionIsolation(int level) throws SQLException
160     {
161         connection.setTransactionIsolation(level);
162     }
163 
164     /*
165      * (non-Javadoc)
166      *
167      * @see java.sql.Connection#setAutoCommit(boolean)
168      */
169     public void setAutoCommit(boolean autoCommit) throws SQLException
170     {
171         connection.setAutoCommit(autoCommit);
172     }
173 
174     /*
175      * (non-Javadoc)
176      *
177      * @see java.sql.Connection#setReadOnly(boolean)
178      */
179     public void setReadOnly(boolean readOnly) throws SQLException
180     {
181         connection.setReadOnly(readOnly);
182     }
183 
184     /*
185      * (non-Javadoc)
186      *
187      * @see java.sql.Connection#getCatalog()
188      */
189     public String getCatalog() throws SQLException
190     {
191         return connection.getCatalog();
192     }
193 
194     /*
195      * (non-Javadoc)
196      *
197      * @see java.sql.Connection#setCatalog(java.lang.String)
198      */
199     public void setCatalog(String catalog) throws SQLException
200     {
201         connection.setCatalog(catalog);
202     }
203 
204     /*
205      * (non-Javadoc)
206      *
207      * @see java.sql.Connection#getMetaData()
208      */
209     public DatabaseMetaData getMetaData() throws SQLException
210     {
211         return connection.getMetaData();
212     }
213 
214     /*
215      * (non-Javadoc)
216      *
217      * @see java.sql.Connection#getWarnings()
218      */
219     public SQLWarning getWarnings() throws SQLException
220     {
221         return connection.getWarnings();
222     }
223 
224     /*
225      * (non-Javadoc)
226      *
227      * @see java.sql.Connection#setSavepoint()
228      */
229     public Savepoint setSavepoint() throws SQLException
230     {
231         return connection.setSavepoint();
232     }
233 
234     /*
235      * (non-Javadoc)
236      *
237      * @see java.sql.Connection#releaseSavepoint(java.sql.Savepoint)
238      */
239     public void releaseSavepoint(Savepoint savepoint) throws SQLException
240     {
241         connection.releaseSavepoint(savepoint);
242     }
243 
244     /*
245      * (non-Javadoc)
246      *
247      * @see java.sql.Connection#rollback(java.sql.Savepoint)
248      */
249     public void rollback(Savepoint savepoint) throws SQLException
250     {
251         connection.rollback();
252     }
253 
254     /*
255      * (non-Javadoc)
256      *
257      * @see java.sql.Connection#createStatement()
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      * (non-Javadoc)
268      *
269      * @see java.sql.Connection#createStatement(int, int)
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      * (non-Javadoc)
280      *
281      * @see java.sql.Connection#createStatement(int, int, int)
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      * (non-Javadoc)
293      *
294      * @see java.sql.Connection#getTypeMap()
295      */
296     public Map getTypeMap() throws SQLException
297     {
298         return connection.getTypeMap();
299     }
300 
301     /*
302      * (non-Javadoc)
303      *
304      * @see java.sql.Connection#setTypeMap(java.util.Map)
305      */
306     public void setTypeMap(Map map) throws SQLException
307     {
308         connection.setTypeMap(map);
309     }
310 
311     /*
312      * (non-Javadoc)
313      *
314      * @see java.sql.Connection#nativeSQL(java.lang.String)
315      */
316     public String nativeSQL(String sql) throws SQLException
317     {
318         return connection.nativeSQL(sql);
319     }
320 
321     /*
322      * (non-Javadoc)
323      *
324      * @see java.sql.Connection#prepareCall(java.lang.String)
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      * (non-Javadoc)
335      *
336      * @see java.sql.Connection#prepareCall(java.lang.String, int, int)
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      * (non-Javadoc)
348      *
349      * @see java.sql.Connection#prepareCall(java.lang.String, int, int, int)
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      * (non-Javadoc)
363      *
364      * @see java.sql.Connection#prepareStatement(java.lang.String)
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      * (non-Javadoc)
375      *
376      * @see java.sql.Connection#prepareStatement(java.lang.String, int)
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      * (non-Javadoc)
387      *
388      * @see java.sql.Connection#prepareStatement(java.lang.String, int, int)
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      * (non-Javadoc)
400      *
401      * @see java.sql.Connection#prepareStatement(java.lang.String, int, int, int)
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      * (non-Javadoc)
416      *
417      * @see java.sql.Connection#prepareStatement(java.lang.String, int[])
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      * (non-Javadoc)
428      *
429      * @see java.sql.Connection#setSavepoint(java.lang.String)
430      */
431     public Savepoint setSavepoint(String name) throws SQLException
432     {
433         return connection.setSavepoint(name);
434     }
435 
436     /*
437      * (non-Javadoc)
438      *
439      * @see java.sql.Connection#prepareStatement(java.lang.String,
440      *      java.lang.String[])
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 }