View Javadoc

1   /*
2    * $Id: ConnectionWrapper.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.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.Array;
22  import java.sql.Blob;
23  import java.sql.CallableStatement;
24  import java.sql.Clob;
25  import java.sql.Connection;
26  import java.sql.DatabaseMetaData;
27  import java.sql.NClob;
28  import java.sql.PreparedStatement;
29  import java.sql.SQLClientInfoException;
30  import java.sql.SQLException;
31  import java.sql.SQLWarning;
32  import java.sql.SQLXML;
33  import java.sql.Savepoint;
34  import java.sql.Statement;
35  import java.sql.Struct;
36  import java.util.Map;
37  import java.util.Properties;
38  
39  import javax.sql.XAConnection;
40  import javax.transaction.xa.XAResource;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  
45  /**
46   * Using for unification XAConnection and Connection
47   */
48  public class ConnectionWrapper implements Connection, XaTransaction.MuleXaObject
49  {
50      private final XAConnection xaConnection;
51      private Connection connection;
52      private volatile boolean enlisted = false;
53      protected static final transient Log logger = LogFactory.getLog(ConnectionWrapper.class);
54      private volatile boolean reuseObject = false;
55  
56      public ConnectionWrapper(XAConnection xaCon) throws SQLException
57      {
58          this.xaConnection = xaCon;
59          this.connection = xaCon.getConnection();
60      }
61  
62      public int getHoldability() throws SQLException
63      {
64          return connection.getHoldability();
65      }
66  
67      public int getTransactionIsolation() throws SQLException
68      {
69          return connection.getTransactionIsolation();
70      }
71  
72      public void clearWarnings() throws SQLException
73      {
74          connection.clearWarnings();
75      }
76  
77      public void close() throws SQLException
78      {
79          connection.close();
80      }
81  
82      public void commit() throws SQLException
83      {
84          connection.commit();
85      }
86  
87      public void rollback() throws SQLException
88      {
89          connection.rollback();
90      }
91  
92      public boolean getAutoCommit() throws SQLException
93      {
94          return connection.getAutoCommit();
95      }
96  
97      public boolean isClosed() throws SQLException
98      {
99          return connection.isClosed();
100     }
101 
102     public boolean isReadOnly() throws SQLException
103     {
104         return connection.isReadOnly();
105     }
106 
107     public void setHoldability(int holdability) throws SQLException
108     {
109         connection.setHoldability(holdability);
110     }
111 
112     public void setTransactionIsolation(int level) throws SQLException
113     {
114         connection.setTransactionIsolation(level);
115     }
116 
117     public void setAutoCommit(boolean autoCommit) throws SQLException
118     {
119         connection.setAutoCommit(autoCommit);
120     }
121 
122     public void setReadOnly(boolean readOnly) throws SQLException
123     {
124         connection.setReadOnly(readOnly);
125     }
126 
127     public String getCatalog() throws SQLException
128     {
129         return connection.getCatalog();
130     }
131 
132     public void setCatalog(String catalog) throws SQLException
133     {
134         connection.setCatalog(catalog);
135     }
136 
137     public DatabaseMetaData getMetaData() throws SQLException
138     {
139         return connection.getMetaData();
140     }
141 
142     public SQLWarning getWarnings() throws SQLException
143     {
144         return connection.getWarnings();
145     }
146 
147     public Savepoint setSavepoint() throws SQLException
148     {
149         return connection.setSavepoint();
150     }
151 
152     public void releaseSavepoint(Savepoint savepoint) throws SQLException
153     {
154         connection.releaseSavepoint(savepoint);
155     }
156 
157     public void rollback(Savepoint savepoint) throws SQLException
158     {
159         connection.rollback();
160     }
161 
162     public Statement createStatement() throws SQLException
163     {
164         Statement st = connection.createStatement();
165         return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
166                                                   new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
167     }
168 
169     public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
170     {
171         Statement st = connection.createStatement(resultSetType, resultSetConcurrency);
172         return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
173                                                   new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
174     }
175 
176     public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
177             throws SQLException
178     {
179         Statement st = connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
180         return (Statement) Proxy.newProxyInstance(Statement.class.getClassLoader(),
181                                                   new Class[]{Statement.class}, new StatementInvocationHandler(this, st));
182     }
183 
184     public Map getTypeMap() throws SQLException
185     {
186         return connection.getTypeMap();
187     }
188 
189     public void setTypeMap(Map<String, Class<?>> map) throws SQLException
190     {
191         connection.setTypeMap(map);
192     }
193 
194     public String nativeSQL(String sql) throws SQLException
195     {
196         return connection.nativeSQL(sql);
197     }
198 
199     public CallableStatement prepareCall(String sql) throws SQLException
200     {
201         CallableStatement cs = connection.prepareCall(sql);
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, int resultSetType, int resultSetConcurrency)
207             throws SQLException
208     {
209         CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency);
210         return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
211                                                           new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
212     }
213 
214     public CallableStatement prepareCall(String sql,
215                                          int resultSetType,
216                                          int resultSetConcurrency,
217                                          int resultSetHoldability) throws SQLException
218     {
219         CallableStatement cs = connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
220         return (CallableStatement) Proxy.newProxyInstance(CallableStatement.class.getClassLoader(),
221                                                           new Class[]{CallableStatement.class}, new StatementInvocationHandler(this, cs));
222     }
223 
224     public PreparedStatement prepareStatement(String sql) throws SQLException
225     {
226         PreparedStatement ps = connection.prepareStatement(sql);
227         return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
228                                                           new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
229     }
230 
231     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
232     {
233         PreparedStatement ps = connection.prepareStatement(sql, autoGeneratedKeys);
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, int resultSetType, int resultSetConcurrency)
239             throws SQLException
240     {
241         PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
242         return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
243                                                           new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
244     }
245 
246     public PreparedStatement prepareStatement(String sql,
247                                               int resultSetType,
248                                               int resultSetConcurrency,
249                                               int resultSetHoldability) throws SQLException
250     {
251         PreparedStatement ps = connection.prepareStatement(sql, resultSetType, resultSetConcurrency,
252                                                            resultSetHoldability);
253         return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
254                                                           new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
255     }
256 
257     public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
258     {
259         PreparedStatement ps = connection.prepareStatement(sql, columnIndexes);
260         return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
261                                                           new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
262     }
263 
264     public Savepoint setSavepoint(String name) throws SQLException
265     {
266         return connection.setSavepoint(name);
267     }
268 
269     public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
270     {
271         PreparedStatement ps = connection.prepareStatement(sql, columnNames);
272         return (PreparedStatement) Proxy.newProxyInstance(PreparedStatement.class.getClassLoader(),
273                                                           new Class[]{PreparedStatement.class}, new StatementInvocationHandler(this, ps));
274     }
275 
276     public boolean enlist() throws TransactionException
277     {
278         try
279         {
280             connection.setAutoCommit(false);
281         }
282         catch (SQLException e)
283         {
284             throw new TransactionException(e);
285         }
286         
287         if (isEnlisted())
288         {
289             return false;
290         }
291         if (logger.isDebugEnabled())
292         {
293             logger.debug("Enlistment request: " + this);
294         }
295 
296         Transaction transaction = TransactionCoordination.getInstance().getTransaction();
297         if (transaction == null)
298         {
299             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
300         }
301         if (!(transaction instanceof XaTransaction))
302         {
303             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
304         }
305         if (!isEnlisted())
306         {
307             final XAResource xaResource;
308             try
309             {
310                 xaResource = xaConnection.getXAResource();
311             }
312             catch (SQLException e)
313             {
314                 throw new TransactionException(e);
315             }
316             
317             enlisted = ((XaTransaction) transaction).enlistResource(xaResource);
318         }
319         
320         return enlisted;
321     }
322 
323     public boolean delist() throws Exception
324     {
325         if (!isEnlisted())
326         {
327             return false;
328         }
329         if (logger.isDebugEnabled())
330         {
331             logger.debug("Delistment request: " + this);
332         }
333 
334         Transaction transaction = TransactionCoordination.getInstance().getTransaction();
335         if (transaction == null)
336         {
337             throw new IllegalTransactionStateException(CoreMessages.noMuleTransactionAvailable());
338         }
339         if (!(transaction instanceof XaTransaction))
340         {
341             throw new IllegalTransactionStateException(CoreMessages.notMuleXaTransaction(transaction));
342         }
343         if (isEnlisted())
344         {
345             enlisted = !((XaTransaction) transaction).delistResource(xaConnection.getXAResource(), XAResource.TMSUCCESS);
346         }
347         return !isEnlisted();
348     }
349 
350 
351     public boolean isEnlisted()
352     {
353         return enlisted;
354     }
355 
356     public void setEnlisted(boolean enlisted)
357     {
358         this.enlisted = enlisted;
359     }
360 
361     public boolean isReuseObject()
362     {
363         return reuseObject;
364     }
365 
366     public void setReuseObject(boolean reuseObject)
367     {
368         this.reuseObject = reuseObject;
369     }
370 
371     public Object getTargetObject()
372     {
373         return xaConnection;
374     }
375 
376     public Array createArrayOf(String typeName, Object[] elements) throws SQLException
377     {
378         return connection.createArrayOf(typeName, elements);
379     }
380 
381     public Blob createBlob() throws SQLException
382     {
383         return connection.createBlob();
384     }
385 
386     public Clob createClob() throws SQLException
387     {
388         return connection.createClob();
389     }
390 
391     public NClob createNClob() throws SQLException
392     {
393         return connection.createNClob();
394     }
395 
396     public SQLXML createSQLXML() throws SQLException
397     {
398         return connection.createSQLXML();
399     }
400 
401     public Struct createStruct(String typeName, Object[] attributes) throws SQLException
402     {
403         return connection.createStruct(typeName, attributes);
404     }
405 
406     public Properties getClientInfo() throws SQLException
407     {
408         return connection.getClientInfo();
409     }
410 
411     public String getClientInfo(String name) throws SQLException
412     {
413         return connection.getClientInfo(name);
414     }
415 
416     public boolean isValid(int timeout) throws SQLException
417     {
418         return connection.isValid(timeout);
419     }
420 
421     public void setClientInfo(Properties properties) throws SQLClientInfoException
422     {
423         connection.setClientInfo(properties);
424     }
425 
426     public void setClientInfo(String name, String value) throws SQLClientInfoException
427     {
428         connection.setClientInfo(name, value);
429     }
430 
431     public boolean isWrapperFor(Class<?> iface) throws SQLException
432     {
433         return connection.isWrapperFor(iface);
434     }
435 
436     public <T> T unwrap(Class<T> iface) throws SQLException
437     {
438         return connection.unwrap(iface);
439     }
440 }