/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.com
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

package org.jfox.tm;

import java.util.TimerTask;
import java.util.Timer;

import javax.transaction.*;
import javax.transaction.xa.XAResource;

/**
 * 封装一个真正的事务对象,做一些辅助操作
 *
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

class TxWrapper implements Transaction {
  /**
   * ?¨?±?÷???????????±???±?ò?÷?? timout ·?·¨
   */
  private static Timer timer = new Timer(true);
  private static int timeout = 10 * 24 * 60 * 60 * 1000; // 10 days

  private TransactionImpl transaction = null;

  TxWrapper() {

  }

  /**
   * create a transaction & start a timeout
   * ??????????????????????
   */
  void begin() throws SystemException,NotSupportedException {
    transaction = new TransactionImpl();
    timer.schedule((TimerTask)transaction,timeout);
  }

  void setTimeout(int millisecond){
    timeout = millisecond;
  }


  /**
   * ·??? transaction.commit ???ó ?????? timeout ?à??,?±?°????
   * @throws RollbackException
   * @throws HeuristicMixedException
   * @throws HeuristicRollbackException
   * @throws SecurityException
   * @throws SystemException
   */
  public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    try {
      transaction.commit();
    }
    finally { // ?????±?°????????????????
      ((TimerTask)transaction).cancel();
    }
  }

  public boolean delistResource(XAResource xaResource, int flag) throws IllegalStateException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    return transaction.delistResource(xaResource,flag);
  }

  public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    return transaction.enlistResource(xaResource);
  }

  public int getStatus() throws SystemException {
    if(transaction == null) {
      return Status.STATUS_NO_TRANSACTION;
    }
    else {
      return transaction.getStatus();
    }
  }

  public void registerSynchronization(Synchronization synchronization) throws RollbackException, IllegalStateException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    if(synchronization == null) return;
    transaction.registerSynchronization(synchronization);
  }

  /**
   * ·??? transaction.rollback ???ó???????? timeout ?à?????????±?°????
   * @throws IllegalStateException
   * @throws SystemException
   */
  public void rollback() throws IllegalStateException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    try {
      transaction.rollback();
    }
    finally {
      ((TimerTask)transaction).cancel();
    }
  }

  public void setRollbackOnly() throws IllegalStateException, SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    transaction.setRollbackOnly();
  }

  public String toString() {
    if(transaction == null) {
      return "No Transaction.";
    }
    else {
      return transaction.toString();
    }
  }

  Transaction suspend() throws SystemException {
    if(transaction == null){
      throw new IllegalStateException("no transaction associated with current thread.");
    }
    Transaction suspendedTransaction = transaction;
    transaction.suspend();
    transaction = null;
    return suspendedTransaction;
  }

  void resume(Transaction trans) throws InvalidTransactionException, IllegalStateException, SystemException {
    if (trans == null || !(trans instanceof TransactionImpl)){
      throw new InvalidTransactionException(trans + " is not a instance of " + TransactionImpl.class.getName());
    }
    transaction = (TransactionImpl)trans;
    try {
      transaction.resume();
    }
    catch(RollbackException e){
      throw new IllegalStateException("transaction already rolled back, " + e.getMessage());
    }
  }
}