package com.github.xionghuicoder.clearpool.jta; import java.util.HashSet; import java.util.Set; 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; import com.github.xionghuicoder.clearpool.ConnectionPoolException; public class TransactionManagerImpl implements TransactionManager { private static final TransactionManagerImpl MANAGER = new TransactionManagerImpl(); private static final ThreadLocal<Transaction> TX_HOLDER = new ThreadLocal<Transaction>(); private final static boolean SINGLETON_MARK; static { SINGLETON_MARK = true; } private Set<Transaction> suspendTx; private int transactionTimeout; private TransactionManagerImpl() { if (SINGLETON_MARK) { throw new ConnectionPoolException("create TransactionManager illegal"); } } public static TransactionManagerImpl getManager() { return MANAGER; } @Override public void begin() throws NotSupportedException, SystemException { Transaction action = TX_HOLDER.get(); if (action != null) { throw new NotSupportedException("nested transaction is not supported"); } action = new TransactionImpl(this.transactionTimeout); TX_HOLDER.set(action); } @Override public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException { Transaction action = TX_HOLDER.get(); if (action == null) { throw new IllegalStateException("this is no transaction held"); } try { action.commit(); } finally { TX_HOLDER.set(null); } } @Override public int getStatus() throws SystemException { Transaction action = TX_HOLDER.get(); if (action == null) { return Status.STATUS_NO_TRANSACTION; } return action.getStatus(); } @Override public Transaction getTransaction() throws SystemException { Transaction tx = TX_HOLDER.get(); if (tx != null) { return new TransactionAdapter(tx); } return null; } @Override public void resume(Transaction transaction) throws InvalidTransactionException, SystemException { if (!(transaction instanceof TransactionAdapter) || this.suspendTx == null || !this.suspendTx.remove(transaction)) { throw new InvalidTransactionException("the transaction is invalid"); } Transaction tx = ((TransactionAdapter) transaction).getTx(); Transaction current = TX_HOLDER.get(); if (current != null) { throw new IllegalStateException("the thread already has a transaction"); } ((TransactionImpl) tx).resume(); TX_HOLDER.set(tx); } @Override public void rollback() throws SecurityException, SystemException { Transaction action = TX_HOLDER.get(); if (action == null) { throw new ConnectionPoolException("this is no transaction holding"); } try { action.rollback(); } finally { TX_HOLDER.set(null); } } @Override public void setRollbackOnly() throws SystemException { Transaction action = TX_HOLDER.get(); if (action == null) { throw new IllegalStateException("this is no transaction started"); } action.setRollbackOnly(); } @Override public void setTransactionTimeout(int i) throws SystemException { if (i < 0) { throw new SystemException("the parameter shouldn't be nagative"); } this.transactionTimeout = i; Transaction action = TX_HOLDER.get(); if (action != null && action instanceof TransactionImpl) { ((TransactionImpl) action).setTransactionTimeout(i); } } @Override public Transaction suspend() throws SystemException { Transaction tx = TX_HOLDER.get(); if (tx != null) { if (this.suspendTx == null) { this.suspendTx = new HashSet<Transaction>(); } ((TransactionImpl) tx).suspend(); TransactionAdapter adapter = new TransactionAdapter(tx); this.suspendTx.add(adapter); TX_HOLDER.set(null); return adapter; } return null; } }