package org.jboss.jbossts.xts.bridge.at;
import com.arjuna.mwlabs.wscf.model.twophase.arjunacore.subordinate.SubordinateCoordinator;
import com.arjuna.mwlabs.wst11.at.ContextFactoryImple;
import com.arjuna.mwlabs.wst11.at.context.TxContextImple;
import com.arjuna.mw.wst.TxContext;
import com.arjuna.wst.UnknownTransactionException;
import com.arjuna.wsc11.ContextFactoryMapper;
import com.arjuna.webservices11.wsat.AtomicTransactionConstants;
import com.arjuna.wst.SystemException;
import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManager;
/**
* An API class for use by the JTA ==> AT bridge manager providing a wrapper around a subordinate transaction.
* Static methods are provided to create and register a WS-AT subordinate transaction or to locate a recovered
* transaction. The returned wrapper allows a client to drive the coordinator through prepare, (phase 2) commit
* and/or rollback, to access the transaction id under which the coordinator is registered and, if the transaction
* has not been recovered, to obtain a resumable tx context for the transaction.
*
* n.b. this class only supports bridging to WS-AT 1.1 transactions.
*/
public class BridgeWrapper
{
/**
* cached reference to the WS-AT 1.1. context factory - we only support bridging to WS-AT 1.1 subordinate
* transactions
*/
private static ContextFactoryImple contextFactory =
(ContextFactoryImple)ContextFactoryMapper.getFactory().getContextFactory(AtomicTransactionConstants.WSAT_PROTOCOL);
/**
* this class handles all creation of bridged transactions
*/
private BridgeWrapper()
{
}
/**
* create an AT 1.1 subordinate transaction, associate it with the AT 1.1. registry then return a
* BridgedTransaction wrapper allowing the transaction to be driven through prepare, commit
* and/or rollback and providing access to the transaction id and a context which can be used to
* resume the transaction.
* @param expires the timeout for the bridged-to transaction or 0 if no timeout is required
* @param isSecure true if AT 1.1. protocol messages for the bridged-to transaction should employ
* secure communications, otherwise false
* @return a wrapper for the bridged-to transaction
* @throws SystemException
*/
public static BridgeWrapper create(long expires, boolean isSecure)
{
// the AT 1.1 context factory provides us with a means to create the required data.
ContextFactoryImple.BridgeTxData bridgeTxData = contextFactory.createBridgedTransaction(expires, isSecure);
if (bridgeTxData != null) {
BridgeWrapper bridgeWrapper = new BridgeWrapper();
bridgeWrapper.context = new TxContextImple(bridgeTxData.context);
bridgeWrapper.coordinator = bridgeTxData.coordinator;
bridgeWrapper.id = bridgeTxData.identifier;
return bridgeWrapper;
} else {
return null;
}
}
/**
* recreate a wrapper for a bridged-to WS-AT 1.1 transaction recovered from the log
* @param identifier the identifier of a previously created bridged-to transaction
* @return a wrapper for the bridged-to transaction or null if it may still be awaiting recovery
* @throws UnknownTransactionException if recovery has been performed and no transaction with the
* given identifier has been foung in the log
*/
public static BridgeWrapper recover(String identifier) throws UnknownTransactionException
{
SubordinateCoordinator coordinator = SubordinateCoordinator.getRecoveredCoordinator(identifier);
if (coordinator != null) {
BridgeWrapper bridgeWrapper = new BridgeWrapper();
bridgeWrapper.context = null;
bridgeWrapper.coordinator =coordinator;
bridgeWrapper.id = identifier;
return bridgeWrapper;
} else {
XTSATRecoveryManager recoveryManager = XTSATRecoveryManager.getRecoveryManager();
if (recoveryManager != null && recoveryManager.isCoordinatorRecoveryStarted()) {
throw new UnknownTransactionException();
} else {
return null;
}
}
}
/**
* obtain the identifier for the bridged-to transaction
* @return the identifier for the bridged-to transaction
*/
public String getIdentifier()
{
return id;
}
/**
* obtain a resumable transaction context for the bridged-to transaction
* @return a resumable transaction context
* @throws UnknownTransactionException if this transaction has been recovered from the log and hence
* has no associated transaction context.
*/
public TxContext getContext() throws UnknownTransactionException
{
if (context != null) {
return context;
} else {
throw new UnknownTransactionException();
}
}
/**
* initiate synchronization beforeCompletion processing for the bridged-to transaction
*
* @return true if the beforeCompletion succeeds otherwise false.
*/
public boolean prepareVolatile()
{
return coordinator.prepareVolatile();
}
/**
* prepare the bridged-to transaction
* @return the result of preparing the transaction
*/
public int prepare ()
{
return coordinator.prepare();
}
/**
* initiate synchronization afterCompletion processing for the bridged-to transaction following a
* successful commit
*/
public void commitVolatile()
{
coordinator.commitVolatile();
}
/**
* perform a phase 2 commit for the bridged-to transaction
*/
public void commit ()
{
coordinator.commit();
}
/**
* initiate synchronization afterCompletion processing for the bridged-to transaction following a
* rollback
*/
public void rollbackVolatile()
{
coordinator.rollbackVolatile();
}
/**
* rollback the bridged-to transaction
*/
public void rollback ()
{
coordinator.rollback();
}
private SubordinateCoordinator coordinator;
private TxContext context;
private String id;
}