/* ====================================================================
* The LateralNZ Software License, Version 1.0
*
* Copyright (c) 2003 LateralNZ. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by
* LateralNZ (http://www.lateralnz.org/) and other third parties."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "LateralNZ" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please
* contact oss@lateralnz.org.
*
* 5. Products derived from this software may not be called "Panther",
* or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
* "LATERALNZ" appear in their name, without prior written
* permission of LateralNZ.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of LateralNZ. For more
* information on Lateral, please see http://www.lateralnz.com/ or
* http://www.lateralnz.org
*
*/
package org.lateralnz.simpletrans;
import java.io.Serializable;
import java.sql.*;
import java.util.Map;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.XAException;
import org.apache.log4j.Logger;
import org.lateralnz.common.util.DAOUtils;
/**
* a 'transaction-aware' wrapper for a JDBC connection. This is used to ensure
* that a connection is only commited, rolled back or closed until required
* by a transaction
*
* @author J R Briggs
*/
public class TransConnection implements Connection, XAResource, Serializable {
private static final Logger log = Logger.getLogger(TransConnection.class.getName());
private String name;
private Connection conn;
private boolean close = false;
private boolean inTrans = false;
private long tempTime;
private java.util.ArrayList statements = null;
/**
* wrap a JDBC connection with the specified name
*/
public TransConnection(String name, Connection conn, boolean inTrans) throws SQLException {
this.name = name;
this.conn = conn;
this.inTrans = inTrans;
this.conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
/* JRB 15/09/2004: this isn't needed by the look of things. setAutoCommit to false
* seems to already start the transaction (which is done in enlistResource in the
* transaction) -- at least in the postgres driver. Need to test with other
* databases to confirm this.
Statement st = conn.createStatement();
try {
st.executeUpdate("start transaction");
}
finally {
DAOUtils.close(st);
}*/
statements = new java.util.ArrayList();
if (log.isDebugEnabled()) {
tempTime = System.currentTimeMillis();
log.debug("created new transaction connection for jdbc conn " + conn);
}
}
/**
* get the name of this connection
*/
public String getName() {
return name;
}
/**
* @see java.sql.Connection#clearWarnings
*/
public void clearWarnings() throws SQLException {
conn.clearWarnings();
}
/**
* if not in a transaction, this closes the connection immediately,
* otherwise just flags that a close is required
* @see java.sql.Connection#close
*/
public void close() throws SQLException {
if (!inTrans) {
doClose();
}
else {
close = true;
}
}
/**
* check if close has been flagged on this connection
*/
public boolean isCloseFlagged() {
return close;
}
/**
* performs the actual close on the underlying connection
*/
protected void doClose() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("closing connection " + conn);
tempTime = System.currentTimeMillis() - tempTime;
if (tempTime > 15000) {
log.debug("time between opening and closing conn " + conn + " was " + tempTime + " after performing " + statements.toString());
}
}
conn.close();
}
/**
* if not in a transaction, a commit is performed immediately,
* otherwise nothing happens
* @see java.sql.Connection#commit
*/
public void commit() throws SQLException {
if (!inTrans) {
doCommit();
}
}
/**
* performs the actual commit on the underlying connection
*/
public void doCommit() throws SQLException {
conn.commit();
}
/**
* @see java.sql.Connection#createStatement
*/
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
/**
* @see java.sql.Connection#createStatement
*/
public Statement createStatement(int param, int param1) throws SQLException {
return conn.createStatement(param, param1);
}
/**
* @see java.sql.Connection#createStatement
*/
public Statement createStatement(int param, int param1, int param2) throws SQLException {
return conn.createStatement(param, param1, param2);
}
/**
* @see java.sql.Connection#getAutoCommit
*/
public boolean getAutoCommit() throws SQLException {
return conn.getAutoCommit();
}
/**
* @see java.sql.Connection#getCatalog
*/
public String getCatalog() throws SQLException {
return conn.getCatalog();
}
/**
* @see java.sql.Connection#getHoldability
*/
public int getHoldability() throws SQLException {
return conn.getHoldability();
}
/**
* @see java.sql.Connection#getMetaData
*/
public DatabaseMetaData getMetaData() throws SQLException {
return conn.getMetaData();
}
/**
* @see java.sql.Connection#getTransactionIsolation
*/
public int getTransactionIsolation() throws SQLException {
return conn.getTransactionIsolation();
}
/**
* @see java.sql.Connection#getTypeMap
*/
public Map getTypeMap() throws SQLException {
return conn.getTypeMap();
}
/**
* @see java.sql.Connection#getWarnings
*/
public SQLWarning getWarnings() throws SQLException {
return conn.getWarnings();
}
/**
* @see java.sql.Connection#isClosed
*/
public boolean isClosed() throws SQLException {
return conn.isClosed();
}
/**
* @see java.sql.Connection#isReadOnly
*/
public boolean isReadOnly() throws SQLException {
return conn.isReadOnly();
}
/**
* @see java.sql.Connection#nativeSQL
*/
public String nativeSQL(String str) throws SQLException {
return conn.nativeSQL(str);
}
/**
* @see java.sql.Connection#prepareCall
*/
public CallableStatement prepareCall(String str) throws SQLException {
return conn.prepareCall(str);
}
/**
* @see java.sql.Connection#prepareCall
*/
public CallableStatement prepareCall(String str, int param, int param2) throws SQLException {
return conn.prepareCall(str, param, param2);
}
/**
* @see java.sql.Connection#prepareCall
*/
public CallableStatement prepareCall(String str, int param, int param2, int param3) throws SQLException {
return conn.prepareCall(str, param, param2, param3);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str) throws SQLException {
statements.add(str);
return conn.prepareStatement(str);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str, int param) throws SQLException {
return conn.prepareStatement(str, param);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str, int[] values) throws SQLException {
return conn.prepareStatement(str, values);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str, String[] str1) throws SQLException {
return conn.prepareStatement(str, str1);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str, int param, int param2) throws SQLException {
return conn.prepareStatement(str, param, param2);
}
/**
* @see java.sql.Connection#prepareStatement
*/
public PreparedStatement prepareStatement(String str, int param, int param2, int param3) throws SQLException {
return conn.prepareStatement(str, param, param2, param3);
}
/**
* @see java.sql.Connection#releaseSavepoint
*/
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
conn.releaseSavepoint(savepoint);
}
/**
* if not in a transaction, this rolls back the underlying connection immediately,
* otherwise nothing is done
* @see java.sql.Connection#rollback
*/
public void rollback() throws SQLException {
if (!inTrans) {
doRollback(null);
}
}
/**
* if not in a transaction, this rolls back the underlying connection immediately,
* otherwise nothing is done
* @see java.sql.Connection#rollback
*/
public void rollback(Savepoint savepoint) throws SQLException {
if (!inTrans) {
doRollback(savepoint);
}
}
/**
* performs the actual rollback on the underlying Connection
* @see java.sql.Connection#rollback
*/
public void doRollback(Savepoint savepoint) throws SQLException {
if (savepoint == null) {
conn.rollback();
}
else {
conn.rollback(savepoint);
}
}
/**
* @see java.sql.Connection#setAutoCommit
*/
public void setAutoCommit(boolean param) throws SQLException {
conn.setAutoCommit(param);
}
/**
* @see java.sql.Connection#setCatalog
*/
public void setCatalog(String str) throws SQLException {
conn.setCatalog(str);
}
/**
* @see java.sql.Connection#setHoldability
*/
public void setHoldability(int param) throws SQLException {
conn.setHoldability(param);
}
/**
* @see java.sql.Connection#setReadOnly
*/
public void setReadOnly(boolean param) throws SQLException {
conn.setReadOnly(param);
}
/**
* @see java.sql.Connection#setSavepoint
*/
public Savepoint setSavepoint() throws SQLException {
return conn.setSavepoint();
}
/**
* @see java.sql.Connection#setSavepoint
*/
public Savepoint setSavepoint(String str) throws SQLException {
return conn.setSavepoint(str);
}
/**
* @see java.sql.Connection#setTransactionIsolation
*/
public void setTransactionIsolation(int param) throws SQLException {
conn.setTransactionIsolation(param);
}
/**
* @see java.sql.Connection#setTypeMap
*/
public void setTypeMap(Map map) throws SQLException {
conn.setTypeMap(map);
}
/** these methods need implementation **/
public void commit(javax.transaction.xa.Xid xid, boolean param) throws XAException {
throw new UnsupportedOperationException();
}
public void end(javax.transaction.xa.Xid xid, int param) throws XAException {
throw new UnsupportedOperationException();
}
public void forget(javax.transaction.xa.Xid xid) throws XAException {
throw new UnsupportedOperationException();
}
public int getTransactionTimeout() throws XAException {
throw new UnsupportedOperationException();
}
public boolean isSameRM(javax.transaction.xa.XAResource xAResource) throws XAException {
throw new UnsupportedOperationException();
}
public int prepare(javax.transaction.xa.Xid xid) throws XAException {
return XAResource.XA_OK;
}
public javax.transaction.xa.Xid[] recover(int param) throws XAException {
throw new UnsupportedOperationException();
}
public void rollback(javax.transaction.xa.Xid xid) throws XAException {
try {
this.rollback();
}
catch (SQLException se) {
throw new XAException(se.getMessage());
}
}
public boolean setTransactionTimeout(int param) throws XAException {
throw new UnsupportedOperationException();
}
public void start(javax.transaction.xa.Xid xid, int param) throws XAException {
throw new UnsupportedOperationException();
}
}
|