/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2008 Bull S.A.S.
 * Contact: jonas-team@ow2.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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id: WSDeployment.java 20050 2010-07-02 13:40:21Z benoitf $
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.web.tomcat7.ws;

import org.apache.catalina.Context;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.startup.ContextConfig;
import org.ow2.jonas.web.tomcat7.JOnASStandardContext;
import org.ow2.jonas.web.tomcat7.Tomcat7Service;
import org.ow2.jonas.ws.jaxws.IWebServiceDeploymentManager;
import org.ow2.jonas.ws.jaxws.IWebServiceEndpoint;
import org.ow2.jonas.ws.jaxws.WSException;
import org.ow2.jonas.ws.jaxws.PortMetaData;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

import java.io.File;

/**
 * @author Guillaume Sauthier
 */
public class WSDeployment implements IWebServiceDeploymentManager {

    /**
     * Logger.
     */
    private static Log logger = LogFactory.getLog(WSDeployment.class);

    /**
     * Our support: Tomcat.
     */
    private Tomcat7Service tomcatService;

    /**
     * The work directory of tomcat.
     */
    private String workDirectory;

    /**
     * Construct a new {@link WSDeployment} manager based on Tomcat.
     * @param tomcatService Tomcat instance
     */
    public WSDeployment(final Tomcat7Service tomcatService) {
        this.tomcatService = tomcatService;
    }

    /**
     * @param workDirectory the workDirectory to set
     */
    public void setWorkDirectory(final String workDirectory) {
        this.workDirectory = workDirectory;
    }

    /**
     * @see org.ow2.jonas.ws.jaxws.IWebServiceDeploymentManager#registerWSEndpoint(org.ow2.jonas.ws.jaxws.IWebServiceEndpoint)
     */
    public void registerWSEndpoint(final IWebServiceEndpoint endpoint) throws WSException {

        switch (endpoint.getType()) {
        case POJO:
            throw new IllegalStateException("Not implemented yet");
        case EJB:
            registerEJBEndpoint(endpoint);
        }

    }

    /**
     * Register a new EJB based WS endpoint.
     * @param endpoint the EJB based WS endpoint to deploy
     * @throws WSException
     */
    private void registerEJBEndpoint(final IWebServiceEndpoint endpoint) throws WSException {
        // Ensure web container is started
        tomcatService.startInternalWebContainer();

        PortMetaData pmd = endpoint.getPortMetaData();
        // Find the host
        Host host = tomcatService.findHost(pmd.getHostname());

        // TODO Configure security
        // TODO, if there are multiple EJB exposed as WS, we need to reuse the Context

        // Configure Wrapper
        WebServiceEndpointStandardWrapper wrapper = null;
        wrapper = new WebServiceEndpointStandardWrapper(endpoint);

        wrapper.setParentClassLoader(this.getClass().getClassLoader());

        logger.debug("Added Wrapper/Servlet: {0}", wrapper);

        // Create the context
        JOnASStandardContext context = new JOnASStandardContext(false, true, false);

        // Configure the context
        context.setPath(URLUtils.getContextRoot(pmd));

        // Add the Servlet
        context.addChild(wrapper);

        String pattern = endpoint.getPortMetaData().getUrlPattern();
        context.addServletMapping(pattern, wrapper.getServletName());

        context.setTomcatService(tomcatService);

        // I need here a valid File in the work directory of JOnAS
        File docBase = new File(workDirectory,
                                endpoint.getPortMetaData().getContextRoot());
        if (!docBase.exists()) {
            docBase.mkdirs();
        } // TODO remove the directory ?
        context.setDocBase(docBase.getPath());

        // This listener is here to tell tomcat that the Context is
        // OK for startup, even if no ContextConfig was set.
        context.addLifecycleListener(new LifecycleListener() {

            public void lifecycleEvent(LifecycleEvent lifecycleEvent) {

                if (Lifecycle.START_EVENT.equals(lifecycleEvent.getType())) {
                    // The context is configured
                    Context ctx = (Context) lifecycleEvent.getLifecycle();
                    ctx.setConfigured(true);
                } else if (Lifecycle.AFTER_START_EVENT.equals(lifecycleEvent.getType())) {
                    // Cleanup registered application listeners (such as JSF, ...)
                    Context ctx = (Context) lifecycleEvent.getLifecycle();
                    String[] listeners = ctx.findApplicationListeners();
                    for (String listener : listeners) {
                        ctx.removeApplicationListener(listener);
                    }
                }
            }
        });

        // Add the Context
        // Will be automatically started
        host.addChild(context);

        // Compute a default URL that can be used to access the endpoint locally
        String url = URLUtils.getEndpointURL(pmd, host);
        endpoint.getPortMetaData().setEndpointURL(url);

        logger.debug("Added Context: {0}", context);
    }

    /* (non-Javadoc)
     * @see org.ow2.jonas.ws.jaxws.IWebServiceDeploymentManager#unregisterWSEndpoint(org.ow2.jonas.ws.jaxws.IWebServiceEndpoint)
     */
    public void unregisterWSEndpoint(final IWebServiceEndpoint endpoint) throws WSException {
        // Ensure web container is started
        tomcatService.startInternalWebContainer();

        switch (endpoint.getType()) {
        case POJO:
            throw new IllegalStateException("Not implemented yet");
        case EJB:
            unregisterEJBEndpoint(endpoint);
        }
    }


    private void unregisterEJBEndpoint(final IWebServiceEndpoint endpoint) {

        String contextName = URLUtils.getContextRoot(endpoint.getPortMetaData());
        String hostname = endpoint.getPortMetaData().getHostname();

        Host host = tomcatService.findHost(hostname);
        Context context = (Context) host.findChild(contextName);

        // remove the docbase directory
        // add by youchao
        String path = context.getDocBase();
        File docBase = new File(path);
        if(docBase.isDirectory()) {
            docBase.delete();
        }

        host.removeChild(context);

        logger.debug("Context {0} stopped", contextName);
    }

}
