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

com.sun.jts.jta.TransactionManagerImpl Maven / Gradle / Ivy

There is a newer version: 8.0.0-JDK17-M7
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright 2021 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.jts.jta;

import java.util.*;
import jakarta.transaction.*;
import java.io.File;
import org.omg.CosTransactions.*;
import org.omg.CORBA.*;
import org.omg.CORBA.ORBPackage.InvalidName;

import com.sun.jts.CosTransactions.*;
import com.sun.jts.codegen.otsidl.*;

import jakarta.transaction.SystemException;
import org.omg.CosTransactions.Status;
import org.omg.CosTransactions.Current;
import org.omg.CosTransactions.NoTransaction;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicHazard;
import com.sun.jts.CosTransactions.GlobalTID;

import javax.transaction.xa.Xid;
import jakarta.resource.spi.work.WorkException;
import jakarta.resource.spi.work.WorkCompletedException;


import java.util.logging.Logger;
import java.util.logging.Level;
import com.sun.logging.LogDomains;
import com.sun.jts.utils.LogFormatter;
import org.glassfish.internal.api.Globals;

/**
 * An implementation of jakarta.transaction.TransactionManager using JTA.
 *
 * This is a singleton object
 *
 * @author Tony Ng
 */
public class TransactionManagerImpl implements TransactionManager {

    /**
     * the singleton object
     */
    static private TransactionManagerImpl tm = null;

    /**
     * store the current psuedo object
     */
    private Current current;

    /**
     * a mapping of GlobalTID -> TransactionState
     */
    // private Hashtable transactionStates;

    static private int[] directLookup;
    static final int maxStatus;

    /*
        Logger to log transaction messages
    */
    static Logger _logger = LogDomains.getLogger(TransactionManagerImpl.class, LogDomains.TRANSACTION_LOGGER);

      //START IASRI 4706150

    /**
    * store XAResource Timeout
    */
    static private int xaTimeOut = 0;
      //END IASRI 4706150

    static private Status CosTransactionStatus[] =
    {
        org.omg.CosTransactions.Status.StatusActive,
        org.omg.CosTransactions.Status.StatusMarkedRollback,
        org.omg.CosTransactions.Status.StatusPrepared,
        org.omg.CosTransactions.Status.StatusCommitted,
        org.omg.CosTransactions.Status.StatusRolledBack,
        org.omg.CosTransactions.Status.StatusUnknown,
        org.omg.CosTransactions.Status.StatusNoTransaction,
        org.omg.CosTransactions.Status.StatusPreparing,
        org.omg.CosTransactions.Status.StatusCommitting,
        org.omg.CosTransactions.Status.StatusRollingBack
    };

    static private int JTAStatus[] =
    {
        jakarta.transaction.Status.STATUS_ACTIVE,
        jakarta.transaction.Status.STATUS_MARKED_ROLLBACK,
        jakarta.transaction.Status.STATUS_PREPARED,
        jakarta.transaction.Status.STATUS_COMMITTED,
        jakarta.transaction.Status.STATUS_ROLLEDBACK,
        jakarta.transaction.Status.STATUS_UNKNOWN,
        jakarta.transaction.Status.STATUS_NO_TRANSACTION,
        jakarta.transaction.Status.STATUS_PREPARING,
        jakarta.transaction.Status.STATUS_COMMITTING,
        jakarta.transaction.Status.STATUS_ROLLING_BACK
    };

    static {
        int calcMaxStatus = 0;
        for (int i=0; i maxStatus) {
            return jakarta.transaction.Status.STATUS_UNKNOWN;
        } else {
            return directLookup[statusVal];
        }
    }

    /**
     * Create a new transaction and associate it with the current thread.
     *
     * @exception NotSupportedException Thrown if the thread is already
     *    associated with a transaction.
     */
    public void begin()
        throws NotSupportedException, SystemException {

        try {
            // does not support nested transaction
            if (current.get_control() != null) {
                throw new NotSupportedException();
            }
            current.begin();
        } catch (TRANSACTION_ROLLEDBACK ex) {
            throw new NotSupportedException();
        } catch (SubtransactionsUnavailable ex) {
            throw new SystemException();
        }
    }

