/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.ejb;

import java.rmi.RemoteException;
import javax.ejb.EnterpriseBean;
import javax.ejb.Handle;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

import org.jfox.ejb.handler.HandlerChain;
import org.jfox.framework.ComponentName;
import org.jfox.framework.Registry;

/**
 * 执行在 EJBObject EJBHome 中定义的方法
 *
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class StatelessSessionBucket extends SessionBucket {

    private StatelessSessionObjectPool instancePool = null;
    /**
     * StatlessSessionBean 每次返回同样的ObjectId
     */
    private EJBObjectId beanObjectId = null;
    private SessionContext ejbConext = null;

    public StatelessSessionBucket(BucketMetaData meta) {
        super(meta);
    }

    /**
     * 来自 EJBHome 的方法
     *
     * @param invocation
     * @return
     * @throws Exception
     */
    public Object invokeHome(Invocation invocation) throws Exception {
        logger.debug("invokeHome " + invocation.getMethod().getName());
        return ((HandlerChain) Registry.getInstance().getComponentInstance(ComponentName.parseString(StatelessHandlerChain.class.getName() + "@default"))).invokeHome(this, invocation);
    }

    /**
     * 执行 Bean 的方法
     *
     * @param invocation
     * @return
     * @throws Exception
     */
    public Object invokeBean(Invocation invocation) throws Exception {
        logger.debug("invokeBean " + invocation.getMethod().getName());
        return ((HandlerChain) Registry.getInstance().getComponentInstance(ComponentName.parseString(StatelessHandlerChain.class.getName() + "@default"))).invokeBean(this, invocation);

    }

    // 对于 StatelessSessionBean，这个方法不执行任何操作
    public void remove(Handle handle) throws RemoteException, RemoveException {
        try {
            EJBPoolableObject pobj = (EJBPoolableObject) instancePool.retrieveObject();
            remove(pobj.getBeanInstance());
        }
        catch(Exception e) {
            throw new RemoveException(e.getMessage());
        }
    }

    public void remove(EnterpriseBean bean) throws RemoteException, RemoveException {
        ejbRemove((SessionBean) bean);
    }

    // 对于 StatelessSessionBean, 总是返回 true
    public boolean isIdentical(EJBObjectId thisObjectId, EJBObjectId thatObjectId) throws RemoteException {
        return true;
    }

    public EJBPoolableObject retrieveBean(Object key) throws Exception {
        StatelessEJBPoolableObject pobj = (StatelessEJBPoolableObject) instancePool.retrieveObject();
        if(!pobj.isEjbCreated()) { // 新生的对象，要调用 setSessionContext, ejbCreate
            SessionBean bean = (SessionBean) pobj.getBeanInstance();
            setSessionContext(bean, ejbConext);
            ejbCreate(bean, "create", null);
            pobj.ejbCreated();
        }
        return pobj;
    }

    public void restoreBean(Object key, EJBPoolableObject pobj) {
        instancePool.restoreObject(pobj);
    }

    public EJBObjectId createBean(Invocation invocation) throws Exception {
        if(beanObjectId == null) { // 第一次调用 create ，生成 beanObjectId,ejbContext
            beanObjectId = nextObjectId();
            ejbConext = new SessionContextImpl(beanObjectId, bucketMeta);
        }
        StatelessEJBPoolableObject pobj = (StatelessEJBPoolableObject) instancePool.createObject();
        if(!pobj.isEjbCreated()) { // 新生的对象，要调用 setSessionContext, ejbCreate
            SessionBean bean = (SessionBean) pobj.getBeanInstance();
            setSessionContext(bean, ejbConext);
            // stateless session bean 只有一个没有参数的 ejbCreate 方法
            ejbCreate(bean, "create", null);
            pobj.ejbCreated();
        }
        this.restoreBean(invocation.getObjectId(), pobj);
        return beanObjectId;
    }

    protected void doInit() throws Exception {
        instancePool = new StatelessSessionObjectPool(new StatelessEJBObjectFactory(StatelessEJBPoolableObject.class, bucketMeta.getBeanClass(), this));
        instancePool.init();
        super.doInit();
    }

    protected void doDestroy() throws Exception {
        super.doDestroy();
        instancePool.destroy();
    }
}