/*
* $Id: IdegaTransactionManager.java,v 1.15.2.1 2007/01/12 19:32:48 idegaweb Exp $ Created
* in 2001 by Tryggvi Larusson
*
* Copyright (C) 2001-2005 Idega Software hf. All Rights Reserved.
*
* This software is the proprietary information of Idega hf. Use is subject to
* license terms.
*/
package com.idega.transaction;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import com.idega.data.GenericEntity;
import com.idega.data.IDOHome;
import com.idega.data.IDOLookup;
import com.idega.data.IDOLookupException;
import com.idega.repository.data.Instantiator;
import com.idega.repository.data.Singleton;
import com.idega.repository.data.SingletonRepository;
import com.idega.util.ThreadContext;
import com.idega.util.database.ConnectionBroker;
/**
* <p>
* idegaWeb Implementation of the JTA (javax.transaction) TransactionManager
* interface.<br>
* This class works together with ConnectionBroker to mark a Connection for a
* transaction and associate it with the current Thread.
* </p>
* Last modified: $Date: 2007/01/12 19:32:48 $ by $Author: idegaweb $
*
* @author <a href="mailto:tryggvil@idega.com">tryggvil</a>
* @version $Revision: 1.15.2.1 $
*/
public class IdegaTransactionManager implements javax.transaction.TransactionManager, Singleton {
static String transaction_attribute_name = "idega_transaction";
private static Instantiator instantiator = new Instantiator() {
public Object getInstance(Object datasource) {
return new IdegaTransactionManager((String) datasource);
}
};
private String datasource = com.idega.util.database.ConnectionBroker.DEFAULT_POOL;
/**
*
* Only this class can construct itself
*
*/
public String getDatasource() {
return this.datasource;
}
private IdegaTransactionManager(String datasource) {
if (datasource != null) {
this.datasource = datasource;
}
}
/**
* @deprecated use getInstance(String datasource) instead
*/
public static TransactionManager getInstance() {
return getInstance(ConnectionBroker.DEFAULT_POOL);
}
/**
*
* <p>
* The only way to get an instance of the TransactionManager
* </p>
* @param datasource
* @return
*/
public static TransactionManager getInstance(String datasource) {
// uses datasource as identifier, that is there is a singleton for each
// datasource!
return (IdegaTransactionManager) SingletonRepository.getRepository().getInstanceUsingIdentifier(
IdegaTransactionManager.class, instantiator, datasource, datasource);
}
/**
* Looks up the datasource for the returing entity, and calls
* getInstance(datasource)
*
* @param returningEntityInterfaceClass
* @return
*/
public static TransactionManager getInstance(Class returningEntityInterfaceClass) {
try {
IDOHome home = IDOLookup.getHome(returningEntityInterfaceClass);
return getInstance(home.getDatasource());
}
catch (IDOLookupException e) {
e.printStackTrace();
return getInstance();
}
}
/**
*
* Start a transaction, constructs a new Transaction and associates it with
* the current thread.
*
*/
public void begin() throws NotSupportedException, SystemException {
Transaction trans = null;
try {
trans = getTransaction();
}
catch (Exception ex) {
}
/*
* if(transactionAlreadyBegun){ throw new
* NotSupportedException("Transaction already begun, nested transactions
* not currently supported"); }
*/
if (trans == null) {
trans = new IdegaTransaction(this.datasource);
}
begin(trans);
// trans.registerSynchronization(new IdegaTransactionSynchronization());
// ThreadContext.getInstance().setAttribute(Thread.currentThread(),transaction_attribute_name,trans);
}
public void begin(Transaction trans) throws NotSupportedException, SystemException {
/*
* boolean transactionAlreadyBegun=false; boolean
* startingValidUnderTransaction=true; Transaction trans2=null; try{
* trans2 = getTransaction(); if(trans2!=null){
* transactionAlreadyBegun=true; } } catch(Exception ex){ }
*/
/*
* if(transactionAlreadyBegun){ if(trans2.equals(trans)){
* ((IdegaTransaction)trans2).beginSubTransaction(); } else{ throw new
* NotSupportedException("Nested transaction is invalid (does not equal
* to the supertransaction)"); } //throw new
* NotSupportedException("Transaction already begun, nested transactions
* not currently supported"); } else{ //Transaction trans = new
* IdegaTransaction(this.datasource);
* //trans.registerSynchronization(new
* IdegaTransactionSynchronization());
* }
*/
((UserTransaction) trans).begin();
}
/**
*
* Commits the current transaction and deassociates it with the current
* thread.
*
*/
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
java.lang.SecurityException, java.lang.IllegalStateException, SystemException {
Transaction transaction = getTransaction();
transaction.commit();
}
public int getStatus() throws SystemException {
return getTransaction().getStatus();
}
/**
*
* Returns the current Transaction, If no transaction has been begun, it
* creates a new (unassigned) Transaction object
*/
public Transaction getTransaction() throws SystemException {
Transaction trans = (Transaction) ThreadContext.getInstance().getAttribute(Thread.currentThread(),
getTransactionAttributeName());
if (trans == null) {
/**
* Changed -- The transactionManager now creates a new (empty)
* transaction
*/
// throw new SystemException("Transaction not set");
trans = new IdegaTransaction(this.datasource);
}
return trans;
}
/**
*
* UNIMPLEMENTED
*
*/
public void resume(Transaction tobj) throws InvalidTransactionException, java.lang.IllegalStateException,
SystemException {
// Transaction trans = getTransaction();
}
/**
*
* Rollbacks the current transaction and deassociates it with the current
* thread.
*
*/
public void rollback() throws java.lang.IllegalStateException, java.lang.SecurityException, SystemException {
Transaction transaction = getTransaction();
transaction.rollback();
}
public void setRollbackOnly() throws java.lang.IllegalStateException, SystemException {
Transaction trans = getTransaction();
trans.setRollbackOnly();
}
/**
*
* UNIMPLEMENTED
*
*/
public void setTransactionTimeout(int seconds) throws SystemException {
// Transaction trans = getTransaction();
}
/**
*
* UNIMPLEMENTED
*
*/
public Transaction suspend() throws SystemException {
Transaction trans = getTransaction();
return trans;
}
/**
*
* Returns true if the TransactionManager has bound a Transaction Object to
* the current Thread
*
*/
public boolean hasCurrentThreadBoundTransaction() {
/*
* try{ Transaction trans = getTransaction(); } catch(SystemException
* ex){ return false; } return true;
*/
Transaction obj = null;
try {
obj = (Transaction) ThreadContext.getInstance().getAttribute(Thread.currentThread(),
getTransactionAttributeName());
if (obj == null) {
return false;
}
else {
return true;
}
}
catch (Exception ex) {
return false;
}
}
private void endTransaction(IdegaTransaction transaction) {
transaction.end();
}
public void setEntity(GenericEntity entity) {
this.datasource = entity.getDatasource();
}
private String getTransactionAttributeName() {
return transaction_attribute_name + "_" + this.datasource;
}
}