    //START IASRI PERFIMPROVEMNT
    /**
     * Create a new transaction with the given timeout and associate it
     *        with the current thread.
     *
     * @exception NotSupportedException Thrown if the thread is already
     *    associated with a transaction.
     */
    public void begin(int timeout)
        throws NotSupportedException, SystemException {
        try {
            // does not support nested transaction
            if (current.get_control() != null) {
                throw new NotSupportedException();
            }
            ((com.sun.jts.CosTransactions.CurrentImpl)current).begin(timeout);
        } catch (TRANSACTION_ROLLEDBACK ex) {
            throw new NotSupportedException();
        } catch (SubtransactionsUnavailable ex) {
            throw new SystemException();
        }
    }
    //END IASRI PERFIMPROVEMNT

    /**
     * Complete the transaction associated with the current thread. When this
     * method completes, the thread becomes associated with no transaction.
     *
     * @exception RollbackException Thrown to indicate that
     *    the transaction has been rolled back rather than committed.
     *
     * @exception HeuristicMixedException Thrown to indicate that a heuristic
     *    decision was made and that some relevant updates have been committed
     *    while others have been rolled back.
     *
     * @exception HeuristicRollbackException Thrown to indicate that a
     *    heuristic decision was made and that all relevant updates have been
     *    rolled back.
     *
     * @exception SecurityException Thrown to indicate that the thread is
     *    not allowed to commit the transaction.
     *
     * @exception IllegalStateException Thrown if the current thread is
     *    not associated with a transaction.
     */
    public void commit() throws RollbackException,
    HeuristicMixedException, HeuristicRollbackException, SecurityException,
    IllegalStateException, SystemException {

        try {
            current.commit(true);
        } catch (TRANSACTION_ROLLEDBACK ex) {
            RollbackException rbe = new RollbackException();
            Throwable cause = ex.getCause();
            if (cause != null) {
                rbe.initCause(cause);
            }
            throw rbe;
        } catch (NoTransaction ex) {
            throw new IllegalStateException();
        } catch (NO_PERMISSION ex) {
            throw new SecurityException();
        } catch (HeuristicMixed ex) {
            throw new HeuristicMixedException();
        } catch (HeuristicHazard ex) {
            throw new HeuristicRollbackException();
        } catch (Exception ex) {
            // ex.printStackTrace();
            throw new SystemException(ex.toString());
        }
        /***
        Transaction tran = getTransaction();
        if (tran == null) throw new IllegalStateException();
        tran.commit();
        ***/
    }

    /**
     * Roll back the transaction associated with the current thread. When this
     * method completes, the thread becomes associated with no transaction.
     *
     * @exception SecurityException Thrown to indicate that the thread is
     *    not allowed to roll back the transaction.
     *
     * @exception IllegalStateException Thrown if the current thread is
     *    not associated with a transaction.
     */
    public void rollback()
        throws IllegalStateException, SecurityException, SystemException {

        try {
            current.rollback();
        } catch (NoTransaction ex) {
            throw new IllegalStateException();
        } catch (NO_PERMISSION ex) {
            throw new SecurityException();
        } catch (Exception ex) {
            throw new SystemException(ex.toString());
        }

        /***
        Transaction tran = getTransaction();
        if (tran == null) throw new IllegalStateException();
        tran.rollback();
        ***/
    }

    /**
     * Modify the transaction associated with the current thread such that
     * the only possible outcome of the transaction is to roll back the
     * transaction.
     *
     * @exception IllegalStateException Thrown if the current thread is
     *    not associated with a transaction.
     */
    public void setRollbackOnly()
        throws IllegalStateException, SystemException {

        try {
            current.rollback_only();
        } catch (NoTransaction ex) {
            throw new IllegalStateException();
        } catch (Exception ex) {
            throw new SystemException(ex.toString());
        }
    }

