Package org.ow2.easybeans.deployer

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

/**
* 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: JOnASDeployer.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/

package org.ow2.easybeans.deployer;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.Policy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.security.jacc.PolicyConfiguration;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyContextException;

import org.ow2.easybeans.api.EZBContainer;
import org.ow2.easybeans.api.EZBContainerException;
import org.ow2.easybeans.deployment.InjectionHolder;
import org.ow2.easybeans.loader.EasyBeansClassLoader;
import org.ow2.easybeans.naming.context.ContextImpl;
import org.ow2.easybeans.persistence.PersistenceUnitManager;
import org.ow2.easybeans.resolver.ApplicationJNDIResolver;
import org.ow2.easybeans.resolver.api.EZBApplicationJNDIResolver;
import org.ow2.easybeans.resolver.api.EZBContainerJNDIResolver;
import org.ow2.util.archive.api.ArchiveException;
import org.ow2.util.archive.api.IArchive;
import org.ow2.util.ee.deploy.api.deployable.CARDeployable;
import org.ow2.util.ee.deploy.api.deployable.EARDeployable;
import org.ow2.util.ee.deploy.api.deployable.EJB21Deployable;
import org.ow2.util.ee.deploy.api.deployable.EJB3Deployable;
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.LibDeployable;
import org.ow2.util.ee.deploy.api.deployable.RARDeployable;
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 JOnAS. <br />
* It will deploy EJB3 and EAR. EJB21 of the EAR will go in JOnAS, EJB3 in
* EasyBeans, War in JOnAS, Rar in JOnAS.
* @author Florent Benoit
*/
public class JOnASDeployer extends AbsDeployer implements IDeployer {

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

    /**
     * JOnAS JClassLoader class.
     */
    private static final String JCLASSLOADER_CLASS = "org.objectweb.jonas.server.JClassLoader";

    /**
     * JOnAS service manager class.
     */
    private static final String SERVICE_MANAGER_CLASS = "org.objectweb.jonas.service.ServiceManager";

    /**
     * JOnAS EJB Manager Wrapper class.
     */
    private static final String EJBMANAGERWRAPPER_CLASS = "org.objectweb.jonas_ejb.deployment.lib.wrapper.EjbManagerWrapper";

    /**
     * JOnAS WEB Manager Wrapper class.
     */
    private static final String WEBMANAGERWRAPPER_CLASS = "org.objectweb.jonas_web.deployment.lib.wrapper.WebManagerWrapper";

    /**
     * JOnAS Client Manager Wrapper class.
     */
    private static final String CLIENTMANAGERWRAPPER_CLASS
        = "org.objectweb.jonas_client.deployment.lib.wrapper.ClientManagerWrapper";

    /**
     * JOnAS EJB manager setAvailable method.
     */
    private static final String EJBMANAGERWRAPPER_SETAVAILABLE_METHODNAME = "setAvailableEjbJarsAndAltDDs";

    /**
     * JOnAS WEB manager setAltDD method.
     */
    private static final String WEBMANAGERWRAPPER_SETALTDD_METHODNAME = "setAltDD";

    /**
     * JOnAS Client manager setAltDD method.
     */
    private static final String CLIENTMANAGERWRAPPER_SETALTDD_METHODNAME = "setAltDD";

    /**
     * JOnAS service manager getInstance() method name.
     */
    private static final String SERVICE_MANAGER_GETINSTANCE_METHODNAME = "getInstance";

    /**
     * JOnAS service manager getEjbService() method name.
     */
    private static final String SERVICE_MANAGER_GETEJBSERVICE_METHODNAME = "getEjbService";

    /**
     * JOnAS service manager getWebContainerService() method name.
     */
    private static final String SERVICE_MANAGER_GETWEBCONTAINERSERVICE_METHODNAME = "getWebContainerService";

    /**
     * JOnAS service manager getRarService() method name.
     */
    private static final String SERVICE_MANAGER_GETRARSERVICE_METHODNAME = "getRarService";

    /**
     * checkGenIC method on the EJB 2.1 service.
     */
    private static final String CHECK_GENIC_METHODNAME = "checkGenIC";

    /**
     * deploy method on the EJB 2.1 service.
     */
    private static final String EJBSERVICE_DEPLOY_METHODNAME = "deployJars";

    /**
     * deploy method on the EJB 2.1 service.
     */
    private static final String EJBSERVICE_UNDEPLOY_METHODNAME = "unDeployJars";

    /**
     * deploy method on the RAR service.
     */
    private static final String RARSERVICE_DEPLOY_METHODNAME = "deployRars";

    /**
     * undeploy method on the RAR service.
     */
    private static final String RARSERVICE_UNDEPLOY_METHODNAME = "unDeployRars";

