View Javadoc

1   /*
2    * $Id: ConnectionWrapper.java 12181 2008-06-26 20:05:55Z dirk.olmes $
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.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   * Using for unification XAConnection and Connection
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 }