Package org.ow2.easybeans.deployer

Source Code of org.ow2.easybeans.deployer.JettyDeployer

/**
* EasyBeans
* Copyright (C) 2007 Bull S.A.S.
* Contact: easybeans@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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: JettyDeployer.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/

package org.ow2.easybeans.deployer;

import java.lang.reflect.Method;
import java.net.URL;
import java.util.List;

import javax.servlet.ServletContextEvent;

import org.ow2.easybeans.deployment.api.EZBInjectionHolder;
import org.ow2.util.archive.api.ArchiveException;
import org.ow2.util.ee.deploy.api.deployable.EARDeployable;
import org.ow2.util.ee.deploy.api.deployable.EJBDeployable;
import org.ow2.util.ee.deploy.api.deployable.IDeployable;
import org.ow2.util.ee.deploy.api.deployable.WARDeployable;
import org.ow2.util.ee.deploy.api.deployer.DeployerException;
import org.ow2.util.ee.deploy.api.deployer.IDeployer;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
* Implementation of the Deployer for EasyBeans in Jetty. <br />
* It will deploy EJB3 and EAR. EJB3 will be deployed in EasyBeans while WAR
* file will go in Jetty.
* @author Florent Benoit
*/
public class JettyDeployer extends AbsWebContainerDeployer implements IDeployer {

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

    /**
     * Link to the Jetty Server used to deploy the web applications.
     * Static as shared by all jetty deployers.
     */
    private static Object jettyServer = null;


    /**
     * Name of the WebAppContext class used to deploy a war file.
     */
    private static final String WEB_APP_CONTEXT_CLASS_NAME = "org.mortbay.jetty.webapp.WebAppContext";

    /**
     * WebAppContext class used to deploy a war file.
     */
    private Class webAppContextClass = null;

    /**
     * Name of the method used to get the child handler on the server object.
     */
    private static final String GET_CHILD_HANDLER_METHOD_NAME = "getChildHandlerByClass";

    /**
     * Name of the class that represent an handler collection.
     */
    private static final String HANDLER_COLLECTION_CLASS_NAME = "org.mortbay.jetty.handler.HandlerCollection";

    /**
     * List of the contexts deployed on the current jetty server.
     */
    private Object contexts = null;

    /**
     * Name of the method used to set the URL of the war file on the web app context.
     */
    private static final String SET_WAR_METHOD_NAME = "setWar";

    /**
     * Method object used to set the URL of the war file on the web app context.
     */
    private Method setWarMethod = null;

    /**
     * Name of the method used to set the name of the context on the web app context.
     */
    private static final String SET_CONTEXT_METHOD_NAME = "setContextPath";

    /**
     * Method object used to set the name of the context on the web app context.
     */
    private Method setContextPathMethod = null;

    /**
     * Name of the method used to get the name of the context on the web app context.
     */
    private static final String GET_CONTEXT_METHOD_NAME = "getContextPath";

    /**
     * Method object used to get the name of the context on the web app context.
     */
    private Method getContextPathMethod = null;


    /**
     * Name of the method used to start the web app context.
     */
    private static final String START_CONTEXT_METHOD_NAME = "start";

    /**
     * Method object used to start the web app context.
     */
    private Method startContextMethod = null;

    /**
     * Name of the method used to stop the web app context.
     */
    private static final String STOP_CONTEXT_METHOD_NAME = "stop";

    /**
     * Method object used to stop the web app context.
     */
    private Method stopContextMethod = null;

    /**
     * Name of the class that is an handler.
     */
    private static final String HANDLER_CLASS_NAME = "org.mortbay.jetty.Handler";

    /**
     * Name of the method used to add an handler.
     */
    private static final String ADD_HANDLER_METHOD_NAME = "addHandler";

    /**
     * Method object used to add an handler.
     */
    private Method addHandlerMethod = null;

    /**
     * Name of the method used to remove an handler.
     */
    private static final String REMOVE_HANDLER_METHOD_NAME = "removeHandler";

    /**
     * Method object used to remove an handler.
     */
    private Method removeHandlerMethod = null;


    /**
     * Name of the method used to get all handlers.
     */
    private static final String GET_ALL_HANDLER_METHOD_NAME = "getHandlers";

    /**
     * Method object used to get all handlers.
     */
    private Method getHandlersMethod = null;


