package org.jboss.tm.iiop.client;
import java.io.Serializable;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.UserTransaction;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.INVALID_TRANSACTION;
import org.omg.CORBA.NO_PERMISSION;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosTransactions.Control;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.Inactive;
import org.omg.CosTransactions.NoTransaction;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.SubtransactionsUnavailable;
import org.omg.CosTransactions.Terminator;
import org.jboss.iiop.CorbaORB;
import org.jboss.tm.iiop.TransactionDesc;
import org.jboss.tm.iiop.TransactionFactoryExt;
import org.jboss.tm.iiop.TransactionFactoryExtHelper;
import org.jboss.tm.iiop.TxClientInterceptor;
public class IIOPClientUserTransaction
implements UserTransaction,
Referenceable,
Serializable
{
static final long serialVersionUID = 6653800687253055416L;
private static IIOPClientUserTransaction singleton = null;
private static TransactionFactoryExt txFactory;
private static ThreadLocal threadLocalData = new ThreadLocal() {
protected synchronized Object initialValue()
{
return new TransactionInfo(); }
};
private static class TransactionInfo
{
int timeout = 0; Control control; Coordinator coord; Terminator term; }
private static void setThreadLocalTimeout(int timeout)
{
((TransactionInfo)threadLocalData.get()).timeout = timeout;
}
private static int getThreadLocalTimeout()
{
return ((TransactionInfo)threadLocalData.get()).timeout;
}
private static void setThreadLocalControl(Control control)
{
((TransactionInfo)threadLocalData.get()).control = control;
}
private static Control getThreadLocalControl()
{
return ((TransactionInfo)threadLocalData.get()).control;
}
private static void setThreadLocalCoordinator(Coordinator coord)
{
((TransactionInfo)threadLocalData.get()).coord = coord;
}
private static Coordinator getThreadLocalCoordinator()
{
return ((TransactionInfo)threadLocalData.get()).coord;
}
private static void setThreadLocalTerminator(Terminator term)
{
((TransactionInfo)threadLocalData.get()).term = term;
}
private static Terminator getThreadLocalTerminator()
throws NoTransaction
{
Terminator term = ((TransactionInfo)threadLocalData.get()).term;
if (term == null)
throw new NoTransaction();
return term;
}
private static void setCurrentTransaction(Control control,
PropagationContext pc)
{
setThreadLocalControl(control);
setThreadLocalCoordinator(pc.current.coord);
setThreadLocalTerminator(pc.current.term);
TxClientInterceptor.setOutgoingPropagationContext(pc);
}
private static void unsetCurrentTransaction()
{
setThreadLocalControl(null);
setThreadLocalCoordinator(null);
setThreadLocalTerminator(null);
TxClientInterceptor.unsetOutgoingPropagationContext();
}
private static TransactionFactoryExt getTxFactory()
{
if (txFactory == null)
{
try
{
ORB orb = CorbaORB.getInstance();
org.omg.CORBA.Object obj =
orb.resolve_initial_references("NameService");
NamingContextExt rootContext = NamingContextExtHelper.narrow(obj);
org.omg.CORBA.Object txFactoryObj =
rootContext.resolve_str("TransactionService");
txFactory = TransactionFactoryExtHelper.narrow(txFactoryObj);
}
catch (Exception e)
{
throw new RuntimeException("Could not get transaction factory: "
+ e);
}
}
return txFactory;
}
private static int cosTransactionsToJavax(
org.omg.CosTransactions.Status status)
{
switch (status.value())
{
case org.omg.CosTransactions.Status._StatusActive:
return javax.transaction.Status.STATUS_ACTIVE;
case org.omg.CosTransactions.Status._StatusCommitted:
return javax.transaction.Status.STATUS_COMMITTED;
case org.omg.CosTransactions.Status._StatusCommitting:
return javax.transaction.Status.STATUS_COMMITTING;
case org.omg.CosTransactions.Status._StatusMarkedRollback:
return javax.transaction.Status.STATUS_MARKED_ROLLBACK;
case org.omg.CosTransactions.Status._StatusNoTransaction:
return javax.transaction.Status.STATUS_NO_TRANSACTION;
case org.omg.CosTransactions.Status._StatusPrepared:
return javax.transaction.Status.STATUS_PREPARED;
case org.omg.CosTransactions.Status._StatusPreparing:
return javax.transaction.Status.STATUS_PREPARING;
case org.omg.CosTransactions.Status._StatusRolledBack:
return javax.transaction.Status.STATUS_ROLLEDBACK;
case org.omg.CosTransactions.Status._StatusRollingBack:
return javax.transaction.Status.STATUS_ROLLING_BACK;
case org.omg.CosTransactions.Status._StatusUnknown:
return javax.transaction.Status.STATUS_UNKNOWN;
default:
return javax.transaction.Status.STATUS_UNKNOWN;
}
}
private IIOPClientUserTransaction()
{
}
public static IIOPClientUserTransaction getSingleton()
{
if (singleton == null)
singleton = new IIOPClientUserTransaction();
return singleton;
}
public void begin()
throws NotSupportedException, SystemException
{
if (getThreadLocalControl() != null)
throw new NotSupportedException();
try
{
TransactionDesc td =
getTxFactory().create_transaction(getThreadLocalTimeout());
setCurrentTransaction(td.control, td.propagationContext);
}
catch (RuntimeException e)
{
throw new SystemException(e.toString());
}
}
public void commit()
throws RollbackException,
HeuristicMixedException,
HeuristicRollbackException,
SecurityException,
IllegalStateException,
SystemException
{
try
{
getThreadLocalTerminator().commit(true );
unsetCurrentTransaction();
}
catch (NoTransaction e)
{
throw new IllegalStateException(e.toString());
}
catch (HeuristicMixed e)
{
throw new HeuristicMixedException(e.toString());
}
catch (HeuristicHazard e)
{
throw new HeuristicRollbackException(e.toString());
}
catch (TRANSACTION_ROLLEDBACK e)
{
throw new RollbackException(e.toString());
}
catch (BAD_INV_ORDER e)
{
throw new IllegalStateException(e.toString());
}
catch (NO_PERMISSION e)
{
throw new SecurityException(e.toString());
}
catch (RuntimeException e)
{
throw new SystemException(e.toString());
}
}
public void rollback()
throws SecurityException,
IllegalStateException,
SystemException
{
try
{
getThreadLocalTerminator().rollback();
unsetCurrentTransaction();
}
catch (NoTransaction e)
{
throw new IllegalStateException(e.toString());
}
catch (BAD_INV_ORDER e)
{
throw new IllegalStateException(e.toString());
}
catch (NO_PERMISSION e)
{
throw new SecurityException(e.toString());
}
catch (RuntimeException e)
{
throw new SystemException(e.toString());
}
}
public void setRollbackOnly()
throws IllegalStateException,
SystemException
{
Coordinator coord = getThreadLocalCoordinator();
if (coord == null)
throw new IllegalStateException();
try
{
coord.rollback_only();
}
catch (Inactive e)
{
throw new SystemException(e.toString());
}
catch (BAD_INV_ORDER e)
{
throw new IllegalStateException(e.toString());
}
catch (RuntimeException e)
{
throw new SystemException(e.toString());
}
}
public int getStatus()
throws SystemException
{
try
{
Coordinator coord = getThreadLocalCoordinator();
if (coord == null)
return Status.STATUS_NO_TRANSACTION;
else
return cosTransactionsToJavax(coord.get_status());
}
catch (RuntimeException e)
{
throw new SystemException(e.toString());
}
}
public void setTransactionTimeout(int seconds)
throws SystemException
{
setThreadLocalTimeout(seconds);
}
public Reference getReference()
throws NamingException
{
Reference ref = new Reference(
"org.jboss.tm.iiop.client.IIOPClientUserTransaction",
"org.jboss.tm.iiop.client.IIOPClientUserTransactionObjectFactory",
null);
return ref;
}
}