/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas_tm;

import org.omg.CosTransactions._ResourceImplBase;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.Status;
import org.omg.CosTransactions.Vote;
import org.omg.CosTransactions.otid_t;
import org.omg.CosTransactions.NotPrepared;
import org.omg.CosTransactions.HeuristicRollback;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicCommit;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.InvalidControl;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.UNKNOWN;
import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
import java.rmi.RemoteException;


/**
 * This class wraps a JOnAS ControlImpl as a CORBA Resource, allowing it to be registered
 * by a CORBA supcoord.
 * @author Philippe Durieux
 */
public class ControlResourceImpl extends _ResourceImplBase {

    /**
     * the wrapped ControlImpl
     * @serial
     */
    private ControlImpl myctrl;

    /**
     * is true only if prepared, but not yet committed or rolled back.
     * @serial
     */
    private boolean prepared = false;


    // ------------------------------------------------------------------
    // Constructors
    // ------------------------------------------------------------------

    /**
     * constructor used by ControlImpl when registered in its supcoord.
     */
    ControlResourceImpl(ControlImpl ctrl) {
	TraceTm.debugTm("ControlResourceImpl.ControlResourceImpl(ControlImpl)");
	this.myctrl = ctrl;
    }

    // ------------------------------------------------------------------
    // Resource interface
    // ------------------------------------------------------------------

    /** 
     * phase 1 of the 2PC.
     *
     * @return int vote commit, rollback, or readonly.
     */
    public Vote prepare() throws HeuristicMixed, HeuristicHazard  {
	TraceTm.debugTm("ControlResourceImpl.prepare()");
	try {
	    Vote ret;
	    switch (myctrl.prepare()) {
	    case org.objectweb.jonas_tm.Resource.VOTE_COMMIT:
		ret = Vote.VoteCommit;
	    case org.objectweb.jonas_tm.Resource.VOTE_ROLLBACK:
		ret = Vote.VoteRollback;
	    case org.objectweb.jonas_tm.Resource.VOTE_READONLY:
		ret = Vote.VoteReadOnly;
	    default:
		//unexpected
		TraceTm.error("ControlResourceImpl: unknown Vote value on prepare");
		ret = Vote.VoteReadOnly;
	    }
	    prepared = true;
	    return ret;
	} catch (org.objectweb.jonas_tm.HeuristicMixed e) {
	    throw new HeuristicMixed();
	} catch (RemoteException e) {
	    throw new UNKNOWN("JOnAS TM RemoteException: " + e.getMessage());
	}
    }

    /** 
     * rollback transaction
     */
    public void rollback() throws HeuristicMixed, HeuristicHazard, HeuristicCommit {
	TraceTm.debugTm("ControlResourceImpl.rollback()");
	try {
	    myctrl.rollback();
	    prepared = false;
	} catch (org.objectweb.jonas_tm.HeuristicMixed e) {
	    throw new HeuristicMixed();
	} catch (RemoteException e) {
	    throw new UNKNOWN("JOnAS TM RemoteException: " + e.getMessage());
	}
    }

    /** 
     * phase 2 of the 2PC.
     */
    public void commit() throws NotPrepared,HeuristicRollback,HeuristicMixed,HeuristicHazard {
	TraceTm.debugTm("ControlResourceImpl.commit()");
	try {
	    if (!prepared)
		throw new NotPrepared();
	    myctrl.commit();
	    prepared = false;
	} catch (org.objectweb.jonas_tm.HeuristicMixed e) {
	    throw new HeuristicMixed();
	} catch (org.objectweb.jonas_tm.HeuristicHazard e) {
	    throw new HeuristicHazard();
	} catch (javax.transaction.TransactionRolledbackException e) {
	    throw new TRANSACTION_ROLLEDBACK();
	} catch (RemoteException e) {
	    throw new UNKNOWN("JOnAS TM RemoteException: " + e.getMessage());
	}
    }


    /** 
     * commit 1 phase.
     */
    public void commit_one_phase() throws HeuristicHazard {
	TraceTm.debugTm("ControlResourceImpl.commit_one_phase()");
	try {
	    myctrl.commit_one_phase();
	//} catch (org.objectweb.jonas_tm.HeuristicMixed e) {
	//    throw new HeuristicMixed();
	} catch (org.objectweb.jonas_tm.HeuristicHazard e) {
	    throw new HeuristicHazard();
	} catch (javax.transaction.TransactionRolledbackException e) {
	    throw new TRANSACTION_ROLLEDBACK();
	} catch (RemoteException e) {
	    throw new UNKNOWN("JOnAS TM RemoteException: " + e.getMessage());
	}
    }

    /**
     * forget heuristics about this transaction.
     */
    public void forget() {
	TraceTm.debugTm("ControlResourceImpl.forget()");
	try {
	    myctrl.forget();
	} catch (RemoteException e) {
	    throw new UNKNOWN("JOnAS TM RemoteException: " + e.getMessage());
	}
    }

}