    /**
     * Name of the method for changing the Java Delegation model.
     */
    private static final String SET_JAVA_DELEGATION_MODEL_METHOD_NAME = "setParentLoaderPriority";

    /**
     * Method object used for changing the Java Delegation model.
     */
    private Method javaDelegationModelMethod = null;


    /**
     * Build a new instance of this deployer.
     * @throws DeployerException if the instance is not built.
     */
    public JettyDeployer() throws DeployerException {
        super();

        // Check if this deployer has been initialized correctly
        if (jettyServer == null) {
            throw new DeployerException("This deployer has not be initialized correctly as the Jetty server is null");
        }

        // Load the class
        this.webAppContextClass = loadClass(WEB_APP_CONTEXT_CLASS_NAME, getClassLoader());

        // get Handler collection from jetty
        Method getChildHandlerByClassMethod = getMethod(jettyServer.getClass(), GET_CHILD_HANDLER_METHOD_NAME, Class.class);
        Class handlerCollectionClass = loadClass(HANDLER_COLLECTION_CLASS_NAME, getClassLoader());
        Object handlerCollection = invoke(getChildHandlerByClassMethod, jettyServer, handlerCollectionClass);
        if (handlerCollection == null) {
            throw new DeployerException("No handler collection has been defined on the jetty server object '" + jettyServer
                    + "'.");
        }
        this.contexts = invoke(getChildHandlerByClassMethod, handlerCollection, handlerCollectionClass);

        // add/remove/get Handler method
        Class handlerClazz = loadClass(HANDLER_CLASS_NAME, getClassLoader());
        this.addHandlerMethod = getMethod(this.contexts.getClass(), ADD_HANDLER_METHOD_NAME, handlerClazz);
        this.removeHandlerMethod = getMethod(this.contexts.getClass(), REMOVE_HANDLER_METHOD_NAME, handlerClazz);
        this.getHandlersMethod = getMethod(this.contexts.getClass(), GET_ALL_HANDLER_METHOD_NAME);


        // get the setters methods
        this.setWarMethod = getMethod(this.webAppContextClass, SET_WAR_METHOD_NAME, String.class);
        this.setContextPathMethod = getMethod(this.webAppContextClass, SET_CONTEXT_METHOD_NAME, String.class);
        this.javaDelegationModelMethod = getMethod(this.webAppContextClass, SET_JAVA_DELEGATION_MODEL_METHOD_NAME, boolean.class);

        // getters
        this.getContextPathMethod = getMethod(this.webAppContextClass, GET_CONTEXT_METHOD_NAME);

        // and the start method
        this.startContextMethod = getMethod(this.webAppContextClass, START_CONTEXT_METHOD_NAME);
        this.stopContextMethod = getMethod(this.webAppContextClass, STOP_CONTEXT_METHOD_NAME);

    }

    /**
     * Deploy a deployable. It can be an EJB jar, EAR, WAR, etc.
     * @param deployable a given deployable
     * @throws DeployerException if the deployment is not done.
     */
    public void deploy(final IDeployable deployable) throws DeployerException {
        checkSupportedDeployable(deployable);
        if (deployable instanceof EJBDeployable) {
            deployEJB((EJBDeployable) deployable);
        } else if (deployable instanceof EARDeployable) {
            // needs to unpack it before deploying it
            EARDeployable earDeployable = unpackEARDeployable((EARDeployable) deployable);
            deployEAR(earDeployable);
        }
    }


    /**
     * Deploy the WAR files present in the given EAR.
     * @param earDeployable the EAR containing the WARs
     * @param earURL the EAR URL
     * @param earClassLoader the EAR classloader
     * @param parentClassLoader the parent classloader (EJB) to use
     * @param ejbInjectionHolder the EasyBeans injection holder object
     * @throws DeployerException if the wars are not deployed.
     */
    @Override
    protected void deployWARs(final EARDeployable earDeployable, final URL earURL, final ClassLoader earClassLoader,
            final ClassLoader parentClassLoader, final EZBInjectionHolder ejbInjectionHolder) throws DeployerException {
        // First, try to see if there are .war in this EAR
        List<WARDeployable> wars = earDeployable.getWARDeployables();

        for (WARDeployable war : wars) {

            // Build a new instance of the webapp context
            Object webAppContext = newInstance(this.webAppContextClass);

            // invoke setters
            // for the URL of the war file
            try {
                invoke(this.setWarMethod, webAppContext, war.getArchive().getURL().getPath());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get URL from the archive '" + war.getArchive() + "'.", e);
            }
            // for defining the name of the context
            invoke(this.setContextPathMethod, webAppContext, "/" + war.getContextRoot());

            // Java delegation model = true
            invoke(this.javaDelegationModelMethod, webAppContext, Boolean.TRUE);

            // add the built context on the existing list
            invoke(this.addHandlerMethod, this.contexts, webAppContext);

            // set the thread context classloader to the parent classloader
            ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(parentClassLoader);

            // start context
            try {
                invoke(this.startContextMethod, webAppContext);
            } finally {
                // reset classloader
                Thread.currentThread().setContextClassLoader(oldCl);
            }

            // War has been deployed
            logger.info("The war ''{0}'' has been deployed on the ''{1}'' context.", war, war.getContextRoot());
        }
    }