    /**
     * Obtain the status of the transaction associated with the current thread.
     *
     * @return The transaction status. If no transaction is associated with
     *    the current thread, this method returns the Status.NoTransaction
     *    value.
     */
    public int getStatus() throws SystemException {
        try {
            Status status = current.get_status();
            return mapStatus(status);
        } catch (Exception ex) {
            throw new SystemException(ex.toString());
        }
    }

    /**
     * Modify the timeout value that is associated with transactions started
     * by subsequent invocations of the begin method.
     *
     * 

If an application has not called this method, the transaction * service uses some default value for the transaction timeout. * * @param seconds The value of the timeout in seconds. If the value is zero, * the transaction service restores the default value. If the value * is negative a SystemException is thrown. * * @exception SystemException Thrown if the transaction manager * encounters an unexpected error condition. * */ public synchronized void setTransactionTimeout(int seconds) throws SystemException { try { if (seconds < 0) { String msg = LogFormatter.getLocalizedMessage(_logger, "jts.invalid_timeout"); throw new SystemException(msg); } current.set_timeout(seconds); } catch (Exception ex) { throw new SystemException(ex.toString()); } } /** * Get the transaction object that represents the transaction * context of the calling thread */ public Transaction getTransaction() throws SystemException { try { Control control = current.get_control(); if (control == null) { return null; } else { return createTransactionImpl(control); } } catch (Unavailable uex) { throw new SystemException(uex.toString()); } catch (Exception ex) { throw new SystemException(ex.toString()); } } /** * Resume the transaction context association of the calling thread * with the transaction represented by the supplied Transaction object. * When this method returns, the calling thread is associated with the * transaction context specified. */ public void resume(Transaction suspended) throws InvalidTransactionException, IllegalStateException, SystemException { // thread is already associated with a transaction? if (getTransaction() != null) throw new IllegalStateException(); // check for invalid Transaction object if (suspended == null) throw new InvalidTransactionException(); if ((suspended instanceof TransactionImpl) == false) { throw new InvalidTransactionException(); } Control control = ((TransactionImpl) suspended).getControl(); try { current.resume(control); } catch (InvalidControl ex) { //_logger.log(Level.FINE,"Invalid Control Exception in resume",ex); throw new InvalidTransactionException(); } catch (Exception ex) { throw new SystemException(ex.toString()); } } /** * Suspend the transaction currently associated with the calling * thread and return a Transaction object that represents the * transaction context being suspended. If the calling thread is * not associated with a transaction, the method returns a null * object reference. When this method returns, the calling thread * is associated with no transaction. */ public Transaction suspend() throws SystemException { try { Control control = current.suspend(); if (control == null) return null; return createTransactionImpl(control); } catch (Unavailable uex) { throw new SystemException(uex.toString()); } catch (Exception ex) { throw new SystemException(ex.toString()); } } /** TransactionState getOrCreateTransactionState(GlobalTID gtid, Transaction tran) throws SystemException { synchronized (transactionStates) { TransactionState result = (TransactionState) transactionStates.get(gtid); if (result == null) { result = new TransactionState(gtid); transactionStates.put(gtid, result); try { // remove Transaction State on transaction completion Synchronization sync = new SynchronizationListener(gtid, result); tran.registerSynchronization(sync); } catch (Exception ex) { _logger.log(Level.WARNING, "jts.unexpected_error_in_get_or_create_transaction_state",ex); throw new SystemException(); } } return result; } } TransactionState getTransactionState(GlobalTID gtid, Transaction tran) throws SystemException { synchronized (transactionStates) { return (TransactionState) transactionStates.get(gtid); } } **/ private Transaction createTransactionImpl(Control control) throws Unavailable, SystemException { GlobalTID gtid = null; if (Configuration.isLocalFactory()) { gtid = ((ControlImpl) control).getGlobalTID(); } else { ControlImpl cntrlImpl = ControlImpl.servant(JControlHelper.narrow(control)); gtid = cntrlImpl.getGlobalTID(); } // return new TransactionImpl(this, control, gtid); return new TransactionImpl(control, gtid); } /** * The application server passes in the list of XAResource objects * to be recovered. * * @param xaResourceList list of XAResource objects. */ public static void recover(Enumeration xaResourceList) { RecoveryManager.recoverXAResources(xaResourceList); } /** * Recreate a transaction based on the Xid. This call causes the calling * thread to be associated with the specified transaction. * * @param xid the Xid object representing a transaction. * @param timeout positive, non-zero value for transaction timeout. */ public static void recreate(Xid xid, long timeout) throws WorkException { // check if xid is valid if (xid == null || xid.getFormatId() == 0 || xid.getBranchQualifier() == null || xid.getGlobalTransactionId() == null) { WorkException workExc = new WorkCompletedException("Invalid Xid"); workExc.setErrorCode(WorkException.TX_RECREATE_FAILED); throw workExc; } // has TransactionService been initialized? if (!DefaultTransactionService.isActive()) { WorkException workExc = new WorkCompletedException("Transaction Manager unavailable"); workExc.setErrorCode(WorkException.TX_RECREATE_FAILED); throw workExc; } // recreate the transaction GlobalTID tid = new GlobalTID(xid); try { CurrentTransaction.recreate( tid, (int) ((timeout <= 0) ? 0 : timeout)); } catch (Throwable exc) { String errorCode = WorkException.TX_RECREATE_FAILED; if (exc instanceof INVALID_TRANSACTION && (((INVALID_TRANSACTION) exc).minor == MinorCode.TX_CONCURRENT_WORK_DISALLOWED)) { errorCode = WorkException.TX_CONCURRENT_WORK_DISALLOWED; } WorkException workExc = new WorkCompletedException(exc); workExc.setErrorCode(errorCode); throw workExc; } } /** * Release a transaction. This call causes the calling thread to be * dissociated from the specified transaction. * * @param xid the Xid object representing a transaction. */ public static void release(Xid xid) throws WorkException { GlobalTID tid = new GlobalTID(xid); try { CurrentTransaction.release(tid); } catch (Throwable exc) { String errorCode = WorkException.UNDEFINED; if (exc instanceof INTERNAL) { errorCode = WorkException.INTERNAL; } WorkException workExc = new WorkCompletedException(exc); workExc.setErrorCode(errorCode); throw workExc; } } /** * Provides a handle to a XATerminator instance. The * XATerminator instance could be used by a resource adapter * to flow-in transaction completion and crash recovery calls from an EIS. * * @return a XATerminator instance. */ public static jakarta.resource.spi.XATerminator getXATerminator() { return new XATerminatorImpl(); } //START IASRI 4706150 /** * used to set XAResource timeout */ public static void setXAResourceTimeOut(int value){ xaTimeOut = value; } public static int getXAResourceTimeOut(){ return xaTimeOut; } //END IASRI 4706150 /** class SynchronizationListener implements Synchronization { private GlobalTID gtid; private TransactionState tranState; SynchronizationListener(GlobalTID gtid, TransactionState tranState) { this.gtid = gtid; this.tranState = tranState; } public void afterCompletion(int status) { tranState.cleanupTransactionStateMapping(); } public void beforeCompletion() { try { tranState.beforeCompletion(); }catch(XAException xaex){ _logger.log(Level.WARNING,"jts.unexpected_xa_error_in_beforecompletion", new java.lang.Object[] {xaex.errorCode, xaex.getMessage()}); _logger.log(Level.WARNING,"",xaex); } catch (Exception ex) { _logger.log(Level.WARNING,"jts.unexpected_error_in_beforecompletion",ex); } } } **/ /** void cleanupTransactionState(GlobalTID gtid) { transactionStates.remove(gtid); } **/ }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy