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

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

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

public class ProxyObjectFactory extends SimpleObjectFactory {

    protected Class invokerClass = null;

    /**
     * 使用 PoolableObjectInvocationHandler 作为默认的 InvocationHandler
     *
     * @param classType PoolableObject 的 Class
     * @throws Exception
     */
    public ProxyObjectFactory(Class classType) throws Exception {
        super(classType);
        this.invokerClass = PoolableObjectInvocationHandler.class;
    }

    public ProxyObjectFactory(Class classType, Class invokerClass) throws Exception {
        super(classType);
        if(PoolableObjectInvocationHandler.class.isAssignableFrom(invokerClass)) {
            this.invokerClass = invokerClass;
        }
        else {
            throw new Exception(invokerClass.getName() + " not implements " + PoolableObjectInvocationHandler.class.getName());
        }
    }

    public boolean validateObject(PoolableObject object) {
        if(Proxy.isProxyClass(object.getClass())) {
            object = ((PoolableObjectInvocationHandler) Proxy.getInvocationHandler(object)).getPoolableObject();
        }
        return super.validateObject(object);
    }

    public PoolableObject makeObject() throws Exception {
        // 生成 PoolableObject
        PoolableObject obj = (PoolableObject) classType.newInstance();
        // 生成 PoolableObjectInvocationHandler
        InvocationHandler handler = (InvocationHandler) invokerClass.getConstructor(new Class[]{PoolableObject.class}).newInstance(new Object[]{obj});

        return (PoolableObject) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                obj.getClass().getInterfaces(),
                handler);

    }

    public void destroyObject(PoolableObject object) throws Exception {
        if(Proxy.isProxyClass(object.getClass())) {
            object = ((PoolableObjectInvocationHandler) Proxy.getInvocationHandler(object)).getPoolableObject();
        }
        object.passivate();
        super.destroyObject(object);
    }

}