    /**
     * deploy method on the Web container service.
     */
    private static final String WARSERVICE_DEPLOY_METHODNAME = "deployWars";

    /**
     * undeploy method on the Web container service.
     */
    private static final String WARSERVICE_UNDEPLOY_METHODNAME = "unDeployWars";

    /**
     * Reference to the JOnAS service manager.
     */
    private Object serviceManager = null;

    /**
     * Reference to the JOnAS EJB 2.1 Service.
     */
    private Object ejb21Service = null;

    /**
     * Reference to the JOnAS Web Service.
     */
    private Object warService = null;

    /**
     * Reference to the deploy method of war service.
     */
    private Method deployMethodwarService = null;

    /**
     * Reference to the undeploy method of war service.
     */
    private Method undeployMethodwarService = null;

    /**
     * Reference to the deploy method of EJB 2.1 service.
     */
    private Method deployMethodejb21Service = null;

    /**
     * Reference to the undeploy method of EJB 2.1 service.
     */
    private Method undeployMethodejb21Service = null;

    /**
     * Reference to the checkGenIC method of EJB 2.1 service.
     */
    private Method checkGenICMethod = null;

    /**
     * Reference to the JOnAS Resource Service.
     */
    private Object rarService = null;

    /**
     * Reference to the deploy method of rar service.
     */
    private Method deployMethodRarService = null;

    /**
     * Reference to the undeploy method of rar service.
     */
    private Method undeployMethodRarService = null;

    /**
     * Classloader used by JOnAS.
     */
    private Constructor jClassLoaderConstructor = null;

    /**
     * setAltDD method on EJB manager.
     */
    private Method ejbSetAltDD = null;

    /**
     * setAltDD method on Web manager.
     */
    private Method webSetAltDD = null;

    /**
     * setAltDD method on Client manager.
     */
    private Method clientSetAltDD = null;


    /**

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

        // First, get the service manager
        Class serviceManagerClazz = loadClass(SERVICE_MANAGER_CLASS);

        // Get the unique instance of the service manager
        Method getInstanceMethod = getMethod(serviceManagerClazz, SERVICE_MANAGER_GETINSTANCE_METHODNAME);
        this.serviceManager = invoke(getInstanceMethod, null);

        // Get ejb service
        Method getEJBServiceMethod = getMethod(serviceManagerClazz, SERVICE_MANAGER_GETEJBSERVICE_METHODNAME);
        this.ejb21Service = invoke(getEJBServiceMethod, this.serviceManager);

        // War service
        Method getWarServiceMethod = getMethod(serviceManagerClazz, SERVICE_MANAGER_GETWEBCONTAINERSERVICE_METHODNAME);
        this.warService = invoke(getWarServiceMethod, this.serviceManager);

        // Rar service
        Method getRarServiceMethod = getMethod(serviceManagerClazz, SERVICE_MANAGER_GETRARSERVICE_METHODNAME);
        this.rarService = invoke(getRarServiceMethod, this.serviceManager);

        // (un)deployRars method
        this.deployMethodRarService = getMethod(this.rarService.getClass(), RARSERVICE_DEPLOY_METHODNAME, Context.class);
        this.undeployMethodRarService = getMethod(this.rarService.getClass(), RARSERVICE_UNDEPLOY_METHODNAME, URL[].class, URL.class);

        // (un)deployWars method
        this.deployMethodwarService = getMethod(this.warService.getClass(), WARSERVICE_DEPLOY_METHODNAME, Context.class);
        this.undeployMethodwarService = getMethod(this.warService.getClass(), WARSERVICE_UNDEPLOY_METHODNAME, URL[].class);

        // (un)Deploy Jars method
        this.deployMethodejb21Service = getMethod(this.ejb21Service.getClass(), EJBSERVICE_DEPLOY_METHODNAME, Context.class);
        this.undeployMethodejb21Service = getMethod(this.ejb21Service.getClass(), EJBSERVICE_UNDEPLOY_METHODNAME, URL[].class);

        // GenIC
        try {
            this.checkGenICMethod = getMethod(this.ejb21Service.getClass(), CHECK_GENIC_METHODNAME, String.class, URL[].class);
        } catch (DeployerException e) {
            logger.warn("A method was not present in this JOnAS version, auto-GenIC will be disabled");
        }

        // get the constructor of the JClassLoader class.
        Class jclassLoaderClass = loadClass(JCLASSLOADER_CLASS);

        // Then get the constructor of JClassLoader
        try {
            this.jClassLoaderConstructor = jclassLoaderClass.getConstructor(String.class, URL[].class, ClassLoader.class);
        } catch (SecurityException e) {
            throw new DeployerException("Cannot get the constructor on the '" + JCLASSLOADER_CLASS + "' class", e);
        } catch (NoSuchMethodException e) {
            throw new DeployerException("Cannot get the constructor on the '" + JCLASSLOADER_CLASS + "' class", e);
        }

        // SetAltDD methods
        // First, load the classes
        Class ejbManagerClass = loadClass(EJBMANAGERWRAPPER_CLASS);
        Class webManagerClass = loadClass(WEBMANAGERWRAPPER_CLASS);
        Class clientManagerClass = loadClass(CLIENTMANAGERWRAPPER_CLASS);
        // Then get the methods
        this.ejbSetAltDD = getMethod(ejbManagerClass, EJBMANAGERWRAPPER_SETAVAILABLE_METHODNAME, URLClassLoader.class, URL[].class,
                URL[].class);
        this.webSetAltDD = getMethod(webManagerClass, WEBMANAGERWRAPPER_SETALTDD_METHODNAME, URLClassLoader.class, URL[].class,
                URL[].class);
        this.clientSetAltDD = getMethod(clientManagerClass, CLIENTMANAGERWRAPPER_SETALTDD_METHODNAME, URLClassLoader.class,
                URL[].class, URL[].class);

    }

    /**
     * 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);
            // flag as deployed
            String path;
            try {
                path = earDeployable.getOriginalDeployable().getArchive().getURL().toExternalForm();
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for deployable '" + earDeployable + "'.", e);
            }
            setDeployed(path, earDeployable);
        }
    }

    /**
     * Undeploy the given deployable. It can be an EJB jar, EAR, WAR, etc.
     * @param deployable a given deployable to undeploy
     * @throws DeployerException if the undeploy operation fails.
     */
    public void undeploy(final IDeployable deployable) throws DeployerException {
        if (deployable instanceof EARDeployable) {
            undeployEAR((EARDeployable) deployable);
            // unflag deployed
            unsetDeployed(deployable);
        } else {
            throw new UnsupportedOperationException("Undeploy only .ear files");
        }
    }

