/*
 * 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
 *
 * Initial developer(s): Philippe Coq, Philippe Durieux
 * Contributor(s): ______________________________________.
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas_ejb.container;

import java.io.Serializable;
import java.lang.IllegalStateException;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import javax.ejb.EJBException;
import javax.ejb.RemoveException;
import javax.naming.Context;
import javax.ejb.SessionContext;
import javax.transaction.Transaction;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;

/**
 * This class implements javax.ejb.SessionContext interface.
 * it should be implemented by JStatefulContext and JStatelessContext
 * depending if the beans is stateful or stateless.
 */

public abstract class JSessionContext extends JContext implements SessionContext, Serializable {

    protected JSessionSwitch bs = null;
    protected boolean ismarkedremoved;
    
    // ------------------------------------------------------------------
    // constructors
    // ------------------------------------------------------------------

    /**
     * Constructs a SessionContext
     */
    public JSessionContext(JSessionFactory bf, SessionBean eb) {
	super(bf, eb);
	TraceEjb.debugIc("JSessionContext constructor");
	// session beans may have home or localHome
	this.home = bf.getHome();
	this.localhome = bf.getLocalHome();
    }

    // ------------------------------------------------------------------
    // SessionContext implementation
    // ------------------------------------------------------------------

    /**
     * Obtains a reference to the EJB object that is currently associated with the instance. 
     * @return The EJB object currently associated with the instance. 
     * @exception IllegalStateException: Thrown if the instance invokes this 
     *            method while the instance is in a state that does not allow the 
     *            instance to invoke this method.
     */
    public EJBObject getEJBObject() throws IllegalStateException {
	TraceEjb.debugIc("JSessionContext getEJBObject");
	if (ismarkedremoved || bs == null) {
	    if (ismarkedremoved)
		TraceEjb.error("EJB is marked removed");
	    else
		TraceEjb.error("EJB has no EntitySwitch");
	    throw new IllegalStateException("getEJBObject: EJB is removed");
	}
	EJBObject ejbobject = bs.getRemote();
	if (ejbobject == null) {
	    throw new IllegalStateException("No Remote Interface for this bean");
	}
	return ejbobject;
    }

    /**
     * Obtain a reference to the EJB local object that is 
     * currently associated with the instance.
     * @returns The EJB local object currently associated with the instance.
     * @throws  java.lang.IllegalStateException - if the instance invokes this 
     * method while the instance is in a state that does not allow the instance to 
     * invoke this method, or if the instance does not have a local interface.
     */
    public EJBLocalObject getEJBLocalObject() throws IllegalStateException {
	TraceEjb.debugIc("JSessionContext getEJBLocalObject");
	if (ismarkedremoved || bs == null) {
	    if (ismarkedremoved)
		TraceEjb.error("EJB is marked removed");
	    else
		TraceEjb.error("EJB has no EntitySwitch");
	    throw new IllegalStateException("getEJBLocalObject: EJB is removed");
	}
	EJBLocalObject ejblocalobject = bs.getLocal();
	if (ejblocalobject == null)
	    throw new IllegalStateException("No Local Interface for this bean");
	return ejblocalobject;
    }

    // -------------------------------------------------------------------
    // Other public methods
    // -------------------------------------------------------------------

    /**
     * Reinit Context for reuse
     */
    public void initSessionContext(JSessionSwitch bs) {
	TraceEjb.debugIc("JSessionContext initSessionContext");
	this.bs = bs;
	ismarkedremoved = false;
    }

   /**
     * Returns the bean instance of this context
     * Used in the generated classes to retrieve the instance
     * @return the bean instance
     * @throws RemoteException if no instance
     */
    // RemoteException is throwned to allow simpler genic templates
    public SessionBean getInstance() throws RemoteException {
	if (instance == null) {
	    TraceEjb.error("JSessionContext.getInstance: null!");
	    throw new RemoteException("No instance available");
	}
	return (SessionBean) instance;
    }

    public boolean isMarkedRemoved() {
	return ismarkedremoved;
    }

    // ------------------------------------------------------------------
    // Other methods
    // ------------------------------------------------------------------

    abstract public void setRemoved() throws RemoteException, RemoveException;
}
