package org.jboss.tm.iiop.client;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.TCKind;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.InvalidName;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.CosTransactions.Control;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.Current;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.Inactive;
import org.omg.CosTransactions.InvalidControl;
import org.omg.CosTransactions.NoTransaction;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.Status;
import org.omg.CosTransactions.Status;
import org.omg.CosTransactions.SubtransactionsUnavailable;
import org.omg.CosTransactions.Terminator;
import org.omg.CosTransactions.Unavailable;
import org.omg.PortableInterceptor.InvalidSlot;
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 TransactionCurrent
extends LocalObject
implements Current
{
private static TransactionCurrent instance = null; private static TransactionFactoryExt txFactory;
private static Set suspendedTransactions =
Collections.synchronizedSet (new HashSet());
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();
}
public static void init(NamingContextExt nc)
{
try
{
org.omg.CORBA.Object txFactoryObj =
nc.resolve_str("TransactionService");
txFactory = TransactionFactoryExtHelper.narrow(txFactoryObj);
}
catch (CannotProceed e)
{
throw new RuntimeException(
"Exception initializing TransactionCurrent: " + e);
}
catch (NotFound e)
{
throw new RuntimeException(
"Exception initializing TransactionCurrent: " + e);
}
catch (InvalidName e)
{
throw new RuntimeException(
"Exception initializing TransactionCurrent: " + e);
}
}
public static synchronized TransactionCurrent getInstance()
{
if (instance == null)
instance = new TransactionCurrent();
return instance;
}
public void begin()
throws SubtransactionsUnavailable
{
if (getThreadLocalControl() != null)
throw new SubtransactionsUnavailable();
TransactionDesc td = txFactory.create_transaction(
getThreadLocalTimeout());
setCurrentTransaction(td.control, td.propagationContext);
}
public void commit(boolean reportHeuristics)
throws NoTransaction,
HeuristicHazard,
HeuristicMixed
{
getThreadLocalTerminator().commit(reportHeuristics);
unsetCurrentTransaction();
}
public void rollback()
throws NoTransaction
{
getThreadLocalTerminator().rollback();
unsetCurrentTransaction();
}
public void rollback_only()
throws NoTransaction
{
try
{
Coordinator coord = getThreadLocalCoordinator();
if (coord == null)
throw new NoTransaction();
coord.rollback_only();
}
catch (Inactive e)
{
throw new RuntimeException("Current transaction already prepared: "
+ e);
}
}
public Status get_status()
{
Coordinator coord = getThreadLocalCoordinator();
return (coord == null) ? Status.StatusNoTransaction : coord.get_status();
}
public String get_transaction_name()
{
Coordinator coord = getThreadLocalCoordinator();
return (coord == null) ? "" : coord.get_transaction_name();
}
public void set_timeout(int timeOut)
{
setThreadLocalTimeout(timeOut);
}
public Control get_control()
{
return getThreadLocalControl();
}
public Control suspend()
{
Control control = getThreadLocalControl();
if (control != null)
{
unsetCurrentTransaction();
suspendedTransactions.add(control);
}
return control;
}
public void resume(Control whichTransaction)
throws InvalidControl
{
try
{
if (whichTransaction == null)
throw new InvalidControl();
if (!suspendedTransactions.remove(whichTransaction))
throw new InvalidControl();
Coordinator coord = whichTransaction.get_coordinator();
if (coord == null)
throw new InvalidControl();
PropagationContext pc = coord.get_txcontext(); setCurrentTransaction(whichTransaction, pc);
}
catch (Unavailable e)
{
throw new InvalidControl();
}
}
}