    /**
     * @return the classloader for loading the class.
     */
    private static ClassLoader getClassLoader() {
        return jettyServer.getClass().getClassLoader();
    }

    /**
     * Check that the given deployable is supported by this deployer. If it is
     * not supported, throw an error.
     * @param deployable the deployable that needs to be deployed
     * @throws DeployerException if this deployable is not supported.
     */
    private void checkSupportedDeployable(final IDeployable deployable) throws DeployerException {
        if (!(deployable instanceof EARDeployable || deployable instanceof EJBDeployable)) {
            throw new DeployerException("The deployable '" + deployable + "' is not supported by this deployer");
        }
    }

    /**
     * Undeploy an given WAR (called by the undeploy method).
     * @param warDeployable a given WAR deployable
     * @throws DeployerException if the undeployment is not done.
     */
    @Override
    protected void undeployWAR(final WARDeployable warDeployable) throws DeployerException {
        // get the root context of this deployable
        String contextRoot = warDeployable.getContextRoot();

        // Get all handlers
        Object[] handlers = (Object[]) invoke(this.getHandlersMethod, this.contexts);

        // For each handler, check the name of the context root
        Object context = null;
        for (Object handler : handlers) {
            // Handler is a webapp context ?
            if (handler.getClass().equals(this.webAppContextClass)) {
                // get context
                String foundCtx = (String) invoke(this.getContextPathMethod, handler);
                if (contextRoot.equals(foundCtx) || ("/" + contextRoot).equals(foundCtx)) {
                    // found !
                    context = handler;
                    break;
                }
            }
        }

        // Context not found
        if (context == null) {
            throw new DeployerException("Unable to find a context with the name '" + contextRoot
                    + "' for the War deployable '" + warDeployable + "'.");
        }

        // Stop the context
        invoke(this.stopContextMethod, context);

        // Remove the context
        invoke(this.removeHandlerMethod, this.contexts, context);

        logger.info("The context ''{0}'' of the War ''{1}'' has been undeployed", contextRoot, warDeployable);

    }

    /**
     * Set the given context event object.
     * @param contextEvent the given object.
     * @throws DeployerException if the jetty server object is not found from the given context event.
     */
    public static void setContextEvent(final ServletContextEvent contextEvent) throws DeployerException {

        // First, try to get the source on the given context event
        Object source = contextEvent.getSource();
        if (source == null) {
            throw new DeployerException("No source object on the given contextEvent '" + contextEvent + "'.");
        }

        // try to get getContextHandler method on this source object
        Method getContextHandlerMethod = getMethod(source.getClass(), "getContextHandler");
        if (getContextHandlerMethod == null) {
            throw new DeployerException("No getContextHandler method was found on the '" + source + "' object");
        }

        // get Handler
        Object contextHandler = invoke(getContextHandlerMethod, source);
        if (contextHandler == null) {
            throw new DeployerException("No context handler object was returned from the '" + source + "' object");
        }

        // get the getServer method
        Method getServerMethod = getMethod(contextHandler.getClass(), "getServer");
        if (getServerMethod == null) {
            throw new DeployerException("No getServer method was found on the '" + contextHandler + "' object");
        }

        // Set the jetty server
        jettyServer = invoke(getServerMethod, contextHandler);

        // No server ?
        if (jettyServer == null) {
            throw new DeployerException("No Jetty server found on the servlet context event '" + contextEvent + "'.");
        }

    }

}
TOP

Related Classes of org.ow2.easybeans.deployer.JettyDeployer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.