/* 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.lang.reflect.Proxy;
import java.rmi.RemoteException;
import javax.ejb.EJBObject;
import javax.ejb.EnterpriseBean;
import javax.ejb.Handle;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;

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

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class StatefulSessionBucket extends SessionBucket {

    private StatefulSessionObjectPool instancePool = null;

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

    /**
     * 来自 EJBHome 的方法
     *
     * @param invocation
     * @return
     * @throws Exception
     */
    public Object invokeHome(Invocation invocation) throws Exception {
        logger.debug("invokeHome " + invocation.getMethod().getName());
        //TODO: user IOC
        return ((HandlerChain) Registry.getInstance().getComponentInstance(ComponentName.parseString(StatefulHandlerChain.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(StatefulHandlerChain.class.getName() + "@default"))).invokeBean(this, invocation);
    }

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

    public void remove(Handle handle) throws RemoteException, RemoveException {
        EJBObject ejbObject = handle.getEJBObject();
        // Handle 实际上是一个代理对象，保存了 ObjectId 在里面
        EJBObjectId objectId = ((ContainerInvokerSupport) Proxy.getInvocationHandler(ejbObject)).getObjectId();
        try {
            EJBPoolableObject pobj = (EJBPoolableObject) instancePool.retrieveObject(objectId);
            remove(pobj.getBeanInstance());
        }
        catch(Exception e) {
            throw new RemoveException(e.getMessage());
        }
    }

    public boolean isIdentical(EJBObjectId thisObjectId, EJBObjectId thatObjectId) throws RemoteException {
        return thisObjectId.equals(thatObjectId);
    }

    public EJBPoolableObject retrieveBean(Object key) {
        try {
            return (EJBPoolableObject) instancePool.retrieveObject(key);
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

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

    public EJBObjectId createBean(Invocation invocation) throws Exception {
        EJBObjectId beanObjectId = nextObjectId();
        EJBPoolableObject pobj = (EJBPoolableObject) instancePool.createObject();
        SessionBean bean = (SessionBean) pobj.getBeanInstance();
        setSessionContext(bean, new SessionContextImpl(beanObjectId, bucketMeta));
        ejbCreate(bean, invocation.getMethod().getName(), invocation.getArgs());
        instancePool.restoreObject(beanObjectId, pobj);
        return beanObjectId;
    }

    protected void doInit() throws Exception {
        instancePool = new StatefulSessionObjectPool(this, new EJBObjectFactory(EJBPoolableObject.class, bucketMeta.getBeanClass()));
        instancePool.init();
        super.doInit();
    }

    protected void doDestroy() throws Exception {
        super.doDestroy();
        // 销毁 instancePool 的时候，会序列化所有的实例，并且不再受 LifeCycleManager 的监控
        instancePool.destroy();
    }

    public static void main(String[] args) {

    }
}