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

io.agroal.narayana.LocalXAResource Maven / Gradle / Ivy

// Copyright (C) 2017 Red Hat, Inc. and individual contributors as indicated by the @author tags.
// You may not use this file except in compliance with the Apache License, Version 2.0.

package io.agroal.narayana;

import io.agroal.api.transaction.TransactionAware;
import org.jboss.tm.XAResourceWrapper;

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import static javax.transaction.xa.XAException.XAER_INVAL;
import static javax.transaction.xa.XAException.XAER_NOTA;
import static javax.transaction.xa.XAException.XAER_RMERR;
import static javax.transaction.xa.XAException.XA_RBROLLBACK;

/**
 * @author Luis Barreiro
 * @author Jesper Pedersen
 */
public class LocalXAResource implements XAResourceWrapper {

    private static final String PRODUCT_NAME = LocalXAResource.class.getPackage().getImplementationTitle();
    private static final String PRODUCT_VERSION = LocalXAResource.class.getPackage().getImplementationVersion();
    
    private final TransactionAware transactionAware;
    private final String jndiName;
    private Xid currentXid;

    public LocalXAResource(TransactionAware transactionAware, String jndiName) {
        this.transactionAware = transactionAware;
        this.jndiName = jndiName;
    }

    public Object getConnection() throws Throwable {
        return transactionAware.getConnection();
    }

    @Override
    public void start(Xid xid, int flags) throws XAException {
        if ( currentXid == null ) {
            if ( flags != TMNOFLAGS ) {
                throw xaException( XAER_INVAL, "Starting resource with wrong flags" );
            }
            try {
                transactionAware.transactionStart();
            } catch ( Exception t ) {
                transactionAware.setFlushOnly();
                throw xaException( XAER_RMERR, "Error trying to start local transaction: ", t );
            }
            currentXid = xid;
        } else {
            if ( flags != TMJOIN && flags != TMRESUME ) {
                throw xaException( XAException.XAER_DUPID, "Invalid flag for join|resume" );
            }
        }
    }

    @Override
    public void commit(Xid xid, boolean onePhase) throws XAException {
        if ( xid == null || !xid.equals( currentXid ) ) {
            throw xaException( XAER_NOTA, "Invalid xid to transactionCommit" );
        }

        currentXid = null;
        try {
            transactionAware.transactionBeforeCompletion( true );
            transactionAware.transactionCommit();
        } catch ( Exception t ) {
            transactionAware.setFlushOnly();
            throw xaException( onePhase ? XA_RBROLLBACK : XAER_RMERR, "Error trying to transactionCommit local transaction: ", t );
        }
    }

    @Override
    public void rollback(Xid xid) throws XAException {
        if ( xid == null || !xid.equals( currentXid ) ) {
            throw xaException( XAER_NOTA, "Invalid xid to transactionRollback" );
        }

        currentXid = null;
        try {
            transactionAware.transactionBeforeCompletion( false );
            transactionAware.transactionRollback();
        } catch ( Exception t ) {
            transactionAware.setFlushOnly();
            throw xaException( XAER_RMERR, "Error trying to transactionRollback local transaction: ", t );
        }
    }

    @Override
    public void end(Xid xid, int flags) throws XAException {
        if ( xid == null || !xid.equals( currentXid ) ) {
            transactionAware.setFlushOnly();
            throw xaException( XAER_NOTA, "Invalid xid to transactionEnd" );
        }
    }

    @Override
    public void forget(Xid xid) throws XAException {
        transactionAware.setFlushOnly();
        throw xaException( XAER_NOTA, "Forget not supported in local XA resource" );
    }

    @Override
    public int getTransactionTimeout() throws XAException {
        return 0;
    }

    @Override
    public boolean isSameRM(XAResource xaResource) throws XAException {
        return this == xaResource;
    }

    @Override
    public int prepare(Xid xid) throws XAException {
        return XA_OK;
    }

    @Override
    public Xid[] recover(int flags) throws XAException {
        transactionAware.setFlushOnly();
        throw xaException( XAER_RMERR, "No recover in local XA resource");
    }

    @Override
    public boolean setTransactionTimeout(int timeout) throws XAException {
        return false;
    }

    @SuppressWarnings( "StringConcatenation" )
    private static XAException xaException(int errorCode, String message, Throwable cause) {
        XAException xaException = xaException( errorCode, message + cause.getMessage() );
        xaException.initCause( cause );
        return xaException;
    }

    private static XAException xaException(int errorCode, String message ) {
        XAException xaException = new XAException( message );
        xaException.errorCode = errorCode;
        return xaException;
    }

    // --- XA Resource Wrapper //

    @Override
    public XAResource getResource() {
        return this;
    }

    @Override
    public String getProductName() {
        return PRODUCT_NAME;
    }

    @Override
    public String getProductVersion() {
        return PRODUCT_VERSION;
    }

    @Override
    public String getJndiName() {
        return jndiName;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy