//idega 2000 - Tryggvi Larusson /* *Copyright 2000 idega.is All Rights Reserved. */ package com.idega.transaction; /** *@author <a href="mailto:tryggvi@idega.is">Tryggvi Larusson</a> *@version 1.0 */ import com.idega.util.database.ConnectionBroker; import com.idega.util.ThreadContext; import javax.transaction.*; import javax.transaction.xa.*; import java.sql.*; /** * Title: idegaWeb Implementation of the JTA (javax.transaction) API * Description: * Copyright: Copyright (c) 2002 * Company: idega * @author <a href="tryggvi@idega.is">Tryggvi Larusson</a> */ public class IdegaTransaction implements Transaction, UserTransaction{ /** * * @uml.property name="syncronization" * @uml.associationEnd multiplicity="(0 1)" */ private Synchronization syncronization; private int status=Status.STATUS_NO_TRANSACTION; private boolean isRollBackOnly=false; private Connection _conn; private String _dataSource=ConnectionBroker.DEFAULT_POOL; private int transactionTimeOutSeconds=60*60; private int transactionCount=0; private long transactionBegun = System.currentTimeMillis(); public IdegaTransaction(){ } protected IdegaTransaction(String datasource){ this.setDatasource(datasource); } public void commit()throws RollbackException, HeuristicMixedException, HeuristicRollbackException, java.lang.SecurityException, SystemException{ if(this.getStatus()==Status.STATUS_NO_TRANSACTION){ throw new SystemException("Transaction not begun"); } else{ if(this.transactionCount==1){ try{ doRealCommit(); } catch(RollbackException rbe){ throw (RollbackException)rbe.fillInStackTrace(); } catch(HeuristicMixedException hme){ throw (HeuristicMixedException)hme.fillInStackTrace(); } catch(HeuristicRollbackException hrbe){ throw (HeuristicRollbackException)hrbe.fillInStackTrace(); } catch(SecurityException sce){ throw (SecurityException)sce.fillInStackTrace(); } catch(SystemException se){ throw (SystemException)se.fillInStackTrace(); } finally{ end(); } } else{ this.transactionCount--; } } } protected void doRealCommit()throws RollbackException, HeuristicMixedException, HeuristicRollbackException, java.lang.SecurityException, SystemException{ if(this.isRollBackOnly){ //Do nothing // this.rollback(); this.end(); throw new RollbackException("Transaction Rolled back"); /** * @todo: Should this throw an exception? */ } else{ Synchronization sync = getSynchronization(); if(sync!=null){ sync.beforeCompletion(); } setStatus(Status.STATUS_PREPARING); setStatus(Status.STATUS_PREPARED); setStatus(Status.STATUS_COMMITTING); try{ getConnection().commit(); } catch(SQLException ex){ SystemException exeption = new SystemException(ex.getMessage()); throw (SystemException)exeption.fillInStackTrace(); } setStatus(Status.STATUS_COMMITTED); if(sync!=null){ sync.afterCompletion(getStatus()); } this.end(); } } /** * UNIMPLEMENTED */ public boolean delistResource(XAResource xaRes, int flag)throws java.lang.IllegalStateException, SystemException{ return false; } /** * UNIMPLEMENTED */ public boolean enlistResource(XAResource xaRes)throws RollbackException, java.lang.IllegalStateException, SystemException{ return false; } /** * * @uml.property name="status" */ public int getStatus() throws SystemException { return this.status; } public void registerSynchronization(Synchronization sync)throws RollbackException, java.lang.IllegalStateException, SystemException{ this.syncronization=sync; } public void rollback()throws java.lang.IllegalStateException,SystemException{ if(this.getStatus()==Status.STATUS_NO_TRANSACTION){ throw new SystemException("Transaction not begun"); } else{ if(this.transactionCount==1){ try{ doRealRollback(); } catch(IllegalStateException ise){ throw (IllegalStateException)ise.fillInStackTrace(); } catch(SystemException se){ throw (SystemException)se.fillInStackTrace(); } finally{ end(); } } else{ this.setRollbackOnly(); this.transactionCount--; } } } public void doRealRollback()throws java.lang.IllegalStateException, SystemException{ Synchronization sync = getSynchronization(); if(sync!=null){ sync.beforeCompletion(); } setStatus(Status.STATUS_PREPARING); setStatus(Status.STATUS_PREPARED); setStatus(Status.STATUS_ROLLING_BACK); try{ getConnection().rollback(); } catch(SQLException ex){ SystemException exeption = new SystemException(ex.getMessage()); throw (SystemException)exeption.fillInStackTrace(); } setStatus(Status.STATUS_ROLLEDBACK); if(sync!=null){ sync.afterCompletion(getStatus()); } } public void setRollbackOnly()throws java.lang.IllegalStateException, SystemException{ setRollBackOnly(true); } private void setRollBackOnly(boolean rollbackOnly)throws java.lang.IllegalStateException, SystemException{ if(rollbackOnly){ this.setStatus(Status.STATUS_MARKED_ROLLBACK); } else{ this.setStatus(Status.STATUS_ACTIVE); } this.isRollBackOnly=rollbackOnly; } private Synchronization getSynchronization(){ return this.syncronization; } /** * * @uml.property name="status" */ private void setStatus(int status) { this.status = status; } private Connection getFirstConnection(){ //Connection conn = ConnectionBroker.getConnection(false); Connection conn = ConnectionBroker.getConnection(this._dataSource); initFirstConnection(conn); return conn; } private void initFirstConnection(Connection conn){ try{ //System.out.println("initFirstConnection() conn.getTransactionIsolation()="+conn.getTransactionIsolation()); //System.out.println("initFirstConnection() conn.getMetaData().getDefaultTransactionIsolation()="+conn.getMetaData().getDefaultTransactionIsolation()); //if(conn.getMetaData().getDefaultTransactionIsolation()!=conn.TRANSACTION_NONE){ conn.setAutoCommit(false); //} } catch(SQLException ex){ System.err.println("Error in IdegaTransaction.freeConnection() Message :"+ex.getMessage()); //ex.printStackTrace(System.err); } } public Connection getConnection(){ return this._conn; } public void freeConnection(Connection conn){ if(conn!=null){ try{ //System.out.println("freeConnection() conn.getTransactionIsolation()="+conn.getTransactionIsolation()); //System.out.println("freeConnection() conn.getMetaData().getDefaultTransactionIsolation()="+conn.getMetaData().getDefaultTransactionIsolation()); //if(conn.getMetaData().getDefaultTransactionIsolation()!=conn.TRANSACTION_NONE){ conn.setAutoCommit(true); //} } catch(SQLException ex){ //ex.printStackTrace(System.err); System.err.println("Error in IdegaTransaction.freeConnection() Message :"+ex.getMessage()); } //ConnectionBroker.freeConnection(conn,false); ConnectionBroker.freeConnection(this._dataSource,this._conn,false); this._conn=null; } } protected void end(){ freeConnection(this._conn); this._conn=null; ThreadContext.getInstance().removeAttribute(Thread.currentThread(),getTransactionAttributeName()); } protected void setDatasource(String datasourceName){ this._dataSource=datasourceName; } public void begin() throws javax.transaction.NotSupportedException, javax.transaction.SystemException { if(this.transactionCount==0){ //((IdegaTransactionManager)IdegaTransactionManager.getInstance()).begin(this); this._conn = getFirstConnection(); ThreadContext.getInstance().setAttribute(Thread.currentThread(),getTransactionAttributeName(),this); this.transactionCount=1; this.transactionBegun=System.currentTimeMillis(); setStatus(Status.STATUS_ACTIVE); } else{ beginSubTransaction(); } } public void setTransactionTimeout(int parm1) throws javax.transaction.SystemException { this.transactionTimeOutSeconds=parm1; } public void beginSubTransaction(){ this.transactionCount++; } private String getTransactionAttributeName() { return IdegaTransactionManager.transaction_attribute_name+"_"+this._dataSource; } }