/*
 * 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.jtests.beans.transacted;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.RemoveException;
import javax.ejb.SessionSynchronization;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

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

/*
 * Stateful session bean
 */
public class SimpleSY extends SimpleSL implements SessionSynchronization {

    private boolean rollbackonly = false;
    private Context ictx = null;
    private SimpleELocalHome lhome = null;
    

    // ------------------------------------------------------------------
    // SynchroSimple implementation
    // ------------------------------------------------------------------

    /**
     * Ask bean to set transaction rollback only
     */
    public void setRollbackOnly() {
        logger.log(BasicLevel.DEBUG, "");
        rollbackonly = true;
    }

    /**
     * REQUIRED -> should return true.
     */
    public boolean call_requires_new_local() {
        logger.log(BasicLevel.DEBUG, "");
        SimpleLocal loc = getLocalBean();
        boolean tx = loc.opwith_requires_new();
        if (!tx) {
            logger.log(BasicLevel.ERROR, "opwith_requires_new was outside tx");
            return false;	// error
        }
        try {
            loc.remove();		// cleaning
        } catch (RemoveException e) {
            logger.log(BasicLevel.ERROR, "cannot remove local bean");
        }
        return isAssociated();
    }

    /**
     * REQUIRED -> should return true.
     */
    public boolean call_notsupported_local() {
        logger.log(BasicLevel.DEBUG, "");
        SimpleLocal loc = getLocalBean();
        boolean tx = loc.opwith_notsupported();
        if (tx) {
            logger.log(BasicLevel.ERROR, "opwith_notsupported was in tx");
            return false;	// error
        }
        try {
            loc.remove();		// cleaning
        } catch (RemoveException e) {
            logger.log(BasicLevel.ERROR, "cannot remove local bean");
        }
        return isAssociated();
    }

    // ------------------------------------------------------------------
    // SessionSynchronization implementation
    // ------------------------------------------------------------------

    /** 
     * The afterBegin method notifies a session Bean instance that a new 
     * transaction has started, and that the subsequent business methods on
     * the instance will be invoked in the context of the transaction. 
     * This method executes in the proper transaction context. 
     *
     * @throws EJBException Thrown if the instance could not perform
     * the function requested by the container because of a system-level error.
     */
    public void afterBegin() {
        logger.log(BasicLevel.DEBUG, "");
    }


    /** 
     * The beforeCompletion method notifies a session Bean instance that a
     * transaction is about to be committed. 
     * This method executes in the proper transaction context. 
     * Note: The instance may still cause the container to rollback the transaction
     * by invoking the setRollbackOnly() method on the instance context, or by throwing
     * an exception. 
     *   
     * @throws EJBException Thrown by the method to indicate a failure caused by a
     * system-level error.
     */
    public void beforeCompletion() {
        logger.log(BasicLevel.DEBUG, "");
        if (rollbackonly) {
            sessionContext.setRollbackOnly();
        }
    }


    /** 
     * The afterCompletion method notifies a session Bean instance that a
     * transaction commit protocol has completed, and tells the instance whether
     * the transaction has been committed or rolled back. 
     * This method executes with no transaction context. 
     *
     * @param : committed - True if the transaction has been committed, false if
     * it has been rolled back.
     * 
     * @throws EJBException Thrown by the method to indicate a failure caused by a
     * system-level error.
     */
    public void afterCompletion(boolean committed) {
        logger.log(BasicLevel.DEBUG, "");
    }

    // ------------------------------------------------------------------
    // private methods
    // ------------------------------------------------------------------

    /**
     * init non persistent bean data.
     * This should be called when instance is created or activated.
     */
    private void stateUpdate() throws NamingException {
        // Get initial Context
        if (ictx == null) {
            ictx = new InitialContext();
        }
        // lookup paperhome in JNDI
        if (lhome == null) {
            lhome = (SimpleELocalHome) ictx.lookup("java:comp/env/ejb/SimpleEC");
        }
    }

    /**
     * get local bean
     */
    private SimpleLocal getLocalBean() {
        SimpleLocal ret = null;
        try {
            stateUpdate();
        } catch (NamingException e) {
            logger.log(BasicLevel.ERROR, "getLocalBean raised exception "+e);
            throw new EJBException("Error in getLocalBean:"+e);
        }
        try {
            ret = lhome.create(123);
        } catch (CreateException e) {
            logger.log(BasicLevel.ERROR, "Cannot create local entity bean "+e);
            throw new EJBException("Cannot create local entity bean:"+e);
        }
        return ret;
    }
}