    /**
     * Undeploy an EAR (called by the undeploy method).
     * @param tmpEARDeployable a given EAR deployable
     * @throws DeployerException if the undeployment is not done.
     */
    protected void undeployEAR(final EARDeployable tmpEARDeployable) throws DeployerException {
        logger.info("Undeploying {0}", tmpEARDeployable);

        // From which deployable get the containers deployed
        EARDeployable earDeployable = tmpEARDeployable;

        // Was deployed ?
        EARDeployable existingDeployable = null;
        try {
            existingDeployable = EARDeployable.class.cast(getDeployedDeployable(tmpEARDeployable.getArchive().getURL()
                    .toExternalForm()));
        } catch (ArchiveException e) {
            throw new DeployerException("Cannot get the URL on the EAR deployable '" + earDeployable + "'.", e);
        }
        if (existingDeployable != null) {
            earDeployable = existingDeployable;
        }

        // Check if this archive has been unpacked ?
        EARDeployable unpackedDeployable = earDeployable.getUnpackedDeployable();
        if (unpackedDeployable != null) {
            earDeployable = unpackedDeployable;
        }

        // get EAR URL
        URL earURL;
        try {
            earURL = earDeployable.getArchive().getURL();
        } catch (ArchiveException e) {
            throw new DeployerException("Cannot get the URL on the EAR deployable '" + earDeployable + "'.", e);
        }

        // Undeploy wars (by sending URL of these wars)
        List<WARDeployable> warDeployables = earDeployable.getWARDeployables();
        if (warDeployables != null && this.warService != null) {
            List<URL> urls = new ArrayList<URL>();
            for (WARDeployable warDeployable : warDeployables) {
                try {
                    urls.add(warDeployable.getArchive().getURL());
                } catch (ArchiveException e) {
                    logger.error("Cannot get the URL from the Deployable ''{0}''", warDeployable, e);
                }
            }

            URL[] warURLs = urls.toArray(new URL[urls.size()]);
            invoke(this.undeployMethodwarService, this.warService, new Object[]{warURLs});
        }

        // Undeploy EJB 2.1 jars (by sending URL of these jars)
        List<EJB21Deployable> ejb21Deployables = earDeployable.getEJB21Deployables();
        if (ejb21Deployables != null && this.ejb21Service != null) {
            List<URL> urls = new ArrayList<URL>();
            for (EJB21Deployable ejbDeployable : ejb21Deployables) {
                try {
                    urls.add(ejbDeployable.getArchive().getURL());
                } catch (ArchiveException e) {
                    logger.error("Cannot get the URL from the Deployable ''{0}''", ejbDeployable, e);
                }
            }

            // Call undeploy by using the array of URLs
            URL[] ejbJarURLs = urls.toArray(new URL[urls.size()]);
            invoke(this.undeployMethodejb21Service, this.ejb21Service, new Object[]{ejbJarURLs});

        }

        // Undeploy EJB3s
        undeployEJB3FromEAR(earDeployable);

        // Undeploy Resource Adapters (by sending URL of these jars)
        List<RARDeployable> rarDeployables = earDeployable.getRARDeployables();
        if (rarDeployables != null && this.rarService != null) {
            List<URL> urls = new ArrayList<URL>();
            for (RARDeployable rarDeployable : rarDeployables) {
                try {
                    urls.add(rarDeployable.getArchive().getURL());
                } catch (ArchiveException e) {
                    logger.error("Cannot get the URL from the Deployable ''{0}''", rarDeployable, e);
                }
            }

            // Call undeploy by using the array of URLs
            URL[] rarURLs = urls.toArray(new URL[urls.size()]);
            invoke(this.undeployMethodRarService, this.rarService, rarURLs, earURL);

        }

        logger.info("''{0}'' EAR Deployable is now undeployed", tmpEARDeployable);
    }

