All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.jbossts.xts.bridge.at.BridgeWrapper Maven / Gradle / Ivy

package org.jboss.jbossts.xts.bridge.at;

import com.arjuna.mwlabs.wscf.model.twophase.arjunacore.subordinate.SubordinateATCoordinator;
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.getMapper().getContextFactory(AtomicTransactionConstants.WSAT_PROTOCOL);

    /**
     * this class handles all creation of bridged transactions 
     */

    private BridgeWrapper()
    {
    }

    /**
     * the standard type string used to identify AT AT subordinate transactions. bridge clients
     * must ensure that they do not employ this type for their subordinates.
     */

    public static final String SUBORDINATE_TX_TYPE_AT_AT = SubordinateATCoordinator.SUBORDINATE_TX_TYPE_AT_AT;


    /**
     * 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 subordinateType a unique string which groups subordinates for the benefit of their parent
     * tx/app and allows them to be identified and retrieved as a group during recovery. this must differ
     * from the string {@link SUBORDINATE_TX_TYPE_AT_AT}
     * @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(String subordinateType, 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(subordinateType, expires, isSecure);
        if (bridgeTxData != null) {
            BridgeWrapper bridgeWrapper = new BridgeWrapper();

            bridgeWrapper.context = new TxContextImple(bridgeTxData.context);
            bridgeWrapper.coordinator = bridgeTxData.coordinator;
            bridgeWrapper.id = bridgeTxData.identifier;
            bridgeWrapper.subordinateType = subordinateType;
            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 found in the log
     */
    public static BridgeWrapper recover(String identifier) throws UnknownTransactionException
    {
        SubordinateATCoordinator coordinator = SubordinateATCoordinator.getRecoveredCoordinator(identifier);
        if (coordinator != null) {
            BridgeWrapper bridgeWrapper = new BridgeWrapper();
            bridgeWrapper.context = null;
            bridgeWrapper.coordinator =coordinator;
            bridgeWrapper.id = identifier;
            bridgeWrapper.subordinateType = coordinator.getSubordinateType();
            return bridgeWrapper;
        } else {
            XTSATRecoveryManager recoveryManager = XTSATRecoveryManager.getRecoveryManager();
            if (recoveryManager != null && recoveryManager.isCoordinatorRecoveryStarted()) {
                throw new UnknownTransactionException();
            } else {
                return null;
            }
        }
    }

    /**
     * return a list of bridge wrappers for all recovered subordinate transactions with a given
     * subordinate type
     * @param subordinateType the subordinate type supplied in the original bridge wrapper create call
     * which created the subordinate transaction.
     * @return a possibly zero-length array of bridge wrappers for all recovered subordinate AT transactions
     * with the given subordinate type or null if a subordinate coordinator recovery scan has not yet occurred
     */
    public static BridgeWrapper[] scan(String subordinateType)
    {
        // return null if not yet ready

        XTSATRecoveryManager recoveryManager = XTSATRecoveryManager.getRecoveryManager();
        if (!recoveryManager.isCoordinatorRecoveryStarted()) {
            return null;
        }

        // refuse to expose the internal AT - AT subordinates

        if (subordinateType == null || subordinateType.equals(SUBORDINATE_TX_TYPE_AT_AT)) {
            return EMPTY_SCAN;
        }

        SubordinateATCoordinator[] coordinators = SubordinateATCoordinator.listRecoveredCoordinators();
        int count = 0;

        for (int i = 0; i < coordinators.length; i++) {
            if (coordinators[i].getSubordinateType().equals(subordinateType)) {
                count++;
            }
        }

        if (count == 0) {
            return EMPTY_SCAN;
        }

        BridgeWrapper[] result = new BridgeWrapper[count];
        count = 0;

        for (int i = 0; i < coordinators.length; i++) {
            SubordinateATCoordinator coordinator = coordinators[i];
            if (coordinator.getSubordinateType().equals(subordinateType)) {
                BridgeWrapper bridgeWrapper = new BridgeWrapper();
                bridgeWrapper.context = null;
                bridgeWrapper.coordinator = coordinator;
                bridgeWrapper.id = coordinator.get_uid().stringForm();
                bridgeWrapper.subordinateType = coordinator.getSubordinateType();
                result[count++] = bridgeWrapper;
            }
        }

        return result;
    }

    /**
     * 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();
        }
    }

    /**
     * obtain the subordinate type for the bridged-to transaction
     * @return the subordinate type for the bridged-to transaction
     */
    public String getSubordinateType()
    {
        return subordinateType;
    }

    /**
     * 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 SubordinateATCoordinator coordinator;
    private TxContext context;
    private String id;
    private String subordinateType;

    private final static BridgeWrapper[] EMPTY_SCAN = new BridgeWrapper[0];
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy