001: /* ====================================================================
002: * The LateralNZ Software License, Version 1.0
003: *
004: * Copyright (c) 2003 LateralNZ. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by
021: * LateralNZ (http://www.lateralnz.org/) and other third parties."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "LateralNZ" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please
028: * contact oss@lateralnz.org.
029: *
030: * 5. Products derived from this software may not be called "Panther",
031: * or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
032: * "LATERALNZ" appear in their name, without prior written
033: * permission of LateralNZ.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of LateralNZ. For more
051: * information on Lateral, please see http://www.lateralnz.com/ or
052: * http://www.lateralnz.org
053: *
054: */
055: package org.lateralnz.simpletrans;
056:
057: import java.io.Serializable;
058: import java.sql.*;
059: import java.util.Map;
060:
061: import javax.transaction.xa.XAResource;
062: import javax.transaction.xa.XAException;
063:
064: import org.apache.log4j.Logger;
065:
066: import org.lateralnz.common.util.DAOUtils;
067:
068: /**
069: * a 'transaction-aware' wrapper for a JDBC connection. This is used to ensure
070: * that a connection is only commited, rolled back or closed until required
071: * by a transaction
072: *
073: * @author J R Briggs
074: */
075: public class TransConnection implements Connection, XAResource,
076: Serializable {
077: private static final Logger log = Logger
078: .getLogger(TransConnection.class.getName());
079:
080: private String name;
081: private Connection conn;
082: private boolean close = false;
083: private boolean inTrans = false;
084:
085: private long tempTime;
086: private java.util.ArrayList statements = null;
087:
088: /**
089: * wrap a JDBC connection with the specified name
090: */
091: public TransConnection(String name, Connection conn, boolean inTrans)
092: throws SQLException {
093: this .name = name;
094: this .conn = conn;
095: this .inTrans = inTrans;
096: this .conn
097: .setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
098:
099: /* JRB 15/09/2004: this isn't needed by the look of things. setAutoCommit to false
100: * seems to already start the transaction (which is done in enlistResource in the
101: * transaction) -- at least in the postgres driver. Need to test with other
102: * databases to confirm this.
103:
104: Statement st = conn.createStatement();
105: try {
106: st.executeUpdate("start transaction");
107: }
108: finally {
109: DAOUtils.close(st);
110: }*/
111: statements = new java.util.ArrayList();
112: if (log.isDebugEnabled()) {
113: tempTime = System.currentTimeMillis();
114: log
115: .debug("created new transaction connection for jdbc conn "
116: + conn);
117: }
118: }
119:
120: /**
121: * get the name of this connection
122: */
123: public String getName() {
124: return name;
125: }
126:
127: /**
128: * @see java.sql.Connection#clearWarnings
129: */
130: public void clearWarnings() throws SQLException {
131: conn.clearWarnings();
132: }
133:
134: /**
135: * if not in a transaction, this closes the connection immediately,
136: * otherwise just flags that a close is required
137: * @see java.sql.Connection#close
138: */
139: public void close() throws SQLException {
140: if (!inTrans) {
141: doClose();
142: } else {
143: close = true;
144: }
145: }
146:
147: /**
148: * check if close has been flagged on this connection
149: */
150: public boolean isCloseFlagged() {
151: return close;
152: }
153:
154: /**
155: * performs the actual close on the underlying connection
156: */
157: protected void doClose() throws SQLException {
158: if (log.isDebugEnabled()) {
159: log.debug("closing connection " + conn);
160: tempTime = System.currentTimeMillis() - tempTime;
161: if (tempTime > 15000) {
162: log.debug("time between opening and closing conn "
163: + conn + " was " + tempTime
164: + " after performing " + statements.toString());
165: }
166: }
167: conn.close();
168: }
169:
170: /**
171: * if not in a transaction, a commit is performed immediately,
172: * otherwise nothing happens
173: * @see java.sql.Connection#commit
174: */
175: public void commit() throws SQLException {
176: if (!inTrans) {
177: doCommit();
178: }
179: }
180:
181: /**
182: * performs the actual commit on the underlying connection
183: */
184: public void doCommit() throws SQLException {
185: conn.commit();
186: }
187:
188: /**
189: * @see java.sql.Connection#createStatement
190: */
191: public Statement createStatement() throws SQLException {
192: return conn.createStatement();
193: }
194:
195: /**
196: * @see java.sql.Connection#createStatement
197: */
198: public Statement createStatement(int param, int param1)
199: throws SQLException {
200: return conn.createStatement(param, param1);
201: }
202:
203: /**
204: * @see java.sql.Connection#createStatement
205: */
206: public Statement createStatement(int param, int param1, int param2)
207: throws SQLException {
208: return conn.createStatement(param, param1, param2);
209: }
210:
211: /**
212: * @see java.sql.Connection#getAutoCommit
213: */
214: public boolean getAutoCommit() throws SQLException {
215: return conn.getAutoCommit();
216: }
217:
218: /**
219: * @see java.sql.Connection#getCatalog
220: */
221: public String getCatalog() throws SQLException {
222: return conn.getCatalog();
223: }
224:
225: /**
226: * @see java.sql.Connection#getHoldability
227: */
228: public int getHoldability() throws SQLException {
229: return conn.getHoldability();
230: }
231:
232: /**
233: * @see java.sql.Connection#getMetaData
234: */
235: public DatabaseMetaData getMetaData() throws SQLException {
236: return conn.getMetaData();
237: }
238:
239: /**
240: * @see java.sql.Connection#getTransactionIsolation
241: */
242: public int getTransactionIsolation() throws SQLException {
243: return conn.getTransactionIsolation();
244: }
245:
246: /**
247: * @see java.sql.Connection#getTypeMap
248: */
249: public Map getTypeMap() throws SQLException {
250: return conn.getTypeMap();
251: }
252:
253: /**
254: * @see java.sql.Connection#getWarnings
255: */
256: public SQLWarning getWarnings() throws SQLException {
257: return conn.getWarnings();
258: }
259:
260: /**
261: * @see java.sql.Connection#isClosed
262: */
263: public boolean isClosed() throws SQLException {
264: return conn.isClosed();
265: }
266:
267: /**
268: * @see java.sql.Connection#isReadOnly
269: */
270: public boolean isReadOnly() throws SQLException {
271: return conn.isReadOnly();
272: }
273:
274: /**
275: * @see java.sql.Connection#nativeSQL
276: */
277: public String nativeSQL(String str) throws SQLException {
278: return conn.nativeSQL(str);
279: }
280:
281: /**
282: * @see java.sql.Connection#prepareCall
283: */
284: public CallableStatement prepareCall(String str)
285: throws SQLException {
286: return conn.prepareCall(str);
287: }
288:
289: /**
290: * @see java.sql.Connection#prepareCall
291: */
292: public CallableStatement prepareCall(String str, int param,
293: int param2) throws SQLException {
294: return conn.prepareCall(str, param, param2);
295: }
296:
297: /**
298: * @see java.sql.Connection#prepareCall
299: */
300: public CallableStatement prepareCall(String str, int param,
301: int param2, int param3) throws SQLException {
302: return conn.prepareCall(str, param, param2, param3);
303: }
304:
305: /**
306: * @see java.sql.Connection#prepareStatement
307: */
308: public PreparedStatement prepareStatement(String str)
309: throws SQLException {
310: statements.add(str);
311: return conn.prepareStatement(str);
312: }
313:
314: /**
315: * @see java.sql.Connection#prepareStatement
316: */
317: public PreparedStatement prepareStatement(String str, int param)
318: throws SQLException {
319: return conn.prepareStatement(str, param);
320: }
321:
322: /**
323: * @see java.sql.Connection#prepareStatement
324: */
325: public PreparedStatement prepareStatement(String str, int[] values)
326: throws SQLException {
327: return conn.prepareStatement(str, values);
328: }
329:
330: /**
331: * @see java.sql.Connection#prepareStatement
332: */
333: public PreparedStatement prepareStatement(String str, String[] str1)
334: throws SQLException {
335: return conn.prepareStatement(str, str1);
336: }
337:
338: /**
339: * @see java.sql.Connection#prepareStatement
340: */
341: public PreparedStatement prepareStatement(String str, int param,
342: int param2) throws SQLException {
343: return conn.prepareStatement(str, param, param2);
344: }
345:
346: /**
347: * @see java.sql.Connection#prepareStatement
348: */
349: public PreparedStatement prepareStatement(String str, int param,
350: int param2, int param3) throws SQLException {
351: return conn.prepareStatement(str, param, param2, param3);
352: }
353:
354: /**
355: * @see java.sql.Connection#releaseSavepoint
356: */
357: public void releaseSavepoint(Savepoint savepoint)
358: throws SQLException {
359: conn.releaseSavepoint(savepoint);
360: }
361:
362: /**
363: * if not in a transaction, this rolls back the underlying connection immediately,
364: * otherwise nothing is done
365: * @see java.sql.Connection#rollback
366: */
367: public void rollback() throws SQLException {
368: if (!inTrans) {
369: doRollback(null);
370: }
371: }
372:
373: /**
374: * if not in a transaction, this rolls back the underlying connection immediately,
375: * otherwise nothing is done
376: * @see java.sql.Connection#rollback
377: */
378: public void rollback(Savepoint savepoint) throws SQLException {
379: if (!inTrans) {
380: doRollback(savepoint);
381: }
382: }
383:
384: /**
385: * performs the actual rollback on the underlying Connection
386: * @see java.sql.Connection#rollback
387: */
388: public void doRollback(Savepoint savepoint) throws SQLException {
389: if (savepoint == null) {
390: conn.rollback();
391: } else {
392: conn.rollback(savepoint);
393: }
394: }
395:
396: /**
397: * @see java.sql.Connection#setAutoCommit
398: */
399: public void setAutoCommit(boolean param) throws SQLException {
400: conn.setAutoCommit(param);
401: }
402:
403: /**
404: * @see java.sql.Connection#setCatalog
405: */
406: public void setCatalog(String str) throws SQLException {
407: conn.setCatalog(str);
408: }
409:
410: /**
411: * @see java.sql.Connection#setHoldability
412: */
413: public void setHoldability(int param) throws SQLException {
414: conn.setHoldability(param);
415: }
416:
417: /**
418: * @see java.sql.Connection#setReadOnly
419: */
420: public void setReadOnly(boolean param) throws SQLException {
421: conn.setReadOnly(param);
422: }
423:
424: /**
425: * @see java.sql.Connection#setSavepoint
426: */
427: public Savepoint setSavepoint() throws SQLException {
428: return conn.setSavepoint();
429: }
430:
431: /**
432: * @see java.sql.Connection#setSavepoint
433: */
434: public Savepoint setSavepoint(String str) throws SQLException {
435: return conn.setSavepoint(str);
436: }
437:
438: /**
439: * @see java.sql.Connection#setTransactionIsolation
440: */
441: public void setTransactionIsolation(int param) throws SQLException {
442: conn.setTransactionIsolation(param);
443: }
444:
445: /**
446: * @see java.sql.Connection#setTypeMap
447: */
448: public void setTypeMap(Map map) throws SQLException {
449: conn.setTypeMap(map);
450: }
451:
452: /** these methods need implementation **/
453:
454: public void commit(javax.transaction.xa.Xid xid, boolean param)
455: throws XAException {
456: throw new UnsupportedOperationException();
457: }
458:
459: public void end(javax.transaction.xa.Xid xid, int param)
460: throws XAException {
461: throw new UnsupportedOperationException();
462: }
463:
464: public void forget(javax.transaction.xa.Xid xid) throws XAException {
465: throw new UnsupportedOperationException();
466: }
467:
468: public int getTransactionTimeout() throws XAException {
469: throw new UnsupportedOperationException();
470: }
471:
472: public boolean isSameRM(javax.transaction.xa.XAResource xAResource)
473: throws XAException {
474: throw new UnsupportedOperationException();
475: }
476:
477: public int prepare(javax.transaction.xa.Xid xid) throws XAException {
478: return XAResource.XA_OK;
479: }
480:
481: public javax.transaction.xa.Xid[] recover(int param)
482: throws XAException {
483: throw new UnsupportedOperationException();
484: }
485:
486: public void rollback(javax.transaction.xa.Xid xid)
487: throws XAException {
488: try {
489: this .rollback();
490: } catch (SQLException se) {
491: throw new XAException(se.getMessage());
492: }
493: }
494:
495: public boolean setTransactionTimeout(int param) throws XAException {
496: throw new UnsupportedOperationException();
497: }
498:
499: public void start(javax.transaction.xa.Xid xid, int param)
500: throws XAException {
501: throw new UnsupportedOperationException();
502: }
503:
504: }
|