    /**
     * Deploy an EAR (called by the deploy method).
     * @param earDeployable a given EAR deployable
     * @throws DeployerException if the deployment is not done.
     */
    protected void deployEAR(final EARDeployable earDeployable) throws DeployerException {
        logger.info("Deploying {0}", earDeployable);

        // Get URL of this EAR
        URL earURL = null;
        try {
            earURL = earDeployable.getArchive().getURL();
        } catch (ArchiveException e) {
            throw new DeployerException("Cannot get the URL for the deployable '" + earDeployable + "'.", e);
        }

        // Create a Root classloader for this EAR
        // Empty classloader
        URLClassLoader earClassLoader = (URLClassLoader) newInstance(this.jClassLoaderConstructor, earURL.toExternalForm(), new URL[0],
                Thread.currentThread().getContextClassLoader());

        // Get the URLs of EJB, WEB and Clients
        List<URL> urlsEJB = new ArrayList<URL>();
        for (EJBDeployable ejb : earDeployable.getEJBDeployables()) {
            try {
                urlsEJB.add(ejb.getArchive().getURL());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the archive '" + ejb.getArchive() + "'", e);
            }
        }
        List<URL> urlsWAR = new ArrayList<URL>();
        for (WARDeployable war : earDeployable.getWARDeployables()) {
            try {
                urlsWAR.add(war.getArchive().getURL());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the archive '" + war.getArchive() + "'", e);
            }
        }
        List<URL> urlsClient = new ArrayList<URL>();
        for (CARDeployable car : earDeployable.getCARDeployables()) {
            try {
                urlsClient.add(car.getArchive().getURL());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the archive '" + car.getArchive() + "'", e);
            }
        }

        // Set alt-dd
        invoke(this.ejbSetAltDD, null, earClassLoader, urlsEJB.toArray(new URL[urlsEJB.size()]), new URL[urlsEJB.size()]);
        invoke(this.webSetAltDD, null, earClassLoader, urlsWAR.toArray(new URL[urlsWAR.size()]), new URL[urlsWAR.size()]);
        invoke(this.clientSetAltDD, null, earClassLoader, urlsClient.toArray(new URL[urlsClient.size()]), new URL[urlsClient.size()]);

        // Deploy the RAR files of the EAR (if any)
        deployRARs(earDeployable, earURL, earClassLoader);

        // deploy EJB3s
        // Get EJBs of this EAR
        List<EJB3Deployable> ejb3s = earDeployable.getEJB3Deployables();
        List<EJBDeployable<?>> ejbs = earDeployable.getEJBDeployables();

        // Get libraries of this EAR
        List<LibDeployable> libs = earDeployable.getLibDeployables();

        // Create array of URLs with EJBs + Libraries
        List<URL> urls = new ArrayList<URL>();
        for (EJBDeployable<?> ejb : ejbs) {
            try {
                urls.add(ejb.getArchive().getURL());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the Archive '" + ejb.getArchive() + "'.", e);
            }
        }
        for (LibDeployable lib : libs) {
            try {
                urls.add(lib.getArchive().getURL());
            } catch (ArchiveException e) {
                throw new DeployerException("Cannot get the URL for the Archive '" + lib.getArchive() + "'.", e);

            }
        }

        // Create classloader with these URLs
        URL[] arrayURLs = urls.toArray(new URL[urls.size()]);

        // Child of the EAR classloader with RARs
        ClassLoader ejbClassLoader = new EasyBeansClassLoader(arrayURLs, earClassLoader);

        // Get Persistence unit manager
        PersistenceUnitManager persistenceUnitManager = getPersistenceUnitManager(earDeployable, ejbClassLoader);

        // Get Extra libraries
        List<IArchive> libArchives = getLibArchives(earDeployable);


        // Reset context ID of EJBs
        addEjbContextIdToList(earDeployable, new ArrayList<String>(), true);

        // Create containers for each EJB3 deployable
        List<EZBContainer> containers = new ArrayList<EZBContainer>();
        for (EJBDeployable ejb : ejb3s) {
            containers.add(getEmbedded().createContainer(ejb));
        }

        // Create Resolver for EAR
        EZBApplicationJNDIResolver applicationJNDIResolver = new ApplicationJNDIResolver();

        // Create EasyBeans injection Holder
        InjectionHolder ejbInjectionHolder = new InjectionHolder();
        ejbInjectionHolder.setPersistenceUnitManager(persistenceUnitManager);
        ejbInjectionHolder.setJNDIResolver(applicationJNDIResolver);


        // Configure containers
        for (EZBContainer container : containers) {
            // Set the classloader that needs to be used
            container.setClassLoader(ejbClassLoader);

            // Set application name
            container.setApplicationName(earDeployable.getModuleName());

            // Add persistence context found
            container.setPersistenceUnitManager(persistenceUnitManager);

            // Add the metadata
            container.setExtraArchives(libArchives);

            // set parent JNDI Resolver
            EZBContainerJNDIResolver containerJNDIResolver = container.getConfiguration().getContainerJNDIResolver();
            containerJNDIResolver.setApplicationJNDIResolver(applicationJNDIResolver);

            // Add child on application JNDI Resolver
            applicationJNDIResolver.addContainerJNDIResolver(containerJNDIResolver);


            // Resolve container
            try {
                container.resolve();
            } catch (EZBContainerException e) {
                throw new DeployerException("Cannot resolve the container '" + container.getArchive() + "'.", e);
            }
        }

        // Start containers
        for (EZBContainer container : containers) {
            try {
                container.start();
            } catch (Exception e) {
                logger.error("Cannot start container {0}", container.getName(), e);
                // stop it
                try {
                    container.stop();
                    getEmbedded().removeContainer(container);
                } catch (Exception se) {
                    logger.error("Cannot stop failing container {0}", container.getName(), se);
                }
                // rethrow it
                throw new DeployerException("Container '" + container.getName() + "' has failed", e);
            }
        }

        // Deploy EJB 2.1
        deployEJB21s(earDeployable, earURL, earClassLoader, ejbClassLoader);

        // Link policy context of EJBs and Webs components
        linkPolicyObjects(earDeployable);

        // Commit EJB Policy objects
        commitEJBPolicyObjects(earDeployable);

        // Deploy Web App
        deployWARs(earDeployable, earURL, earClassLoader, ejbClassLoader);

        // Commit Web policy objects
        commitWebBPolicyObjects(earDeployable);

        logger.info("''{0}'' EAR Deployable is now deployed", 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
     * @throws DeployerException if the wars are not deployed.
     */
    protected void deployWARs(final EARDeployable earDeployable, final URL earURL, final ClassLoader earClassLoader,
            final ClassLoader parentClassLoader) throws DeployerException {
        // First, try to see if there are .war in this EAR
        List<WARDeployable> wars = earDeployable.getWARDeployables();

        if (wars.size() > 0) {
            if (this.warService == null) {
                logger.warn("There are WAR files in the EAR ''{0}'' but the 'web' service is not available", earDeployable);
            } else {

                // Build context for sending parameters
                Context ctx = new ContextImpl(earURL.toExternalForm());
                try {
                    ctx.rebind("earURL", earURL);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the EAR URL parameter '" + earURL + "'", e);
                }
                // Get URLS of the wars and context-root
                List<URL> urls = new LinkedList<URL>();
                List<String> ctxRoots = new LinkedList<String>();
                for (WARDeployable warDeployable : wars) {

                    // URL
                    URL url = null;
                    try {
                        url = warDeployable.getArchive().getURL();
                    } catch (ArchiveException e) {
                        throw new DeployerException("Cannot get the URL for the archive '" + warDeployable.getArchive() + "'",
                                e);
                    }
                    urls.add(url);

                    // Context-root
                    ctxRoots.add(warDeployable.getContextRoot());

                }
                try {
                    ctx.rebind("urls", urls.toArray(new URL[urls.size()]));
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the urls parameter '" + urls + "'", e);
                }

                // Bind the parent classloader of the web application
                try {
                    ctx.rebind("parentClassLoader", parentClassLoader);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the parentClassLoader parameter '" + parentClassLoader + "'", e);
                }

                // Bind the earClassLoader of the web application
                try {
                    ctx.rebind("earClassLoader", earClassLoader);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the earClassLoader parameter '" + earClassLoader + "'", e);
                }

                // No alt-dd yet, give an empty array
                try {
                    ctx.rebind("altDDs", new URL[urls.size()]);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the altDDs parameter.'", e);
                }

                // Build context roots
                try {
                    ctx.rebind("contextRoots", ctxRoots.toArray(new String[ctxRoots.size()]));
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the contextRoots parameter '" + urls + "'", e);
                }

                try {
                    this.deployMethodwarService.invoke(this.warService, ctx);
                } catch (IllegalArgumentException e) {
                    throw new DeployerException("Cannot deploy the WARs.'", e);
                } catch (IllegalAccessException e) {
                    throw new DeployerException("Cannot deploy the WARs.'", e);
                } catch (InvocationTargetException e) {
                    throw new DeployerException("Cannot deploy the WARs.'", e.getTargetException());
                }
            }
        }

    }

    /**
     * Deploy the RARs of the given EAR.
     * @param earDeployable the EAR that contains the war files
     * @param earURL the URL of the EAR
     * @param earClassLoader the classloader of the EAR
     * @throws DeployerException if the RARs file can't be deployed
     */
    protected void deployRARs(final EARDeployable earDeployable, final URL earURL, final ClassLoader earClassLoader)
            throws DeployerException {
        // First, try to see if there are .rar in this EAR
        List<RARDeployable> rars = earDeployable.getRARDeployables();
        if (rars.size() > 0) {
            if (this.rarService == null) {
                logger.warn("There are RAR files in the EAR ''{0}'' but the resource service is not available", earDeployable);
            } else {
                Context ctx = new ContextImpl(earURL.toExternalForm());
                try {
                    ctx.rebind("earUrl", earURL);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the EAR URL parameter '" + earURL + "'", e);
                }
                List<URL> urls = new ArrayList<URL>();
                for (RARDeployable rarDeployable : rars) {
                    try {
                        urls.add(rarDeployable.getArchive().getURL());
                    } catch (ArchiveException e) {
                        throw new DeployerException("Cannot get the URL for the archive '" + rarDeployable.getArchive() + "'",
                                e);
                    }
                }
                try {
                    ctx.rebind("urls", urls.toArray(new URL[urls.size()]));
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the urls parameter '" + urls + "'", e);
                }
                try {
                    ctx.rebind("earClassLoader", earClassLoader);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the earClassLoader parameter '" + earClassLoader + "'", e);
                }
                try {
                    ctx.rebind("altDDs", new URL[urls.size()]);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the altDDs parameter.'", e);
                }

                try {
                    this.deployMethodRarService.invoke(this.rarService, ctx);
                } catch (IllegalArgumentException e) {
                    throw new DeployerException("Cannot deploy the RARs.'", e);
                } catch (IllegalAccessException e) {
                    throw new DeployerException("Cannot deploy the RARs.'", e);
                } catch (InvocationTargetException e) {
                    throw new DeployerException("Cannot deploy the RARs.'", e.getTargetException());
                }
            }
        }

    }

    /**
     * Deploy the EJB 2.1 of the given EAR.
     * @param earDeployable the EAR that contains the EJB files
     * @param earURL the URL of the EAR
     * @param earClassLoader the classloader of the EAR
     * @param ejbClassLoader the given EJB ClassLoader
     * @throws DeployerException if the EJB 2.1 filse can't be deployed
     */
    protected void deployEJB21s(final EARDeployable earDeployable, final URL earURL, final URLClassLoader earClassLoader,
            final ClassLoader ejbClassLoader) throws DeployerException {
        // First, try to see if there are EJB 2.1 in this EAR
        List<EJB21Deployable> ejbs = earDeployable.getEJB21Deployables();
        if (ejbs.size() > 0) {
            if (this.ejb21Service == null) {
                logger.warn("There are EJB 2.1 files in the EAR ''{0}'' but the EJB 2.1 service is not available", earDeployable);
            } else {

                // Build list of EJB URLs
                List<URL> urls = new ArrayList<URL>();
                for (EJB21Deployable ejb21Deployable : ejbs) {
                    try {
                        urls.add(ejb21Deployable.getArchive().getURL());
                    } catch (ArchiveException e) {
                        throw new DeployerException("Cannot get the URL for the archive '" + ejb21Deployable.getArchive()
                                + "'", e);
                    }
                }


                // Get classpath of the EJBs
                URL[] compilationURLs = null;

                // content of the ear loader (application wide resources)
                URL[] myApplicationJars = earClassLoader.getURLs();

                // content of the apps loader (system wide resources)
                URL[] appsJars = ((URLClassLoader) earClassLoader.getParent()).getURLs();

                // merge the 3 Set of URLs
                compilationURLs = new URL[myApplicationJars.length + appsJars.length + urls.size()];
                System.arraycopy(urls.toArray(new URL[urls.size()]), 0, compilationURLs, 0, urls.size());
                System.arraycopy(appsJars, 0, compilationURLs, urls.size(), appsJars.length);
                System.arraycopy(myApplicationJars, 0, compilationURLs, urls.size() + appsJars.length, myApplicationJars.length);

                // Call automatic GenIC on the URLs of the EJB 2.1
                if (this.checkGenICMethod != null) {
                    for (EJB21Deployable ejb : ejbs) {
                        URL ejbURL = null;
                        try {
                            ejbURL = ejb.getArchive().getURL();
                        } catch (ArchiveException e) {
                            throw new DeployerException("Cannot get the URL on the deployable '" + ejb + "'", e);
                        }
                        logger.debug("Calling GenIC on the EJB ''{0}'' with compilation URL ''{1}''.", ejbURL, Arrays
                                .asList(compilationURLs));
                        invoke(this.checkGenICMethod, this.ejb21Service, ejbURL.getFile(), compilationURLs);
                    }
                }


                // Deploy EJB 2.1 on JOnAS service
                Context ctx = new ContextImpl(earURL.toExternalForm());
                try {
                    ctx.rebind("earUrl", earURL);
                    ctx.rebind("earRootUrl", earURL);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the EAR URL parameter '" + earURL + "'", e);
                }

                try {
                    ctx.rebind("jarURLs", urls.toArray(new URL[urls.size()]));
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the urls parameter '" + urls + "'", e);
                }
                try {
                    ctx.rebind("earClassLoader", earClassLoader);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the earClassLoader parameter '" + earClassLoader + "'", e);
                }

                // Bind the EJB classloader
                try {
                    ctx.rebind("ejbClassLoader", ejbClassLoader);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the ejbClassLoader parameter '" + ejbClassLoader + "'", e);
                }

                // Role names
                try {
                    ctx.rebind("roleNames", new String[0]);
                } catch (NamingException e) {
                    throw new DeployerException("Cannot add the altDDs parameter.'", e);
                }

                try {
                    this.deployMethodejb21Service.invoke(this.ejb21Service, ctx);
                } catch (IllegalArgumentException e) {
                    throw new DeployerException("Cannot deploy the EJB 2.1'", e);
                } catch (IllegalAccessException e) {
                    throw new DeployerException("Cannot deploy the EJB 2.1'", e);
                } catch (InvocationTargetException e) {
                    throw new DeployerException("Cannot deploy the EJB 2.1'", e.getTargetException());
                }
            }
        }

    }

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

    /**
     * Link policy configuration objects of EJB and Web Component.
     * @param earDeployable the EAR that contains the EJB files
     * @throws DeployerException if the policy objects can't be linked
     */
    private void linkPolicyObjects(final EARDeployable earDeployable) throws DeployerException {

        // Add context ID of EJB and Web components
        List<String> ctxIDs = new LinkedList<String>();
        // Get contextID of EJB
        addEjbContextIdToList(earDeployable, ctxIDs, false);

        // Now for WebApp
        addWebBContextIdToList(earDeployable, ctxIDs, true);

        try {
            // Now link the policy configuration objects
            for (Iterator itCtxId = ctxIDs.iterator(); itCtxId.hasNext();) {
                String toBeLinkedCtxId = (String) itCtxId.next();
                PolicyConfiguration toBeLinkedPC = getPolicyConfigurationFactory().getPolicyConfiguration(toBeLinkedCtxId, false);
                for (Iterator linkCId = ctxIDs.iterator(); linkCId.hasNext();) {
                    String linkedCtxId = (String) linkCId.next();
                    if (!toBeLinkedCtxId.equals(linkedCtxId)) {
                        PolicyConfiguration linkedPC = getPolicyConfigurationFactory().getPolicyConfiguration(linkedCtxId, false);
                        toBeLinkedPC.linkConfiguration(linkedPC);
                    }
                }
            }
        } catch (PolicyContextException pce) {
            throw new DeployerException("Cannot retrieve a policy configuration", pce);
        }

    }

    /**
     * Add context-id for given jar urls to a given List.
     * @param earDeployable the EAR deployable to analyze
     * @param contextIDs the list of context-id.
     * @param resetPolicyConfiguration reset or not the associated policy
     *        configuration.
     * @throws DeployerException if the EAR can't be analyzed
     */
    private void addEjbContextIdToList(final EARDeployable earDeployable, final List<String> contextIDs,
            final boolean resetPolicyConfiguration) throws DeployerException {
        // Extract URLs of EJB from the EAR
        List<EJBDeployable<?>> ejbDeployables = earDeployable.getEJBDeployables();
        List<URL> urls = new ArrayList<URL>();
        if (ejbDeployables != null) {
            for (EJBDeployable ejbDeployable : ejbDeployables) {
                try {
                    urls.add(ejbDeployable.getArchive().getURL());
                } catch (ArchiveException e) {
                    throw new DeployerException("Cannot get URL on the deployable '" + ejbDeployable + "'.", e);
                }
            }
        }

        URL[] jarUrls = urls.toArray(new URL[urls.size()]);

        // Get contextID of EJB
        for (int u = 0; u < jarUrls.length; u++) {
            String ctxId = jarUrls[u].getPath();
            // reset the policy configuration associated to this context ID.
            if (resetPolicyConfiguration) {
                try {
                    getPolicyConfigurationFactory().getPolicyConfiguration(ctxId, true);
                } catch (PolicyContextException pce) {
                    throw new DeployerException("Cannot retrieve a policy configuration", pce);
                }
            }
            contextIDs.add(ctxId);
        }
    }

    /**
     * Add context-id for given web urls to a given List. Also, reset the
     * context-id associated to it. *
     * @param earDeployable the EAR deployable to analyze
     * @param contextIDs the list of context-id.
     * @param resetPolicyConfiguration reset or not the associated policy
     *        configuration.
     * @throws DeployerException if policy context cannot be get.
     */
    private void addWebBContextIdToList(final EARDeployable earDeployable, final List<String> contextIDs,
            final boolean resetPolicyConfiguration) throws DeployerException {

        // Extract URLs of Web from the EAR
        List<WARDeployable> warDeployables = earDeployable.getWARDeployables();
        if (warDeployables != null) {
            for (WARDeployable warDeployable : warDeployables) {
                URL warURL = null;
                try {
                    warURL = warDeployable.getArchive().getURL();
                } catch (ArchiveException e) {
                    throw new DeployerException("Cannot get URL on the deployable '" + warDeployable + "'.", e);
                }

                // build context ID of war
                String ctxId = warURL.getFile() + warDeployable.getContextRoot();
                // reset the policy configuration associated to this context ID.
                if (resetPolicyConfiguration) {
                    try {
                        getPolicyConfigurationFactory().getPolicyConfiguration(ctxId, true);
                    } catch (PolicyContextException pce) {
                        throw new DeployerException("Cannot retrieve a policy configuration", pce);
                    }
                }
                contextIDs.add(ctxId);
            }
        }
    }

    /**
     * Commit policy configuration objects of EJB Component.
     * @param earDeployable the EAR to analyze
     * @throws DeployerException if the policy objects can't be committed
     */
    private void commitEJBPolicyObjects(final EARDeployable earDeployable) throws DeployerException {
        List<String> ctxIDs = new LinkedList<String>();
        addEjbContextIdToList(earDeployable, ctxIDs, false);
        commitPolicyObjects(ctxIDs);
    }

    /**
     * Commit policy configuration objects of Web Component.
     * @param earDeployable the EAR to analyze
     * @throws DeployerException if the policy objects can't be committed
     */
    private void commitWebBPolicyObjects(final EARDeployable earDeployable) throws DeployerException {
        List<String> ctxIDs = new LinkedList<String>();
        addWebBContextIdToList(earDeployable, ctxIDs, false);
        commitPolicyObjects(ctxIDs);
    }

    /**
     * @return policy configuration factory
     * @throws DeployerException if the policy configuration factory cannot
     *         be obtain
     */
    private PolicyConfigurationFactory getPolicyConfigurationFactory() throws DeployerException {
        PolicyConfigurationFactory pcFactory = null;
        try {
            pcFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
        } catch (Exception cnfe) {
            throw new DeployerException("Cannot retrieve current policy configuration factory", cnfe);
        }
        return pcFactory;
    }

    /**
     * Commit policy context IDs of the given list.
     * @param ctxIDs list of context ID to commit.
     * @throws DeployerException if the policy objects cannot be committed.
     */
    private void commitPolicyObjects(final List ctxIDs) throws DeployerException {
        String ctxId = null;
        try {
            // commit the policy configuration objects
            for (Iterator itCtxId = ctxIDs.iterator(); itCtxId.hasNext();) {
                ctxId = (String) itCtxId.next();
                PolicyConfiguration pc = getPolicyConfigurationFactory().getPolicyConfiguration(ctxId, false);
                pc.commit();
            }
        } catch (PolicyContextException pce) {
            throw new DeployerException("Cannot commit policy configuration with Id '" + ctxId + "'", pce);
        }

        // refresh policy
        Policy.getPolicy().refresh();
    }

}
TOP

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

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.