/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@ow2.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.ow2.jonas.lib.ejb21;

import java.rmi.RemoteException;

import javax.transaction.Transaction;

import org.ow2.jonas.lib.timer.TimerEvent;
import org.ow2.jonas.lib.timer.TimerEventListener;
import org.ow2.jonas.lib.timer.TimerManager;


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

/**
 * JSessionSwitch holds all the code that is common to EJBObject and
 * EJBLocalObject for session beans. It mainly keep a reference on the
 * SessionContext and is used to manage the timeout for the session. This class
 * has 2 subclasses, depending if session is stateless or stateful.
 * @author Philippe Durieux
 */
public abstract class JSessionSwitch implements TimerEventListener {

    protected JSessionFactory bf;

    protected JSessionLocal mylocal = null;

    protected JSessionRemote myremote = null;

    protected TimerEvent mytimer = null;

    /**
     * constructor. a new object is build when the pool managed by
     * JSessionFactory becomes empty.
     * @param bf The Bean Factory
     */
    public JSessionSwitch(JSessionFactory bf) throws RemoteException {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        this.bf = bf;

        // Create EJBObject if bean has a Remote Interface
        if (bf.getHome() != null) {
            myremote = ((JSessionHome) bf.getHome()).createRemoteObject();
            myremote.setSessionSwitch(this);
        }

        // Create EJBLocalObject if bean has a Local Interface
        if (bf.getLocalHome() != null) {
            mylocal = ((JSessionLocalHome) bf.getLocalHome()).createLocalObject();
            mylocal.setSessionSwitch(this);
        }
    }

    /**
     * @return the underlaying EJBLocalObject
     */
    public JSessionLocal getLocal() {
        return mylocal;
    }

    /**
     * @return the underlaying EJBObject
     */
    public JSessionRemote getRemote() {
        return myremote;
    }

    /**
     * @return the BeanFactory
     */
    public JSessionFactory getBeanFactory() {
        return bf;
    }

    /**
     * Start a timer for this Session.
     * @param timeout nb of milliseconds max this Session should live.
     */
    public void startTimer(int timeout) {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        mytimer = TimerManager.getInstance().addTimerMs(this, timeout, null, false);
    }

    /**
     * Stop the Timer associated to the Session
     */
    public void stopTimer() {
        if (TraceEjb.isDebugIc()) {
            TraceEjb.interp.log(BasicLevel.DEBUG, "");
        }
        if (mytimer != null) {
            mytimer.unset();
            mytimer = null;
        }
    }

    public abstract JSessionContext getICtx(Transaction tx) throws RemoteException;
    public abstract void releaseICtx(RequestCtx req, boolean discard);
    public abstract void setMustCommit(boolean mc);
    public abstract void saveBeanTx();

    public abstract void pushConnectionList();
    public abstract void popConnectionList();
    public abstract void enlistConnections(Transaction tx);
    public abstract void delistConnections(Transaction tx);
    public abstract void noLongerUsed();
}

