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

import java.util.HashMap;
import java.util.Map;
import javax.naming.Context;
import javax.naming.LinkRef;
import javax.naming.NamingException;

import org.jfox.ejb.meta.EJBReferenceDescriptor;
import org.jfox.ejb.meta.EnvEntryDescriptor;
import org.jfox.ejb.meta.ResourceEnvRefDescriptor;
import org.jfox.ejb.meta.ResourceRefDescriptor;
import org.jfox.framework.deploy.DeployException;
import org.jfox.framework.deploy.Deployable;
import org.jfox.framework.deploy.Deployer;
import org.jfox.framework.extra.ActiveComponent;
import org.jfox.framework.logger.Logger;
import org.jfox.system.AbstractService;

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

public abstract class AbstractWebContainer extends AbstractService implements Deployer, ActiveComponent {

    protected Logger logger = Logger.getLogger(getClass().getName());

    /**
     * recorde the modules deployed
     */
    private Map modules = new HashMap();

    /**
     * get the WebModule by it's webContext
     *
     * @param webContext
     * @return
     */
    public WebModule getWebModule(String webContext) {
        return (WebModule) modules.get(webContext);
    }

    public final void deploy(Deployable webModule) throws DeployException {
        if(!this.isStarted()) {
            throw new DeployException("Web container not started, can not deploy Web Application");
        }
        if(!(webModule instanceof WebModule)) {
            throw new DeployException("can not deploy non-WebModule " + webModule.getClass().getName());
        }

        // do enterprise context binding for nested web module
        if(webModule instanceof NestedWebModule) {
            NestedWebModule nestedWebModule = (NestedWebModule) webModule;
            bindReference(nestedWebModule.getEnterpriseContext(), nestedWebModule.getWebDescriptor());

        }

        modules.put(((WebModule) webModule).getWebContext(), webModule);
        doDeploy((WebModule) webModule);
    }

    public final void undeploy(Deployable comp) {
        if(comp instanceof WebModule) {
            modules.remove(((WebModule) comp).getWebContext());
            doUndeploy((WebModule) comp);
        }
    }

    public final void undeploy(String webContext) {
        WebModule webModule = (WebModule) modules.get(webContext);
        undeploy(webModule);
    }

    public abstract String getConfiguration();

    public abstract String getRoot();

    protected abstract void doDeploy(WebModule webModule) throws DeployException;

    protected abstract void doUndeploy(WebModule webModule);

    private void bindReference(Context enc, WebDescriptor webDescriptor) {
        try {
            EnvEntryDescriptor[] entries = webDescriptor.getEnvEntries();
            for(int i = 0; i < entries.length; i++) {
                EnvEntryDescriptor env = (EnvEntryDescriptor) entries[i];
                String name = env.getName();
                Object value = env.getValueObject();
                enc.bind(name, value);
                logger.debug("bind env-entry, name: " + name);
            }

            EJBReferenceDescriptor[] ejbRefs = webDescriptor.getEjbReferences();
            for(int i = 0; i < ejbRefs.length; i++) {
                EJBReferenceDescriptor ejbRef = (EJBReferenceDescriptor) ejbRefs[i];
//        checkEjbReference(ejbRef);
                LinkRef linkRef = new LinkRef(ejbRef.getRefName());
                enc.bind(ejbRef.getRefName(), linkRef);
                logger.debug("bind ejf-ref, name: " + ejbRef.getRefName());
            }

            ResourceRefDescriptor[] resRefs = webDescriptor.getResourceReferences();
            for(int i = 0; i < resRefs.length; i++) {
                ResourceRefDescriptor resRef = (ResourceRefDescriptor) resRefs[i];
//        checkResourceRef(resRef);
                LinkRef linkRef = new LinkRef(resRef.getRefName());
                enc.bind(resRef.getRefName(), linkRef);
                logger.debug("bind resource-ref, name: " + resRef.getRefName());
            }

            ResourceEnvRefDescriptor[] resourceEnvRefs = webDescriptor.getResourceEnvReferences();
            for(int i = 0; i < resourceEnvRefs.length; i++) {
                ResourceEnvRefDescriptor resourceEnvRef = (ResourceEnvRefDescriptor) resourceEnvRefs[i];
//        checkResourceEnvRef(resourceEnvRef);
                LinkRef linkRef = new LinkRef(resourceEnvRef.getRefName());
                enc.bind(resourceEnvRef.getRefName(), linkRef);
                logger.debug("bind resource-env-ref, name: " + resourceEnvRef.getRefName());
            }

        }
        catch(NamingException e) {
            logger.warn("bind EnterpriseContext error", e);
        }
    }

    public static void main(String[] args) {

    }
}

