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