/**
 * 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_ejb.container;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.List;

import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.xml.rpc.handler.MessageContext;

import org.objectweb.util.monolog.api.BasicLevel;

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

public abstract class JSessionContext extends JContext implements SessionContext, Serializable {

    protected JSessionSwitch bs = null;

    protected boolean ismarkedremoved;

    /**
     * Constructs a SessionContext
     * @param bf The Session Factory
     * @param eb The Session bean instance
     */
    public JSessionContext(JSessionFactory bf, SessionBean eb) {
        super(bf, eb);
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
    }

    // ------------------------------------------------------------------
    // 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 {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        if (ismarkedremoved || bs == null) {
            if (ismarkedremoved)
                TraceEjb.logger.log(BasicLevel.ERROR, "marked removed");
            else
                TraceEjb.logger.log(BasicLevel.ERROR, "no SessionSwitch");
            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.
     * @return 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 {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        if (ismarkedremoved || bs == null) {
            if (ismarkedremoved)
                TraceEjb.logger.log(BasicLevel.ERROR, "marked removed");
            else
                TraceEjb.logger.log(BasicLevel.ERROR, "no SessionSwitch");
            throw new IllegalStateException("getEJBLocalObject: EJB is removed");
        }
        EJBLocalObject ejblocalobject = bs.getLocal();
        if (ejblocalobject == null) throw new IllegalStateException("No Local Object for this bean");
        return ejblocalobject;
    }

    /**
     * Obtain a reference to the JAX-RPC MessageContext.
     * @return The MessageContext for this web service invocation.
     * @throws java.lang.IllegalStateException - the instance is in a state that
     *         does not allow access to this method.
     */
    public abstract MessageContext getMessageContext() throws java.lang.IllegalStateException;

    /**
     * Tests if the transaction has been marked for rollback only.
     * @return true if transaction will rollback
     */
    public boolean getRollbackOnly() throws IllegalStateException {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }

        if (getState() < 2) {
            throw new IllegalStateException("the instance is not allowed to call this method");
        }
        return super.getRollbackOnly();
    }

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

    /**
     * Reinit Context for reuse
     * @param bs The SessionSwitch to reuse.
     */
    public void initSessionContext(JSessionSwitch bs) {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        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 (myinstance == null) {
            TraceEjb.logger.log(BasicLevel.ERROR, "null!");
            throw new RemoteException("No instance available");
        }
        return (SessionBean) myinstance;
    }

    /**
     * @return True if bean instance is marked removed.
     */
    public boolean isMarkedRemoved() {
        return ismarkedremoved;
    }

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

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