/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.tm;

import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class TxManager implements TransactionManager {

    private static ThreadLocal threadTx = new ThreadLocal() {
        protected Object initialValue() {
            return new TxWrapper();
        }

        public Object get() {
            Object obj = super.get();
            if(obj == null) {
                obj = initialValue();
                super.set(obj);
            }
            return obj;
        }
    };

    // singleton instance
    private static TxManager me = new TxManager();

    private volatile int numTrasactions = 0;
    private volatile int numSuspendedTransactions = 0;

    public static TxManager getInstance() {
        return me;
    }

    public void begin() throws NotSupportedException, SystemException {
        numTrasactions++;
        ((TxWrapper) threadTx.get()).begin();
    }

    public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
        numTrasactions--;
        try {
            ((TxWrapper) threadTx.get()).commit();
        }
        finally {
            threadTx.set(null);
        }
    }

    public void rollback() throws IllegalStateException, SecurityException, SystemException {
        numTrasactions--;
        try {
            ((TxWrapper) threadTx.get()).rollback();
        }
        finally {
            threadTx.set(null);
        }
    }

    public int getStatus() throws SystemException {
        Transaction tx = (TxWrapper) threadTx.get();
        if(tx==null) {
            return Status.STATUS_NO_TRANSACTION;
        }
        else {
            return tx.getStatus();
        }
    }

    public Transaction getTransaction() throws SystemException {
        return (TxWrapper) threadTx.get();
    }

    public void setRollbackOnly() throws IllegalStateException, SystemException {
        ((TxWrapper) threadTx.get()).setRollbackOnly();
    }

    public void setTransactionTimeout(int seconds) throws SystemException {
        ((TxWrapper) threadTx.get()).setTimeout(seconds * 1000);
    }

    public Transaction suspend() throws SystemException {
        Transaction trans = ((TxWrapper) threadTx.get()).suspend();
        numSuspendedTransactions++;
        return trans;
    }

    public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException, SystemException {
        if(transaction == null || !(transaction instanceof TransactionImpl)) {
            throw new InvalidTransactionException(transaction + " is not a instance of " + TransactionImpl.class.getName());
        }
        ((TxWrapper) threadTx.get()).resume(transaction);
        numSuspendedTransactions--;
    }

    int getNumTransactions() {
        return numTrasactions;
    }

    int getNumSuspendedTransactions() {
        return numSuspendedTransactions;
    }

    public static void main(String[] args) {

    }
}