Package org.ow2.easybeans.deployer.web.tomcat

Source Code of org.ow2.easybeans.deployer.web.tomcat.Tomcat6Deployer

/**
* EasyBeans
* Copyright (C) 2008 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: Tomcat6Deployer.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/

package org.ow2.easybeans.deployer.web.tomcat;

import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.catalina.Container;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.StandardContext;
import org.ow2.easybeans.deployer.AbsWebContainerDeployer;
import org.ow2.easybeans.deployment.api.EZBInjectionHolder;
import org.ow2.easybeans.jmx.CommonsModelerException;
import org.ow2.easybeans.jmx.CommonsModelerHelper;
import org.ow2.easybeans.jmx.JMXRemoteException;
import org.ow2.easybeans.jmx.MBeanServerHelper;
import org.ow2.easybeans.util.url.URLUtils;
import org.ow2.util.archive.api.ArchiveException;
import org.ow2.util.ee.deploy.api.deployable.EARDeployable;
import org.ow2.util.ee.deploy.api.deployable.WARDeployable;
import org.ow2.util.ee.deploy.api.deployable.metadata.DeployableMetadataException;
import org.ow2.util.ee.deploy.api.deployer.DeployerException;
import org.ow2.util.ee.deploy.api.deployer.IDeployer;
import org.ow2.util.ee.metadata.common.impl.enc.ENCBindingException;
import org.ow2.util.ee.metadata.common.impl.enc.ENCBindingHolder;
import org.ow2.util.ee.metadata.war.api.IWarDeployableMetadata;
import org.ow2.util.ee.metadata.war.impl.WarDeployableMetadataFactory;
import org.ow2.util.ee.metadata.war.impl.enc.ENCBindingBuilder;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
* Deployer used when EasyBeans is embedded in Tomcat 6.0.x.
* @author Florent Benoit
*/
public class Tomcat6Deployer extends AbsWebContainerDeployer implements IDeployer {

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

    /**
     * Engine Object Name.
     */
    private static final String ENGINE_OBJECT_NAME = "*:type=Engine";

    /**
     * Destroy operation on the Tomcat context to undeploy the war.
     */
    private static final String DESTROY_OPERATION = "destroy";

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

    /**
     * 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 context for this war file
            StandardContext standardContext = new StandardContext();

            // Build Object Name
            String objectName = buildObjectName(war);

            // Register Object MBean
            try {
                CommonsModelerHelper.registerModelerMBean(standardContext, objectName);
            } catch (CommonsModelerException e) {
                throw new DeployerException("Cannot register the object '" + standardContext + "' with the objectname '"
                        + objectName + "'.", e);
            }

            // set the context-root

            standardContext.setPath(war.getContextRoot());

            // Get the URL for this War
            URL warURL = null;
            try {
                warURL = war.getArchive().getURL();
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the archive '" + war.getArchive() + "'.", e);
            }


            // Analyze the war archive
            IWarDeployableMetadata warDeployableMetadata = null;
            try {
                warDeployableMetadata = new WarDeployableMetadataFactory().createDeployableMetadata(war);
            } catch (DeployableMetadataException e) {
                logger.error("Unable to analyze the metadata of the war '" + warURL + "'.", e);
            }

            // Now, get the bindings for this web application
            ENCBindingHolder encBindingHolder = null;
            if (warDeployableMetadata != null) {
                try {
                    encBindingHolder = ENCBindingBuilder.analyze(warDeployableMetadata);
                } catch (ENCBindingException e) {
                    logger.error("Unable to analyze metadata of '" + warURL + "'", e);
                }
            }

            // File of this war
            File warFile = URLUtils.urlToFile(warURL);

            // docbase
            String docBase = warFile.getPath();

            // File and not a directory --> unpack it
            if (warFile.isFile()) {
                // Need to unpack the file
                File unpackDir = unpack(warFile, war, earURL);
                docBase = unpackDir.getPath();
            }

            // set the path to the war file (needs to be unpacked else it will
            // be unpacked by tomcat in the webapps folder and it will try to
            // deploy twice the webapp with wrong classloader)
            standardContext.setDocBase(docBase);

            // default XML files
            standardContext.setDefaultWebXml("conf/web.xml");
            standardContext.setDefaultContextXml("context.xml");


            File contextXmlFile = new File(docBase + File.separator + "META-INF" + File.separator + "context.xml");
            // META-INF/context.xml file support
            if (contextXmlFile.exists()) {
                standardContext.setConfigFile(contextXmlFile.getAbsolutePath());
            }

            // Set the parent class loader
            standardContext.setParentClassLoader(parentClassLoader);

            // Set the java delegation model
            standardContext.setDelegate(true);

            // Set our naming context listener
            EasyBeansNamingContextListener namingContextListener = new EasyBeansNamingContextListener();
            namingContextListener.setEncBindingHolder(encBindingHolder);
            namingContextListener.setInjectionHolder(ejbInjectionHolder);
            namingContextListener.setName(getNamingContextName(standardContext));
            standardContext.addLifecycleListener(namingContextListener);
            standardContext.setNamingContextListener(namingContextListener);

            // Start the context
            try {
                standardContext.start();
            } catch (LifecycleException e) {
                throw new DeployerException("Cannot start the context of the War '" + warURL + "'.", e);
            }

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

    /**
     * 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();

        // Now, search the MBean of this context
        ObjectName contextObjectName = null;
        try {
            contextObjectName = new ObjectName(buildObjectName(warDeployable));
        } catch (MalformedObjectNameException e) {
            throw new DeployerException("Cannot get the ObjectName for the WAR deployable '" + warDeployable + "'.", e);
        } catch (NullPointerException e) {
            throw new DeployerException("Cannot get the ObjectName for the WAR deployable '" + warDeployable + "'.", e);
        }

        // Now, search if the MBean of this context is present
        try {
            if (!MBeanServerHelper.getMBeanServerServer().isRegistered(contextObjectName)) {
                throw new DeployerException("There is no MBean with the ObjectName '" + contextObjectName
                        + "' in the MBean Server for the WAR deployable '" + warDeployable + "'.");
            }
        } catch (JMXRemoteException e) {
            throw new DeployerException("Cannot check if the MBean with the ObjectName '" + contextObjectName
                    + "'is registered in the MBean Server for the WAR deployable '" + warDeployable + "'.");
        }

        // Undeploy
        try {
            MBeanServerHelper.getMBeanServerServer().invoke(contextObjectName, DESTROY_OPERATION, null, null);
        } catch (InstanceNotFoundException e) {
            throw new DeployerException("Cannot remove the context '" + contextRoot + "' of the war deployable '"
                    + warDeployable + "'.", e);
        } catch (MBeanException e) {
            throw new DeployerException("Cannot remove the context '" + contextRoot + "' of the war deployable '"
                    + warDeployable + "'.", e);
        } catch (ReflectionException e) {
            throw new DeployerException("Cannot remove the context '" + contextRoot + "' of the war deployable '"
                    + warDeployable + "'.", e);
        } catch (JMXRemoteException e) {
            throw new DeployerException("Cannot remove the context '" + contextRoot + "' of the war deployable '"
                    + warDeployable + "'.", e);
        }

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

    /**
     * Build an objectname for the given war.
     * @param war the given war deployable that contains the datas.
     * @return a JMX object name.
     * @throws DeployerException if the object name cannot be built.
     */
    private String buildObjectName(final WARDeployable war) throws DeployerException {
        String objectName = getDomain() + ":j2eeType=WebModule,name=//" + getDefaultHost() + "/" + war.getContextRoot()
                + ",J2EEServer=EasyBeans,J2EEApplication=EAR";
        return objectName;
    }

    /**
     * Gets the JMX domain of Tomcat.
     * @return the JMX domain of Tomcat.
     * @throws DeployerException if the domain cannot be found
     */
    private String getDomain() throws DeployerException {
        return getEngineObjectName().getDomain();
    }

    /**
     * @return the first Engine object name found in the MBean server
     * @throws DeployerException if the engine object name is not found in
     *         the MBean server.
     */
    @SuppressWarnings("unchecked")
    private ObjectName getEngineObjectName() throws DeployerException {
        // Build Engine object name
        ObjectName engineObjectName = null;
        try {
            engineObjectName = new ObjectName(ENGINE_OBJECT_NAME);
        } catch (MalformedObjectNameException e) {
            throw new DeployerException("Cannot build Tomcat Engine MBean.", e);
        } catch (NullPointerException e) {
            throw new DeployerException("Cannot build Tomcat Engine MBean.", e);
        }

        // Ask the MBean server
        Set<ObjectName> objectNames = null;
        try {
            // Get the list
            objectNames = MBeanServerHelper.getMBeanServerServer().queryNames(engineObjectName, null);
        } catch (JMXRemoteException e) {
            throw new DeployerException("Cannot get Tomcat Engine MBean.", e);
        }

        // Find objects ?
        if (objectNames.size() == 0) {
            throw new DeployerException("No Tomcat Engine MBean was found in the MBean server");
        }

        // Return the domain of this object name
        return (objectNames.iterator().next());
    }

    /**
     * @return the default host of the first engine found in the MBean server
     * @throws DeployerException if the MBean is not found.
     */
    private String getDefaultHost() throws DeployerException {
        ObjectName engineObjectName = getEngineObjectName();
        try {
            return MBeanServerHelper.getMBeanServerServer().getAttribute(engineObjectName, "defaultHost").toString();
        } catch (AttributeNotFoundException e) {
            throw new DeployerException("Cannot get the default host on the object name '" + engineObjectName + "'.", e);
        } catch (InstanceNotFoundException e) {
            throw new DeployerException("Cannot get the default host on the object name '" + engineObjectName + "'.", e);
        } catch (MBeanException e) {
            throw new DeployerException("Cannot get the default host on the object name '" + engineObjectName + "'.", e);
        } catch (ReflectionException e) {
            throw new DeployerException("Cannot get the default host on the object name '" + engineObjectName + "'.", e);
        } catch (JMXRemoteException e) {
            throw new DeployerException("Cannot get the default host on the object name '" + engineObjectName + "'.", e);
        }
    }


    /**
     * Get naming context full name.
     * @param standardContext that will be used to compute the standard context.
     * @return the naming context full name.
     */
    private String getNamingContextName(final StandardContext standardContext) {
        String namingContextName = null;
        Container parent = standardContext.getParent();
        if (parent == null) {
            namingContextName = standardContext.getName();
        } else {
            Stack<String> stk = new Stack<String>();
            StringBuffer buff = new StringBuffer();
            while (parent != null) {
                stk.push(parent.getName());
                parent = parent.getParent();
            }
            while (!stk.empty()) {
                buff.append("/" + stk.pop());
            }
            buff.append(standardContext.getName());
            namingContextName = buff.toString();
        }
        return namingContextName;
    }

}
TOP

Related Classes of org.ow2.easybeans.deployer.web.tomcat.Tomcat6Deployer

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.