0001: /**
0002: * JOnAS: Java(TM) Open Application Server
0003: * Copyright (C) 1999-2006 Bull S.A.S.
0004: * Contact: jonas-team@objectweb.org
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation; either
0009: * version 2.1 of the License, or any later version.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU Lesser General Public
0017: * License along with this library; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
0019: * USA
0020: *
0021: * --------------------------------------------------------------------------
0022: * $Id: AbsJWebContainerServiceImpl.java 9681 2006-10-06 12:19:42Z benoitf $
0023: * --------------------------------------------------------------------------
0024: */package org.objectweb.jonas.web;
0025:
0026: import java.io.File;
0027: import java.io.IOException;
0028: import java.net.MalformedURLException;
0029: import java.net.URL;
0030: import java.net.URLClassLoader;
0031: import java.rmi.RemoteException;
0032: import java.util.ArrayList;
0033: import java.util.Enumeration;
0034: import java.util.HashSet;
0035: import java.util.Hashtable;
0036: import java.util.Iterator;
0037: import java.util.List;
0038: import java.util.Set;
0039: import java.util.StringTokenizer;
0040: import java.util.Vector;
0041:
0042: import javax.management.InstanceAlreadyExistsException;
0043: import javax.management.MBeanRegistrationException;
0044: import javax.management.MBeanServer;
0045: import javax.management.NotCompliantMBeanException;
0046: import javax.management.ObjectName;
0047: import javax.naming.Context;
0048: import javax.naming.LinkRef;
0049: import javax.naming.NamingException;
0050: import javax.naming.Reference;
0051: import javax.naming.StringRefAddr;
0052:
0053: import org.objectweb.jonas_lib.deployment.api.EjbLocalRefDesc;
0054: import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
0055: import org.objectweb.jonas_lib.deployment.api.EnvEntryDesc;
0056: import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
0057: import org.objectweb.jonas_lib.deployment.api.ResourceEnvRefDesc;
0058: import org.objectweb.jonas_lib.deployment.api.ResourceRefDesc;
0059: import org.objectweb.jonas_lib.files.WsGenChecker;
0060: import org.objectweb.jonas_lib.loader.SimpleWebappClassLoader;
0061: import org.objectweb.jonas_lib.loader.WebappClassLoader;
0062: import org.objectweb.jonas_lib.naming.ContainerNaming;
0063: import org.objectweb.jonas_lib.security.PermissionManagerException;
0064:
0065: import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
0066: import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDescException;
0067: import org.objectweb.jonas_web.deployment.lib.wrapper.WebManagerWrapper;
0068:
0069: import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
0070:
0071: import org.objectweb.jonas.common.JModule;
0072: import org.objectweb.jonas.common.JProp;
0073: import org.objectweb.jonas.common.Log;
0074: import org.objectweb.jonas.ear.EarServiceException;
0075: import org.objectweb.jonas.ear.EarServiceImpl;
0076: import org.objectweb.jonas.jmx.J2eeObjectName;
0077: import org.objectweb.jonas.jmx.JmxService;
0078: import org.objectweb.jonas.jmx.JonasObjectName;
0079: import org.objectweb.jonas.naming.CompNamingContext;
0080: import org.objectweb.jonas.naming.NamingManager;
0081: import org.objectweb.jonas.server.LoaderManager;
0082: import org.objectweb.jonas.service.AbsServiceImpl;
0083: import org.objectweb.jonas.service.ServiceException;
0084: import org.objectweb.jonas.service.ServiceManager;
0085: import org.objectweb.jonas.web.lib.JarTools;
0086: import org.objectweb.jonas.web.lib.PermissionManager;
0087: import org.objectweb.jonas.ws.JServiceFactory;
0088: import org.objectweb.jonas.ws.JServiceFactoryFinder;
0089: import org.objectweb.jonas.ws.WebServicesService;
0090:
0091: import org.objectweb.util.monolog.api.BasicLevel;
0092: import org.objectweb.util.monolog.api.Logger;
0093:
0094: /**
0095: * This abstract class provides an implementation for a dynamic
0096: * JWebContainerService service.
0097: * @author Florent Benoit
0098: * @author Ludovic Bert (J2EE 1.3)
0099: * @author Nicolas Van Caneghem (exploded ear)
0100: * @author Michel-Ange Anton (contributor)
0101: */
0102: public abstract class AbsJWebContainerServiceImpl extends
0103: AbsServiceImpl implements JWebContainerService,
0104: AbsJWebContainerServiceImplMBean {
0105:
0106: /**
0107: * The name of the JONAS_BASE directory.
0108: */
0109: protected static final String JONAS_BASE = JProp.getJonasBase();
0110:
0111: /**
0112: * The name of the webapps directory.
0113: */
0114: protected static final String WEBAPPS_DIR = JONAS_BASE
0115: + File.separator + "webapps";
0116:
0117: /**
0118: * The name of the working directory.
0119: */
0120: protected static final String WORK_DIR = JProp.getWorkDir();
0121:
0122: /**
0123: * The name of the working apps directory.
0124: */
0125: protected static final String WORK_WEBAPPS_DIR = WORK_DIR
0126: + File.separator + "webapps";
0127:
0128: /**
0129: * The name of the property used in work directory for single webapps (not ear case).
0130: */
0131: protected static final String SINGLE_WORK_WEBAPPS_DIR_SUFFIX = "single";
0132:
0133: /**
0134: * The name of the property used in work directory for EAR webapps (in ear case).
0135: */
0136: protected static final String INEAR_WORK_WEBAPPS_DIR_SUFFIX = "ear";
0137:
0138: /**
0139: * Web service configuration properties : Files deployed
0140: */
0141: public static final String DESCRIPTORS = "jonas.service.web.descriptors";
0142:
0143: /**
0144: * Web service configuration properties : Autdeployed the files in these
0145: * directories
0146: */
0147: public static final String AUTOLOADDIR = "jonas.service.web.autoloaddir";
0148:
0149: /**
0150: * Web service configuration properties : Xml parsing with validation
0151: */
0152: public static final String PARSINGWITHVALIDATION = "jonas.service.web.parsingwithvalidation";
0153:
0154: /**
0155: * Length of the extension .war
0156: */
0157: private static final int WAR_EXTENSION_LENGTH = 4;
0158:
0159: /**
0160: * Web service configuration properties : Implementation of the web
0161: * container
0162: */
0163: public static final String CLASS = "jonas.service.web.class";
0164:
0165: /**
0166: * Logger for this service.
0167: */
0168: private static Logger logger = null;
0169:
0170: /**
0171: * The name of the current jonas server
0172: */
0173: private static String nameOfServer = null;
0174:
0175: /**
0176: * Reference on the NamingManager.
0177: */
0178: private ContainerNaming naming;
0179:
0180: /**
0181: * Associates an URL of an unpacked WAR file to its classloader.
0182: */
0183: private Hashtable warLoaders = new Hashtable();
0184:
0185: /**
0186: * Associates an URL of a deployed WAR file to its classloader.
0187: */
0188: private Hashtable warBindings = new Hashtable();
0189:
0190: /**
0191: * Reference to a MBean server.
0192: */
0193: private MBeanServer mbeanServer = null; // Bug Tomcat 5 doesn't remove MBean
0194: // WebModule, normally the type is
0195: // "private"
0196:
0197: /**
0198: * List of the war names to load when starting the Web container Service.
0199: */
0200: private Vector warNames = new Vector();
0201:
0202: /**
0203: * List of the war deployed by the Web container Service.
0204: */
0205: private Vector warDeployed = new Vector();
0206:
0207: /**
0208: * List of autoloaded directories.
0209: */
0210: private List autoloadDirectories = new ArrayList();
0211:
0212: /**
0213: * Name of the server
0214: */
0215: private String serverName = null;
0216:
0217: /**
0218: * Version of the server
0219: */
0220: private String serverVersion = null;
0221:
0222: /**
0223: * Reference to the WebServices service
0224: */
0225: private WebServicesService wsService = null;
0226:
0227: /**
0228: * Application Classloader
0229: */
0230: private ClassLoader appsClassLoader;
0231:
0232: /**
0233: * Initialize the service.
0234: * @param ctx the configuration context of the service.
0235: * @throws ServiceException if the initialization failed.
0236: */
0237: protected void doInit(Context ctx) throws ServiceException {
0238:
0239: // Init the logger
0240: logger = Log.getLogger(Log.JONAS_WEB_PREFIX);
0241:
0242: // get apps ClassLoader
0243: try {
0244: LoaderManager lm = LoaderManager.getInstance();
0245: appsClassLoader = lm.getAppsLoader();
0246: } catch (Exception e) {
0247: logger.log(BasicLevel.ERROR,
0248: "Cannot get the Applications ClassLoader from Web Container Service: "
0249: + e);
0250: throw new ServiceException(
0251: "Cannot get the Applications ClassLoader from Web Container Service",
0252: e);
0253: }
0254:
0255: ServiceManager sm = null;
0256: try {
0257: sm = ServiceManager.getInstance();
0258: } catch (Exception e) {
0259: String err = "Cannot get ServiceManager instance.";
0260: logger.log(BasicLevel.ERROR, err);
0261: throw new ServiceException(err, e);
0262: }
0263:
0264: // Get the JMX Server via JMX Service
0265: try {
0266: mbeanServer = ((JmxService) sm.getJmxService())
0267: .getJmxServer();
0268: } catch (ServiceException e) {
0269: // the JMX service may not be started
0270: mbeanServer = null;
0271: }
0272:
0273: // Get the WebServices service
0274: try {
0275: wsService = (WebServicesService) sm.getWebServicesService();
0276: } catch (ServiceException e) {
0277: if (logger.isLoggable(BasicLevel.DEBUG)) {
0278: logger.log(BasicLevel.DEBUG,
0279: "WebServices service not started");
0280: }
0281: //not started
0282: wsService = null;
0283: }
0284:
0285: // Set the XML parsing mode to no validation
0286: String parsingMode = "false";
0287: try {
0288: parsingMode = (String) ctx.lookup(PARSINGWITHVALIDATION);
0289: } catch (NamingException e) {
0290: if (logger.isLoggable(BasicLevel.DEBUG)) {
0291: logger.log(BasicLevel.DEBUG,
0292: "No value for parsingWithValidation");
0293: }
0294: // No problem if there is no value for 'parsingwithvalidation'
0295: // (false by default)
0296: }
0297:
0298: WebManagerWrapper.setParsingWithValidation("true"
0299: .equalsIgnoreCase(parsingMode));
0300: if (logger.isLoggable(BasicLevel.DEBUG)) {
0301: if ("false".equalsIgnoreCase(parsingMode)) {
0302: logger.log(BasicLevel.DEBUG,
0303: "Web XML parsing without validation");
0304: } else {
0305: logger.log(BasicLevel.DEBUG,
0306: "Web XML parsing with validation");
0307: }
0308: }
0309:
0310: // Init the war names to be loaded when starting
0311: String descsValue = null;
0312: try {
0313: descsValue = (String) ctx.lookup(DESCRIPTORS);
0314: } catch (NamingException e) {
0315: if (logger.isLoggable(BasicLevel.DEBUG)) {
0316: logger.log(BasicLevel.DEBUG, "No " + DESCRIPTORS);
0317: }
0318: }
0319: if (descsValue != null) {
0320: StringTokenizer st = new StringTokenizer(descsValue, ",");
0321: while (st.hasMoreTokens()) {
0322: String fileName = st.nextToken().trim();
0323: warNames.add(fileName);
0324: }
0325: }
0326: // Add the wars of the jonas.service.web.autoloaddir property
0327: String dirValue = null;
0328: ArrayList autoDirs = new ArrayList();
0329: try {
0330: dirValue = (String) ctx.lookup(AUTOLOADDIR);
0331: } catch (NamingException e) {
0332: if (logger.isLoggable(BasicLevel.DEBUG)) {
0333: logger.log(BasicLevel.DEBUG, "No " + AUTOLOADDIR);
0334: }
0335: }
0336: if (dirValue != null) {
0337: StringTokenizer st = new StringTokenizer(dirValue, ",");
0338: while (st.hasMoreTokens()) {
0339: String dirName = st.nextToken().trim();
0340: addWars(dirName);
0341: autoDirs.add(dirName);
0342: }
0343: }
0344: // Build autoload directories
0345: File oFile;
0346: Iterator it = autoDirs.iterator();
0347: while (it.hasNext()) {
0348: String dirName = (String) it.next();
0349: try {
0350: oFile = new File(WEBAPPS_DIR, dirName);
0351: if (!oFile.exists()) {
0352: oFile = new File(dirName);
0353: }
0354: if (oFile.exists()) {
0355: autoloadDirectories.add(oFile.getCanonicalPath());
0356: }
0357: } catch (Exception e) {
0358: String err = "Error when trying to verify Webapps autoload directory : "
0359: + dirName;
0360: logger
0361: .log(BasicLevel.ERROR, err + " "
0362: + e.getMessage());
0363: }
0364: }
0365:
0366: //Init the naming manager
0367: try {
0368: naming = NamingManager.getInstance();
0369: } catch (NamingException e) {
0370: throw new ServiceException(
0371: "Error when getting the reference to the Naming manager");
0372: }
0373:
0374: JProp jp = null;
0375: try {
0376: jp = JProp.getInstance();
0377: } catch (Exception e) {
0378: String err = "Error when trying to get jonas name ";
0379: logger.log(BasicLevel.ERROR, err + " " + e.getMessage());
0380: throw new ServiceException(err, e);
0381: }
0382: AbsJWebContainerServiceImpl.nameOfServer = jp.getValue(
0383: "jonas.name", "jonas");
0384:
0385: }
0386:
0387: /**
0388: * Start the service.
0389: * @throws ServiceException if the startup failed.
0390: */
0391: protected void doStart() throws ServiceException {
0392: // Deploy all wars which are in descriptors section
0393: for (Enumeration e = warNames.elements(); e.hasMoreElements();) {
0394: String fileName = (String) e.nextElement();
0395:
0396: URL warURL = checkWarFile(fileName);
0397:
0398: Context contctx = null;
0399: try {
0400: contctx = new CompNamingContext(fileName);
0401: contctx.rebind("warURL", warURL);
0402: // No context root to rebind because not in ear case.
0403: // => no rebind("contextRoot", ...)
0404: } catch (NamingException ne) {
0405: String err = "Cannot start the WebContainerService";
0406: throw new ServiceException(err, ne);
0407: }
0408: try {
0409: registerWar(contctx);
0410: } catch (JWebContainerServiceException jwcse) {
0411: String err = "Cannot deploy the file '" + warURL
0412: + "' : " + jwcse.getMessage();
0413: logger.log(BasicLevel.WARN, err);
0414: }
0415: }
0416:
0417: try {
0418: // Register JWebContainerService MBean :
0419: // JWebContainerServiceImplMBean
0420: if (mbeanServer != null) {
0421: mbeanServer.registerMBean(this , JonasObjectName
0422: .webContainerService());
0423: }
0424: } catch (InstanceAlreadyExistsException iae) {
0425: String err = "Cannot start the WebContainerService Already Exists";
0426: throw new ServiceException(err, iae);
0427: } catch (MBeanRegistrationException mbre) {
0428: throw new ServiceException(
0429: "Cannot start the WebContainerService (MBean registration error)",
0430: mbre);
0431: } catch (NotCompliantMBeanException ncmbe) {
0432: throw new ServiceException(
0433: "Cannot start the WebContainerService (MBean Not compliant error)",
0434: ncmbe);
0435: }
0436: }
0437:
0438: /**
0439: * Stop the service.
0440: * @throws ServiceException if the stop failed.
0441: */
0442: protected void doStop() throws ServiceException {
0443:
0444: // Get all the deployed war which are not in an ear application file
0445: // and undeploy them.
0446: for (int i = warDeployed.size() - 1; i >= 0; i--) {
0447: War war = (War) warDeployed.elementAt(i);
0448: URL warURL = war.getWarURL();
0449: String fileName = warURL.getFile();
0450: try {
0451: // Test if the war is in an ear application.
0452: if (!war.isInEarCase()) {
0453: Context ctx = new CompNamingContext(fileName);
0454: ctx.rebind("warURL", warURL);
0455: ctx.rebind("isEarCase", new Boolean(false));
0456: unRegisterWar(ctx);
0457: }
0458: } catch (Exception e) {
0459: //We don't stop the process of undeploying the wars.
0460: //We only display an error in the logger.
0461: String err = "Error when undeploying the war :"
0462: + fileName;
0463: logger.log(BasicLevel.ERROR, err + e.getMessage());
0464: }
0465: }
0466:
0467: if (mbeanServer != null) {
0468: try {
0469: // unregister AbsJWebContainerServiceImpl MBean
0470: mbeanServer.unregisterMBean(JonasObjectName
0471: .webContainerService());
0472: } catch (Exception e) {
0473: logger.log(BasicLevel.ERROR,
0474: "Cannot stop the WebContainerService: " + e);
0475: }
0476: }
0477: if (logger.isLoggable(BasicLevel.DEBUG)) {
0478: logger.log(BasicLevel.DEBUG, "WebContainerService stopped");
0479: }
0480: }
0481:
0482: /**
0483: * Create the environment and delegate the operation to the implementation
0484: * of the web container.
0485: * @param ctx the context which contains the configuration in order to
0486: * deploy a WAR.
0487: * @throws JWebContainerServiceException if the registration of the WAR
0488: * failed.
0489: */
0490: protected abstract void doRegisterWar(Context ctx)
0491: throws JWebContainerServiceException;
0492:
0493: /**
0494: * Delegate the unregistration to the implementation of the web container.
0495: * @param ctx the context which contains the configuration in order to
0496: * undeploy a WAR.
0497: * @throws JWebContainerServiceException if the unregistration failed.
0498: */
0499: protected abstract void doUnRegisterWar(Context ctx)
0500: throws JWebContainerServiceException;
0501:
0502: /**
0503: * Return the URL where warURL has been unpacked.
0504: * @param warURL the URL of the war
0505: * @param earAppName EAR Application name (can be null if not in EAR case)
0506: * @return the URL where warURL has been unpacked.
0507: * @throws JWebContainerServiceException when it is impossible to retrieve
0508: * the unpacked URL.
0509: */
0510: protected URL getUnpackDir(URL warURL, String earAppName)
0511: throws JWebContainerServiceException {
0512:
0513: String destDir = WORK_WEBAPPS_DIR + File.separator
0514: + nameOfServer + File.separator;
0515:
0516: // Two cases :
0517: // war is alone --> unpack it in :
0518: // WEBAPPS_DIR/servername/filename_without_extension_dir/
0519: // war come from an ear --> unpack it in :
0520: // WEBAPPS_DIR/servername/ear_AppName/filename_without_extension_dir/
0521:
0522: // location of unpacked War
0523: URL unpackedWarURL = null;
0524:
0525: String fileName = warURL.getFile();
0526:
0527: // War file
0528: if (new File(fileName).isFile()) {
0529: // Note : if the war is alone, earAppName is null.
0530: // ear case
0531: if (earAppName != null) {
0532: destDir += INEAR_WORK_WEBAPPS_DIR_SUFFIX
0533: + File.separator + earAppName + File.separator;
0534: } else {
0535: destDir += SINGLE_WORK_WEBAPPS_DIR_SUFFIX
0536: + File.separator;
0537: }
0538:
0539: String fTemp = new File(fileName).getName();
0540: destDir += fTemp.substring(0, fTemp.length()
0541: - WAR_EXTENSION_LENGTH);
0542:
0543: // Unpack the war into a directory
0544: JarTools.unpack(fileName, destDir);
0545: } else {
0546: // Directory (No unpack)
0547: destDir = fileName;
0548: }
0549:
0550: try {
0551: unpackedWarURL = new File(destDir).toURL();
0552: } catch (MalformedURLException mue) {
0553: throw new JWebContainerServiceException("Error", mue);
0554: }
0555:
0556: return unpackedWarURL;
0557:
0558: }
0559:
0560: /**
0561: * Return the class loader of the given warURL. Unpack the associated war
0562: * and build the loader if it's not in the cache.
0563: * @param warURL the url of the war we want to get the loader
0564: * @param earAppName the name of the ear application containing the war. May
0565: * be null in non ear case.
0566: * @param parentLoader the ejb class loader of the ear. May be null in non
0567: * ear case.
0568: * @return the class loader of the given warURL.
0569: * @throws JWebContainerServiceException if the process failed.
0570: */
0571: public URLClassLoader getClassLoader(URL warURL, String earAppName,
0572: ClassLoader parentLoader)
0573: throws JWebContainerServiceException {
0574:
0575: URLClassLoader loaderForCls = null;
0576: try {
0577: WebLoaderHolder holder = (WebLoaderHolder) warLoaders
0578: .get(warURL);
0579: if (holder != null) {
0580: loaderForCls = holder.getJonasWebLoader();
0581: }
0582: } catch (Exception e) {
0583: throw new JWebContainerServiceException(
0584: "Error when getting '" + warURL + "' in cache", e);
0585: }
0586:
0587: if (loaderForCls == null) {
0588: // the war is not already used
0589:
0590: // Use the unpacked directory
0591: URL unpackedWarURL = getUnpackDir(warURL, earAppName);
0592:
0593: try {
0594: if (parentLoader != null) {
0595: // ear case.
0596: loaderForCls = new WebappClassLoader(
0597: unpackedWarURL, parentLoader);
0598: } else {
0599: //Case of non-ear application : only a single war
0600: loaderForCls = new WebappClassLoader(
0601: unpackedWarURL, appsClassLoader);
0602: }
0603: } catch (IOException ioe) {
0604: throw new JWebContainerServiceException(
0605: "Cannot create WebAppClassLoader from '"
0606: + unpackedWarURL + "'", ioe);
0607: }
0608:
0609: // add the class loader in cache.
0610: try {
0611: WebLoaderHolder holder = new WebLoaderHolder(
0612: loaderForCls, null);
0613: warLoaders.put(warURL, holder);
0614: } catch (Exception e) {
0615: throw new JWebContainerServiceException(
0616: "Error when adding '" + warURL + "' in cache",
0617: e);
0618: }
0619: }
0620:
0621: return loaderForCls;
0622:
0623: }
0624:
0625: /**
0626: * @param warURL the URL of the webapp
0627: * @return Returns the ClassLoader used to link a JNDI environnment to a webapp
0628: */
0629: public ClassLoader getContextLinkedClassLoader(URL warURL) {
0630: WebLoaderHolder holder = (WebLoaderHolder) warLoaders
0631: .get(warURL);
0632: if (holder != null) {
0633: return holder.getEnvWebLoader();
0634: }
0635: return null;
0636: }
0637:
0638: /**
0639: * Create the environment and delegate the operation to the implementation
0640: * of the web container.
0641: * @param ctx the context which contains the configuration in order to
0642: * deploy a WAR.
0643: * @throws JWebContainerServiceException if the registration of the WAR
0644: * failed.
0645: */
0646: private void registerWar(Context ctx)
0647: throws JWebContainerServiceException {
0648: // There are 6 possible parameters :
0649: // - warURL is the URL of the war to deploy (required param).
0650: // - parentClassLoader is the parent classloader of
0651: // the web classloader (optional param).
0652: // - earClassLoader is the ear classloader (optional param).
0653: // - earURL is the URL of the ear (optional parameter :
0654: // if earURL is set it means that we are in the ear case, else it
0655: // means that we are in the non ear case).
0656: // - altDD is the optional deployment descriptor (optional param).
0657: // - contextRoot is the context root for the Web application
0658: // (optional param).
0659:
0660: // Get the URL of the ear application file in the case of an
0661: // ear application, null otherwise.
0662: URL earURL = null;
0663: String contextRoot = null;
0664: String earAppName = null;
0665: try {
0666: earURL = (URL) ctx.lookup("earURL");
0667: contextRoot = (String) ctx.lookup("contextRoot");
0668: earAppName = EarServiceImpl
0669: .buildJ2eeApplicationName(earURL);
0670: } catch (NamingException e) {
0671: if (earURL != null || contextRoot != null) {
0672: String err = "Error while getting parameter from context param :"
0673: + e.getMessage();
0674: logger.log(BasicLevel.ERROR, err);
0675: throw new JWebContainerServiceException(err, e);
0676: } // else nothing to do : non-ear case.
0677: }
0678:
0679: // Get the URL of the war to deploy ...
0680: URL warURL = null;
0681: try {
0682: warURL = (URL) ctx.lookup("warURL");
0683: } catch (NamingException e) {
0684: String err = "Error while getting parameter from context param :"
0685: + e.getMessage();
0686: logger.log(BasicLevel.ERROR, err);
0687: throw new JWebContainerServiceException(err, e);
0688: }
0689:
0690: // ... and check if the war to deploy exists.
0691: File warFile = new File(warURL.getFile());
0692: if (!warFile.exists()) {
0693: String err = "registerWar: '" + warFile.getPath()
0694: + "' not found";
0695: logger.log(BasicLevel.ERROR, err);
0696: throw new JWebContainerServiceException(err);
0697: }
0698:
0699: // Check if the war to deploy is not already deployed.
0700: War war = getWar(warURL);
0701: if (war != null) {
0702: // The war is already deployed.
0703: String err = "Cannot deploy war '"
0704: + warURL.getFile()
0705: + "' is already deployed."
0706: + " You must undeploy the war before a new deployment.";
0707: throw new JWebContainerServiceException(err);
0708: }
0709:
0710: URLClassLoader parentLoader = null;
0711: URLClassLoader earClassLoader = null;
0712: boolean isInEar = true;
0713: try {
0714: parentLoader = (URLClassLoader) ctx
0715: .lookup("parentClassLoader");
0716: earClassLoader = (URLClassLoader) ctx
0717: .lookup("earClassLoader");
0718: } catch (NamingException ne) {
0719: if (logger.isLoggable(BasicLevel.DEBUG)) {
0720: logger.log(BasicLevel.DEBUG, "Not an ear case");
0721: }
0722: isInEar = false;
0723: // exception occurs when the earClassLoader is not found.
0724: }
0725:
0726: // Check WsGen for webapp outside of an Ear
0727: //-----------------------------------------
0728:
0729: if (!isInEar) {
0730: try {
0731: ObjectName j2eeServer = J2eeObjectName.J2EEServer(this
0732: .getDomainName(), this .getJonasServerName());
0733: WsGenChecker wsgc = new WsGenChecker(this .mbeanServer,
0734: warFile.getCanonicalPath(), j2eeServer);
0735: wsgc.checkWsGen();
0736: } catch (Exception e) {
0737: throw new EarServiceException(
0738: "Cannot apply WsGen on the war : " + warFile, e);
0739: }
0740: }
0741:
0742: //------------------------------------------
0743:
0744: // get the war class loader.
0745: URLClassLoader loaderForCls = getClassLoader(warURL,
0746: earAppName, parentLoader);
0747:
0748: // get the directory where the war have been unpacked
0749: URL unpackedWarURL = getUnpackDir(warURL, earAppName);
0750:
0751: // Only if the WebServicesService is started
0752: // And in non EAR case
0753: if (wsService != null && earClassLoader == null) {
0754: try {
0755: CompNamingContext contctx = null;
0756: try {
0757: contctx = new CompNamingContext(unpackedWarURL
0758: .getFile());
0759: contctx.rebind("unpackDir", unpackedWarURL
0760: .toExternalForm());
0761: contctx.rebind("jarUrls", new URL[0]);
0762: contctx.rebind("warUrls", new URL[] { warURL });
0763: if (parentLoader != null) {
0764: contctx.rebind("ejbClassLoader", parentLoader);
0765: }
0766: } catch (NamingException e) {
0767: String err = "Can not bind params for the WebServices service, "
0768: + "Can't deploy Web Services Endpoint";
0769: throw new JWebContainerServiceException(err, e);
0770: }
0771: wsService.deployWebServices(contctx);
0772: } catch (ServiceException se) {
0773: String err = "Error during the deployment of the WebServices of the War file '"
0774: + warURL + "'";
0775: logger.log(BasicLevel.ERROR, err + " : "
0776: + se.getMessage());
0777: throw new JWebContainerServiceException(err, se);
0778: }
0779: }
0780:
0781: // Get the deployment descriptor from file
0782: WebContainerDeploymentDesc webDD = null;
0783: try {
0784: webDD = WebManagerWrapper.getDeploymentDesc(warURL,
0785: loaderForCls, earClassLoader);
0786: } catch (WebContainerDeploymentDescException e) {
0787: String err = "Cannot read the deployment descriptors '"
0788: + warURL.getFile() + "'";
0789: logger.log(BasicLevel.ERROR, err + ": " + e);
0790: e.printStackTrace(System.err);
0791: throw new JWebContainerServiceException(err, e);
0792: }
0793:
0794: // Populate the java:comp/env (ENC) environment.
0795: URLClassLoader webClassLoader = null;
0796: try {
0797: if (logger.isLoggable(BasicLevel.DEBUG)) {
0798: logger.log(BasicLevel.DEBUG,
0799: "Populating environment of the file "
0800: + warURL.getFile());
0801: }
0802: Context ctxParam = new CompNamingContext(unpackedWarURL
0803: .getFile());
0804: ctxParam.rebind("DeploymentDesc", webDD);
0805: ctxParam.rebind("warName", unpackedWarURL.getFile());
0806: if (parentLoader == null) {
0807: webClassLoader = new SimpleWebappClassLoader(
0808: unpackedWarURL, appsClassLoader);
0809: } else {
0810: webClassLoader = new SimpleWebappClassLoader(
0811: unpackedWarURL, parentLoader);
0812: }
0813: ctxParam.rebind("parentCL", webClassLoader);
0814: // Do the populating of the java:comp/env (ENC) environment.
0815: setWebEnvironment(ctxParam);
0816: } catch (Exception e) {
0817: //populating environment failed.
0818: String err = "Error when populating ";
0819: logger.log(BasicLevel.ERROR, err + e.getMessage());
0820: throw new JWebContainerServiceException(err, e);
0821: }
0822:
0823: // TODO maybe to be removed ?
0824: WebLoaderHolder holder = (WebLoaderHolder) warLoaders
0825: .get(warURL);
0826: holder.setEnvWebLoader(webClassLoader);
0827:
0828: // Set the right context root for the web application, the priority is
0829: // the following :
0830: // 1 - context-root of application.xml
0831: // 2 - context-root of jonas-web.xml
0832: // 3 - context-root is the name of the file without .war.
0833: if (earClassLoader == null && contextRoot == null) {
0834: String cRoot = webDD.getContextRoot();
0835: if (cRoot == null) {
0836: String file = new File(unpackedWarURL.getFile())
0837: .getName();
0838: if (file.toLowerCase().endsWith(".war")) {
0839: contextRoot = file.substring(0, file.length()
0840: - WAR_EXTENSION_LENGTH);
0841: } else {
0842: //It's a directory which is deployed
0843: contextRoot = file.substring(0, file.length());
0844: }
0845: } else {
0846: contextRoot = cRoot;
0847: }
0848: }
0849:
0850: // ensure context-root is valid (remove starting /)
0851: if (contextRoot.startsWith("/") && !contextRoot.equals("/")) {
0852: logger
0853: .log(
0854: BasicLevel.WARN,
0855: "Context-Root '"
0856: + contextRoot
0857: + "' contains invalid starting / in the name. Fixing it.");
0858: int c = 0;
0859: while (contextRoot.charAt(c) == '/') {
0860: c++;
0861: }
0862: contextRoot = contextRoot.substring(c);
0863: }
0864:
0865: // Set the name of the host where to deploy the war if it is
0866: // specified in the jonas-web.xml.
0867: String hostName = webDD.getHost();
0868:
0869: // Check if the context to deploy is not already deployed.
0870: List deployedWars = getWar(contextRoot);
0871: for (Iterator itDeployed = deployedWars.iterator(); itDeployed
0872: .hasNext();) {
0873: War deployedWar = (War) itDeployed.next();
0874: String hostDeployed = deployedWar.getHostName();
0875: if ((hostDeployed == null && hostName == null)
0876: || (hostDeployed != null && hostDeployed
0877: .equals(hostName))) {
0878: // The war is already deployed.
0879: String err = "Cannot deploy war '"
0880: + warURL.getFile()
0881: + "' is already deployed with the context '"
0882: + contextRoot
0883: + "'."
0884: + " You must undeploy the war before a new deployment.";
0885: throw new JWebContainerServiceException(err);
0886: }
0887: }
0888:
0889: // Context classloader must follow the java2 delegation model ?
0890: boolean java2DelegationModel = webDD.getJava2DelegationModel();
0891:
0892: // Create War
0893: war = new War(warURL, earURL, hostName, contextRoot,
0894: java2DelegationModel, webDD.getXmlContent(), webDD
0895: .getJOnASXmlContent(), webDD.getServletsName());
0896:
0897: // Configure JACC
0898: PermissionManager permissionManager = null;
0899: try {
0900: boolean removePContext = true;
0901: // Policy context is already existing (created by ear service), no need to remove it
0902: if (earClassLoader != null) {
0903: removePContext = false;
0904: }
0905: permissionManager = new PermissionManager(webDD, war
0906: .getContextId(), removePContext);
0907: permissionManager.translateServletDeploymentDescriptor();
0908: // if not in ear case, commit the policy configuration, else it is done
0909: // by EAR service after linking all policy configuration objects
0910: if (earClassLoader == null) {
0911: permissionManager.commit();
0912: }
0913: } catch (Exception e) {
0914: e.printStackTrace();
0915: String err = "Cannot build permission manager object for the webapp '"
0916: + unpackedWarURL + "' : ";
0917: logger.log(BasicLevel.ERROR, err + e.getMessage());
0918: throw new JWebContainerServiceException(err, e);
0919: }
0920:
0921: // Configure the context to give to doRegisterWar ...
0922: Context ctxParam = null;
0923: try {
0924: ctxParam = new CompNamingContext(unpackedWarURL.getFile());
0925: ctxParam.rebind("warURL", warURL);
0926: if (earURL != null) {
0927: ctxParam.rebind("earURL", earURL);
0928: }
0929: ctxParam.rebind("unpackedWarURL", unpackedWarURL);
0930: ctxParam.rebind("parentCL", webClassLoader);
0931: if (hostName != null) {
0932: ctxParam.rebind("hostName", hostName);
0933: }
0934: ctxParam.rebind("contextRoot", contextRoot);
0935: if (earAppName != null) {
0936: ctxParam.rebind("earAppName", earAppName);
0937: }
0938: ctxParam.rebind("jonasDD", webDD.getJOnASXmlContent());
0939: ctxParam.rebind("java2DelegationModel", new Boolean(
0940: java2DelegationModel));
0941: ctxParam.rebind("permissionManager", permissionManager);
0942: } catch (NamingException e) {
0943: String err = "Error when deploying the war '"
0944: + unpackedWarURL.getFile() + "'";
0945: logger.log(BasicLevel.ERROR, err + e.getMessage());
0946: throw new JWebContainerServiceException(err, e);
0947: }
0948:
0949: war.setPermissionManager(permissionManager);
0950:
0951: // ... and delegate the registration of the war to the wrapper.
0952: doRegisterWar(ctxParam);
0953:
0954: // Finaly indicates that the war is deployed.
0955: warDeployed.addElement(war);
0956: warBindings.put(warURL, webClassLoader);
0957:
0958: try {
0959: // Register Ear MBean : EarMBean
0960: if (mbeanServer != null) {
0961: mbeanServer.registerMBean(war, JonasObjectName
0962: .war(warURL.getFile()));
0963: }
0964: } catch (Exception ware) {
0965: logger
0966: .log(BasicLevel.ERROR,
0967: "Can not register the MBean for the war"
0968: + unpackedWarURL + " :"
0969: + ware.getMessage());
0970: }
0971:
0972: // Complete the Deployment of the WebServices
0973: // Only if the WebServicesService is started
0974: // And in non EAR case
0975: if (wsService != null && earClassLoader == null) {
0976: try {
0977: CompNamingContext contctx = null;
0978: try {
0979: contctx = new CompNamingContext(unpackedWarURL
0980: .getFile());
0981: contctx.rebind(
0982: WebServicesService.CLASSLOADER_CTX_PARAM,
0983: loaderForCls);
0984: contctx
0985: .rebind(
0986: WebServicesService.PARENT_OBJECTNAME_CTX_PARAM,
0987: ctxParam.lookup("WebModule"));
0988: contctx.rebind(
0989: WebServicesService.ISINEAR_CTX_PARAM,
0990: Boolean.FALSE);
0991: } catch (NamingException e) {
0992: String err = "Can not bind params for the WebServices service, "
0993: + "can't complete deployment of Web Services Endpoints";
0994: throw new JWebContainerServiceException(err, e);
0995: }
0996: wsService.completeWSDeployment(contctx);
0997: } catch (ServiceException se) {
0998: String err = "Error during the deployment of the WebServices of the War file '"
0999: + warURL + "'";
1000: logger.log(BasicLevel.ERROR, err + " : "
1001: + se.getMessage());
1002: throw new JWebContainerServiceException(err, se);
1003: }
1004: }
1005:
1006: StringBuffer txtInfo = new StringBuffer("War "
1007: + warURL.getFile() + " available at the context ");
1008: if (!contextRoot.startsWith("/")) {
1009: txtInfo.append("/");
1010: }
1011: txtInfo.append(contextRoot);
1012:
1013: if (hostName != null) {
1014: txtInfo.append(" on the host ");
1015: txtInfo.append(hostName);
1016: }
1017: txtInfo.append(".");
1018: logger.log(BasicLevel.INFO, txtInfo.toString());
1019:
1020: // Remove the DD cache (WebServices)
1021: if (wsService != null && earClassLoader == null) {
1022: wsService.removeCache(loaderForCls);
1023: }
1024: }
1025:
1026: /**
1027: * Register a WAR by delegating the operation to the registerWar() method.
1028: * This is used for JMX management.
1029: * @param fileName the name of the war to deploy.
1030: * @throws RemoteException if rmi call failed.
1031: * @throws JWebContainerServiceException if the registration failed.
1032: */
1033: public void registerWarMBean(String fileName)
1034: throws RemoteException, JWebContainerServiceException {
1035: // convert the file name to the appropriate url and check if the file
1036: // exists.
1037: URL warURL = checkWarFile(fileName);
1038:
1039: // create the context to call the registerWar method.
1040: Context ctx = null;
1041: try {
1042: ctx = new CompNamingContext(fileName);
1043: ctx.rebind("warURL", warURL);
1044: } catch (NamingException e) {
1045: String err = "Error when deploying the war '" + fileName
1046: + "'";
1047: logger.log(BasicLevel.ERROR, err + e.getMessage());
1048: throw new JWebContainerServiceException(err, e);
1049: }
1050:
1051: // call the registerWar method.
1052: registerWar(ctx);
1053: }
1054:
1055: /**
1056: * Set the environment of the web container inside the given context.
1057: * @param ctxParam the java:comp/env/ environment where is stored the values
1058: * of the web container environment.
1059: * @throws JWebContainerServiceException if the populating of the
1060: * environment failed.
1061: */
1062: private void setWebEnvironment(Context ctxParam)
1063: throws JWebContainerServiceException {
1064:
1065: WebContainerDeploymentDesc dd = null;
1066: String warName = null;
1067: ClassLoader parentClassLoader = null;
1068:
1069: /*
1070: * get the parameters - Deployment desc of xml - Name of the war -
1071: * Parent Class loader
1072: */
1073: try {
1074: dd = (WebContainerDeploymentDesc) ctxParam
1075: .lookup("DeploymentDesc");
1076: warName = (String) ctxParam.lookup("warName");
1077: } catch (NamingException e) {
1078: String err = "Error while getting parameter from context param ";
1079: logger.log(BasicLevel.ERROR, err + e.getMessage());
1080: throw new JWebContainerServiceException(err, e);
1081: }
1082:
1083: //Get the parentCL
1084: try {
1085: parentClassLoader = (ClassLoader) ctxParam
1086: .lookup("parentCL");
1087: } catch (NamingException e) {
1088: String err = "Error while getting parameter from context param ";
1089: logger.log(BasicLevel.ERROR, err + e.getMessage());
1090: throw new JWebContainerServiceException(err, e);
1091: }
1092:
1093: //Create the java:comp/env entry and bind the entries
1094: try {
1095: // Create a JNDI context for this war java:comp/env
1096: Context javaCtx = naming.createEnvironmentContext(warName);
1097: naming.setComponentContext(javaCtx, parentClassLoader);
1098: Context envCtx = javaCtx.createSubcontext("comp/env");
1099:
1100: // War Environment entries
1101: EnvEntryDesc[] envt = dd.getEnvEntryDesc();
1102: for (int i = 0; i < envt.length; i++) {
1103: // get information in descriptor
1104: String name = envt[i].getName();
1105: Object obj = envt[i].getValue();
1106:
1107: // register object in JNDI
1108: if (logger.isLoggable(BasicLevel.DEBUG)) {
1109: logger
1110: .log(BasicLevel.DEBUG, warName
1111: + ": Binding object " + name
1112: + " -> " + obj);
1113: }
1114: envCtx.rebind(name, obj);
1115: }
1116:
1117: // Resource References
1118: ResourceRefDesc[] resref = dd.getResourceRefDesc();
1119: for (int i = 0; i < resref.length; i++) {
1120: // get information in descriptor
1121: String name = resref[i].getName();
1122: String type = resref[i].getTypeName();
1123: String resname = resref[i].getJndiName();
1124: // register object in JNDI
1125: if (logger.isLoggable(BasicLevel.DEBUG)) {
1126: logger.log(BasicLevel.DEBUG, warName
1127: + ": Linking resource " + name + " -> "
1128: + resname);
1129: }
1130:
1131: if (type.equalsIgnoreCase("java.net.URL")) {
1132: // Specify the factory to use with the right URL
1133: Reference ref = new Reference(
1134: "java.net.URL",
1135: "org.objectweb.jonas_lib.naming.factory.URLFactory",
1136: null);
1137: StringRefAddr refAddr = new StringRefAddr("url",
1138: resname);
1139: ref.add(refAddr);
1140: envCtx.rebind(name, ref);
1141: } else {
1142: // build the LinkRef that will be registered:
1143: // FactoryClassName = null, size = 1, refAddr = resname.
1144: LinkRef lref = new LinkRef(resname);
1145: envCtx.rebind(name, lref);
1146: }
1147: }
1148:
1149: // Resource Environment References
1150: ResourceEnvRefDesc[] resEnvref = dd.getResourceEnvRefDesc();
1151: for (int i = 0; i < resEnvref.length; i++) {
1152: // get information in descriptor
1153: String name = resEnvref[i].getName();
1154: String resname = resEnvref[i].getJndiName();
1155: LinkRef lref = new LinkRef(resname);
1156:
1157: if (logger.isLoggable(BasicLevel.DEBUG)) {
1158: logger.log(BasicLevel.DEBUG, warName
1159: + ": Linking resource environment " + name
1160: + " -> " + resname);
1161: }
1162: envCtx.rebind(name, lref);
1163: }
1164:
1165: // EJB References
1166: EjbRefDesc[] ejbref = dd.getEjbRefDesc();
1167: for (int i = 0; i < ejbref.length; i++) {
1168: // get information in descriptor
1169: String name = ejbref[i].getEjbRefName();
1170: String ejbname = null;
1171: ejbname = ejbref[i].getJndiName();
1172:
1173: LinkRef lref = new LinkRef(ejbname);
1174:
1175: if (logger.isLoggable(BasicLevel.DEBUG)) {
1176: logger.log(BasicLevel.DEBUG, warName
1177: + ": Linking ejb " + name + " -> "
1178: + ejbname);
1179: }
1180: envCtx.rebind(name, lref);
1181: }
1182:
1183: // EJB Local Refs
1184: // We use here ejb-link tag. This should be used also for
1185: // ejb-ref when we are able to manage references to
1186: // another jar file.
1187: EjbLocalRefDesc[] ejblocalref = dd.getEjbLocalRefDesc();
1188: for (int i = 0; i < ejblocalref.length; i++) {
1189: String name = ejblocalref[i].getEjbRefName();
1190: String ejbname = ejblocalref[i].getJndiLocalName();
1191: LinkRef lref = new LinkRef(ejbname);
1192: if (logger.isLoggable(BasicLevel.DEBUG)) {
1193: logger.log(BasicLevel.DEBUG, warName
1194: + ": Linking ejb " + name + " -> "
1195: + ejbname);
1196: }
1197: envCtx.rebind(name, lref);
1198: }
1199:
1200: // Message Destination References
1201: MessageDestinationRefDesc[] mdref = dd
1202: .getMessageDestinationRefDesc();
1203: for (int i = 0; i < mdref.length; i++) {
1204: // get information in descriptor
1205: String name = mdref[i].getMessageDestinationRefName();
1206: String mdname = null;
1207: mdname = mdref[i].getJndiName();
1208:
1209: LinkRef lref = new LinkRef(mdname);
1210:
1211: if (logger.isLoggable(BasicLevel.DEBUG)) {
1212: logger.log(BasicLevel.DEBUG, warName
1213: + ": Linking message-destination " + name
1214: + " -> " + mdname);
1215: }
1216: envCtx.rebind(name, lref);
1217: }
1218:
1219: // Service Ref
1220: // We bind a Reference when full configuration is provided
1221: // Otherwise we bind only a LinkRef in JNDI
1222:
1223: // get the JServiceFactory
1224: JServiceFactory factory = null;
1225:
1226: ServiceRefDesc[] serviceRefs = dd.getServiceRefDesc();
1227: for (int i = 0; i < serviceRefs.length; i++) {
1228:
1229: if (factory == null) {
1230: factory = JServiceFactoryFinder
1231: .getJOnASServiceFactory();
1232: }
1233:
1234: // Create the Service from the ServiceRef description
1235: String name = serviceRefs[i].getServiceRefName();
1236: // create a full Reference
1237: Reference ref = factory.getServiceReference(
1238: serviceRefs[i], parentClassLoader);
1239: envCtx.rebind(name, ref);
1240: if (logger.isLoggable(BasicLevel.DEBUG)) {
1241: logger.log(BasicLevel.DEBUG,
1242: "Adding service-ref 'java:comp/env/" + name
1243: + "'");
1244: }
1245: }
1246:
1247: } catch (NamingException e) {
1248: String err = "Error while populating environment of the war file "
1249: + warName;
1250: logger.log(BasicLevel.ERROR, err + " :" + e.getMessage());
1251: throw new JWebContainerServiceException(err, e);
1252: }
1253: }
1254:
1255: /**
1256: * Delegate the unregistration to the implementation of the web container
1257: * and delete the environment associated to the WAR file.
1258: * @param ctx the context which contains the configuration in order to
1259: * undeploy a WAR.
1260: * @throws JWebContainerServiceException if the unregistration failed.
1261: */
1262: private void unRegisterWar(Context ctx)
1263: throws JWebContainerServiceException {
1264:
1265: // Gets the 2 parameters :
1266: // warURL, isEarCase, hostName and contextRoot.
1267: URL warURL = null;
1268: boolean isEarCase = true;
1269: try {
1270: warURL = (URL) ctx.lookup("warURL");
1271: isEarCase = ((Boolean) ctx.lookup("isEarCase"))
1272: .booleanValue();
1273: } catch (NamingException e) {
1274: String err = "Error while getting parameter from context param.";
1275: logger.log(BasicLevel.ERROR, err + e.getMessage());
1276: throw new JWebContainerServiceException(err, e);
1277: }
1278:
1279: // get the file name for displaying message.
1280: String fileName = warURL.getFile();
1281:
1282: // Check if the war is deployed.
1283: War war = null;
1284: war = getWar(warURL);
1285: if (war == null) {
1286: String err = "Cannot undeploy war: '" + fileName
1287: + "' is not deployed.";
1288: logger.log(BasicLevel.ERROR, err);
1289: throw new JWebContainerServiceException(err);
1290: }
1291:
1292: // Check if the war can be undeployed (2 case authorized) :
1293: // - case EAR and war is in an EAR.
1294: // - case non EAR and war isn't in an EAR.
1295: if (isEarCase != war.isInEarCase()) {
1296: String err = "Cannot undeploy war: '"
1297: + fileName
1298: + "' it is in an ear application. You must undeploy the ear associated.";
1299: logger.log(BasicLevel.ERROR, err);
1300: throw new JWebContainerServiceException(err);
1301: }
1302:
1303: // Call the specific method of the implementation of the web container.
1304: try {
1305: String hostName = war.getHostName();
1306: if (hostName != null) {
1307: ctx.rebind("hostName", war.getHostName());
1308: }
1309: ctx.rebind("contextRoot", war.getContextRoot());
1310: ctx.rebind("webClassLoader", warBindings.get(warURL));
1311: } catch (NamingException e) {
1312: String err = "Error when undeploying the war '" + fileName
1313: + "'";
1314: logger.log(BasicLevel.ERROR, err + e.getMessage());
1315: throw new JWebContainerServiceException(err, e);
1316: }
1317:
1318: // Remove permission manager
1319: PermissionManager permissionManager = war
1320: .getPermissionManager();
1321: try {
1322: permissionManager.delete();
1323: permissionManager = null;
1324: } catch (PermissionManagerException pme) {
1325: logger.log(BasicLevel.ERROR,
1326: "Cannot remove permission manager for file '"
1327: + fileName + "'.", pme);
1328: }
1329:
1330: doUnRegisterWar(ctx);
1331:
1332: // undeploy webservices
1333: if (wsService != null) {
1334: wsService.undeployWebServices(ctx);
1335: }
1336:
1337: // Remove the context.
1338: URLClassLoader loader = (URLClassLoader) warBindings
1339: .remove(warURL);
1340: naming.unSetComponentContext(loader);
1341:
1342: // Remove classloader
1343: warLoaders.remove(warURL);
1344:
1345: // Indicates that the war is not in the deployed war.
1346: // (here we are sure that the war is not null and isn't in an ear).
1347: warDeployed.removeElement(war);
1348:
1349: //unregister mbean
1350: if (mbeanServer != null) {
1351: try {
1352: // unregister Ear MBean : EarMBean
1353: mbeanServer.unregisterMBean(JonasObjectName
1354: .war(fileName));
1355: } catch (Exception e) {
1356: logger.log(BasicLevel.ERROR,
1357: "Cannot remove the MBean for the war "
1358: + fileName + " : " + e.getMessage());
1359: }
1360: }
1361:
1362: logger.log(BasicLevel.INFO, "War " + fileName
1363: + " no longer available");
1364: }
1365:
1366: /**
1367: * Unregister a WAR by delegating the operation to the unRegisterWar()
1368: * method. This is used for JMX management.
1369: * @param fileName the name of the war to undeploy.
1370: * @throws RemoteException if rmi call failed.
1371: * @throws JWebContainerServiceException if the unregistration failed.
1372: */
1373: public void unRegisterWarMBean(String fileName)
1374: throws RemoteException, JWebContainerServiceException {
1375:
1376: // Convert the given file name to an url and check if the war is
1377: // deployed ...
1378: URL warURL = checkWarDeployed(fileName);
1379:
1380: // ... and do the undeployment.
1381: Context ctx = null;
1382: try {
1383: ctx = new CompNamingContext(fileName);
1384: ctx.rebind("warURL", warURL);
1385: ctx.rebind("isEarCase", new Boolean(false));
1386: } catch (NamingException e) {
1387: String err = "Error when undeploying the war file '"
1388: + fileName + "'";
1389: logger.log(BasicLevel.ERROR, err + e.getMessage());
1390: throw new JWebContainerServiceException(err, e);
1391: }
1392: unRegisterWar(ctx);
1393: }
1394:
1395: /**
1396: * Deploy the given wars of an ear file with the specified parent
1397: * classloader (ejb classloader or ear classloader). (This method is only
1398: * used for the ear applications, not for the web applications).
1399: * @param ctx the context containing the configuration to deploy the wars.
1400: * <BR>This context contains the following parameters :<BR>- urls
1401: * the list of the urls of the wars to deploy. <BR>- earURL the URL
1402: * of the ear application file. <BR>- parentClassLoader the parent
1403: * classLoader of the wars. <BR>- earClassLoader the ear classLoader
1404: * of the j2ee app. <BR>- altDDs the optional URI of deployment
1405: * descriptor. <BR>- contextRoots the optional context root of the
1406: * wars. <BR>
1407: * @throws JWebContainerServiceException if an error occurs during the
1408: * deployment.
1409: */
1410: public void deployWars(Context ctx)
1411: throws JWebContainerServiceException {
1412: // Gets the parameters from the context :
1413: // - urls the list of the urls of the wars to deploy.
1414: // - earURL the URL of the ear application file.
1415: // - parentClassLoader the parent classLoader of the wars.
1416: // - earClassLoader the ear classLoader of the j2ee app.
1417: // - altDDs the optional URI of deployment descriptor.
1418: // - contextRoots the optional context root of the wars.
1419: URL[] urls = null;
1420: URL earURL = null;
1421: ClassLoader parentClassLoader = null;
1422: ClassLoader earClassLoader = null;
1423: URL[] altDDs = null;
1424: String[] contextRoots = null;
1425: try {
1426: urls = (URL[]) ctx.lookup("urls");
1427: earURL = (URL) ctx.lookup("earURL");
1428: parentClassLoader = (ClassLoader) ctx
1429: .lookup("parentClassLoader");
1430: earClassLoader = (ClassLoader) ctx.lookup("earClassLoader");
1431: altDDs = (URL[]) ctx.lookup("altDDs");
1432: contextRoots = (String[]) ctx.lookup("contextRoots");
1433: } catch (NamingException e) {
1434: String err = "Error while getting parameter from context param ";
1435: logger.log(BasicLevel.ERROR, err + e.getMessage());
1436: throw new JWebContainerServiceException(err, e);
1437: }
1438: //webDDManager.setAltDD(earClassLoader, urls, altDDs);
1439:
1440: // Deploy all the wars of the ear application.
1441: for (int i = 0; i < urls.length; i++) {
1442: // Get the name of a war to deploy.
1443: String fileName = urls[i].getFile();
1444: if (logger.isLoggable(BasicLevel.DEBUG)) {
1445: logger.log(BasicLevel.DEBUG, "Deploy war '" + fileName
1446: + "' for the ear service");
1447: }
1448:
1449: // The context to give for the creation of the container
1450: // associated to the ejb-jar.
1451: Context contctx = null;
1452: try {
1453: contctx = new CompNamingContext(fileName);
1454: contctx.rebind("warURL", urls[i]);
1455: contctx.rebind("parentClassLoader", parentClassLoader);
1456: contctx.rebind("earClassLoader", earClassLoader);
1457: contctx.rebind("earURL", earURL);
1458: if (altDDs[i] != null) {
1459: contctx.rebind("altDD", altDDs[i]);
1460: }
1461: if (contextRoots[i] != null) {
1462: contctx.rebind("contextRoot", contextRoots[i]);
1463: }
1464: registerWar(contctx);
1465: } catch (Exception e) {
1466: // A war is corrupted so undeploy all the deployed war
1467: // of the ear application.
1468: logger.log(BasicLevel.ERROR, "Error when deploying '"
1469: + fileName + "'");
1470: logger.log(BasicLevel.ERROR, e.getMessage());
1471: logger.log(BasicLevel.ERROR,
1472: "Undeploy war of the ear application");
1473:
1474: for (int j = 0; j < i; j++) {
1475: String warFileName = urls[j].getFile();
1476: try {
1477: // Try to undeploy a war of the ear application.
1478: CompNamingContext context = new CompNamingContext(
1479: warFileName);
1480: context.rebind("warURL", urls[j]);
1481: context.rebind("isEarCase", new Boolean(true));
1482: unRegisterWar(context);
1483: } catch (Exception ex) {
1484: // Cannot undeploy a war of the ear application
1485: // So there is an error message.
1486: logger.log(BasicLevel.ERROR,
1487: "Error when undeploying '"
1488: + warFileName + "'");
1489: logger.log(BasicLevel.ERROR, ex.getMessage());
1490: logger
1491: .log(BasicLevel.ERROR,
1492: "Cannot undeploy war of the ear application");
1493: }
1494:
1495: }
1496: throw new JWebContainerServiceException(
1497: "Error during the deployment", e);
1498: }
1499: }
1500: }
1501:
1502: /**
1503: * Undeploy the given wars of an ear file with the specified parent
1504: * classloader (ejb classloader or ear classloader). (This method is only
1505: * used for the ear applications, not for the war applications).
1506: * @param urls the list of the urls of the wars to undeploy.
1507: */
1508: public void unDeployWars(URL[] urls) {
1509: for (int i = 0; i < urls.length; i++) {
1510: String warFileName = urls[i].getFile();
1511: try {
1512: // Try to undeploy a war of the ear application.
1513: CompNamingContext context = new CompNamingContext(
1514: warFileName);
1515: context.rebind("warURL", urls[i]);
1516: context.rebind("isEarCase", new Boolean(true));
1517: unRegisterWar(context);
1518: } catch (Exception ex) {
1519: // Cannot undeploy a war of the ear application
1520: // So there is an error message.
1521: logger.log(BasicLevel.ERROR, "Error when undeploying '"
1522: + warFileName + "'");
1523: logger.log(BasicLevel.ERROR, ex.getMessage());
1524: logger.log(BasicLevel.ERROR,
1525: "Cannot undeploy war of the ear application");
1526: }
1527: }
1528: }
1529:
1530: /**
1531: * Get the war identified by its URL (.war).
1532: * @param url the URL of the war to get.
1533: * @return the war indentified by its URL, or null if the war is not found.
1534: */
1535: public War getWar(URL url) {
1536: Enumeration wars = warDeployed.elements();
1537: while (wars.hasMoreElements()) {
1538: War war = (War) wars.nextElement();
1539: if (war.getWarURL().equals(url)) {
1540: return war;
1541: }
1542: }
1543: return null;
1544: }
1545:
1546: /**
1547: * Get a list of wars identified by their Context.
1548: * @param pContext the context of the war to get.
1549: * @return the list of wars indentified by their Context, or an empty list
1550: * if no wars are found.
1551: */
1552: private List getWar(String pContext) {
1553: List checkDeployed = new ArrayList();
1554: Enumeration wars = warDeployed.elements();
1555: while (wars.hasMoreElements()) {
1556: War war = (War) wars.nextElement();
1557: if (war.getContextRoot().equals(pContext)) {
1558: checkDeployed.add(war);
1559: }
1560: }
1561: return checkDeployed;
1562: }
1563:
1564: /**
1565: * Make a cleanup of the cache of deployment descriptor. This method must be
1566: * invoked after the ear deployment by the EAR service.
1567: * @param earClassLoader the ClassLoader of the ear application to remove
1568: * from the cache.
1569: */
1570: public void removeCache(ClassLoader earClassLoader) {
1571: WebManagerWrapper.removeCache(earClassLoader);
1572: }
1573:
1574: /**
1575: * Check if the specified file name correspond to a file which is located
1576: * relatively to where the JOnAS server is launched or in the
1577: * $JONAS_BASE/web-apps.
1578: * @param fileName the file to check if it exists.
1579: * @return the URL of the file found (either relatively to the JOnAS server
1580: * or to the $JONAS_BASE/web-apps).
1581: * @throws JWebContainerServiceException if the specified file does't
1582: * exists.
1583: */
1584: private URL checkWarFile(String fileName)
1585: throws JWebContainerServiceException {
1586:
1587: File f = null;
1588: try {
1589: f = new File(fileName).getCanonicalFile();
1590: if (!f.exists()) {
1591: boolean found = false;
1592: String warFileName = null;
1593: // Check also in JONAS_BASE/webapps directory
1594: warFileName = WEBAPPS_DIR + File.separator + fileName;
1595: f = new File(warFileName).getCanonicalFile();
1596: found = f.exists();
1597: if (found) {
1598: fileName = f.getPath();
1599: } else {
1600: String err = "File '" + f.getPath() + "' not found";
1601: logger.log(BasicLevel.ERROR, err);
1602: throw new JWebContainerServiceException(err);
1603: }
1604: }
1605: } catch (IOException e) {
1606: String err = "Invalid war file name '" + fileName;
1607: logger.log(BasicLevel.ERROR, err);
1608: throw new JWebContainerServiceException(err, e);
1609: }
1610:
1611: URL warURL = null;
1612: try {
1613: warURL = f.toURL();
1614: } catch (MalformedURLException e) {
1615: String err = "Invalid war file name '" + fileName + "'.";
1616: logger.log(BasicLevel.ERROR, err + e.getMessage());
1617: throw new JWebContainerServiceException(err, e);
1618: }
1619: return warURL;
1620: }
1621:
1622: /**
1623: * Check if the specified file is already deployed in the JOnAS server and
1624: * return the URL of this deployed war file.
1625: * @param fileName the name of the WAR file to check.
1626: * @return the URL of the deployed war file.
1627: * @throws JWebContainerServiceException if the file name doesn't correspond
1628: * to a deployed war.
1629: */
1630: private URL checkWarDeployed(String fileName)
1631: throws JWebContainerServiceException {
1632:
1633: URL url = null;
1634: try {
1635: Enumeration wars = warDeployed.elements();
1636: while (wars.hasMoreElements()) {
1637: War war = (War) wars.nextElement();
1638: url = (new File(fileName).getCanonicalFile()).toURL();
1639: if (war.getWarURL().equals(url)) {
1640: return url;
1641: }
1642: }
1643: String warFileName = WEBAPPS_DIR + File.separator
1644: + fileName;
1645: wars = warDeployed.elements();
1646: while (wars.hasMoreElements()) {
1647: War war = (War) wars.nextElement();
1648: url = (new File(warFileName).getCanonicalFile())
1649: .toURL();
1650: if (war.getWarURL().equals(url)) {
1651: return url;
1652: }
1653: }
1654:
1655: String err = "Cannot undeploy war: '" + fileName
1656: + "' is not deployed.";
1657: logger.log(BasicLevel.ERROR, err);
1658: throw new JWebContainerServiceException(err);
1659:
1660: } catch (MalformedURLException e) {
1661: String err = "Invalid war file name '" + fileName + "'.";
1662: logger.log(BasicLevel.ERROR, err + e.getMessage());
1663: throw new JWebContainerServiceException(err, e);
1664: } catch (IOException e) {
1665: String err = "Invalid war file name '" + fileName;
1666: logger.log(BasicLevel.ERROR, err);
1667: throw new JWebContainerServiceException(err, e);
1668: }
1669: }
1670:
1671: /**
1672: * @return current number of wars deployed in the JOnAS server
1673: */
1674: public Integer getCurrentNumberOfWars() {
1675: return new Integer(warDeployed.size());
1676: }
1677:
1678: /**
1679: * Return the list of installed web applications. The WAR files or the
1680: * directories with expanded web application are searched in
1681: * JONAS_BASE/webapps and all webapps directories 'autoload'.
1682: * @return The list of WAR files or the directories with expanded web
1683: * application found
1684: * @throws Exception if the list can't be retrieved
1685: */
1686: public List getInstalledWars() throws Exception {
1687: // get WAR files found in JONAS_BASE/webapps
1688: ArrayList al = JModule.getInstalledContainersInDir(WEBAPPS_DIR,
1689: JModule.WAR_EXTENSION, JModule.WAR_CHILD_DIR,
1690: JModule.WAR_CONFIRM_FILE);
1691: // get WAR files found in all autoload directories
1692: for (Iterator it = autoloadDirectories.iterator(); it.hasNext();) {
1693: al.addAll(JModule.getInstalledContainersInDir((String) it
1694: .next(), JModule.WAR_EXTENSION,
1695: JModule.WAR_CHILD_DIR, JModule.WAR_CONFIRM_FILE));
1696: }
1697: return al;
1698: }
1699:
1700: /**
1701: * This method is added temporarily. It will disapear when Wars will have
1702: * their associated MBeans (when Wars will become manageable)
1703: * @return the names of the wars currently deployed in the JOnAS server
1704: */
1705: public Set getWarNames() {
1706: HashSet names = new HashSet();
1707: for (Enumeration wars = warDeployed.elements(); wars
1708: .hasMoreElements();) {
1709: War war = (War) wars.nextElement();
1710: URL warURL = war.getWarURL();
1711: names.add(warURL.getFile());
1712: }
1713: return names;
1714: }
1715:
1716: /**
1717: * Add wars from a directory (war can be directories with WEB-INF/
1718: * directories) If the dir has a relative path, this path is relative from
1719: * where the Application Server is launched. If the dir is not found it will
1720: * be searched in $JONAS_BASE/webapps/ directory.
1721: * @param dirPath the path to the directory containing the wars to load.
1722: */
1723: private void addWars(String dirPath) {
1724: boolean found = false;
1725:
1726: // Look the directory relative to the $WEBAPPS_DIR directory
1727: File dir = new File(WEBAPPS_DIR + File.separator + dirPath);
1728: found = dir.isDirectory();
1729:
1730: if (found) {
1731: addWarsFrom(dir);
1732: } else {
1733: String err = "Warning: Cannot load dir: '" + dirPath + "' ";
1734: err += "is not a directory or directory doesn't exist";
1735: logger.log(BasicLevel.WARN, err);
1736: }
1737: }
1738:
1739: /**
1740: * Add the wars of the specified directory.
1741: * @param dir the directory from which the wars are loaded.
1742: * @throws JWebContainerServiceException if the argument is not a directory
1743: */
1744: private void addWarsFrom(File dir)
1745: throws JWebContainerServiceException {
1746: try {
1747: if (dir.isDirectory()) {
1748: File[] files = dir.listFiles();
1749: for (int i = 0; i < files.length; i++) {
1750: if (files[i].isFile()) {
1751: if (files[i].getPath().toLowerCase().endsWith(
1752: ".war")) {
1753: // War file
1754: warNames.add(files[i].getCanonicalPath());
1755: }
1756: } else {
1757: // Directory webapp
1758: warNames.add(files[i].getCanonicalPath());
1759: }
1760: }
1761: }
1762: } catch (IOException e) {
1763: String err = "Invalid file name '" + dir.getPath();
1764: logger.log(BasicLevel.ERROR, err);
1765: throw new JWebContainerServiceException(err, e);
1766: }
1767: }
1768:
1769: /**
1770: * Test if the specified filename is already deployed or not
1771: * @param fileName the name of the war file.
1772: * @return true if the war is deployed, else false.
1773: */
1774: public boolean isWarLoaded(String fileName) {
1775:
1776: URL url = null;
1777: boolean isLoaded = false;
1778: try {
1779: // Absolute filename
1780: try {
1781: url = new File(fileName).getCanonicalFile().toURL();
1782: //Check if the war is already deployed or not
1783: if (getWar(url) != null) {
1784: isLoaded = true;
1785: } else {
1786: // Not found force to test in relative Webapps directory
1787: url = null;
1788: }
1789: } catch (Exception e) {
1790: url = null;
1791: }
1792: // Relative filename
1793: if (url == null) {
1794: url = new File(WEBAPPS_DIR + File.separator + fileName)
1795: .getCanonicalFile().toURL();
1796: //Check if the war is already deployed or not
1797: if (getWar(url) != null) {
1798: isLoaded = true;
1799: }
1800: }
1801: } catch (Exception e) {
1802: String err = "Can not found if the war is deployed or not";
1803: logger.log(BasicLevel.ERROR, err);
1804: return false;
1805: }
1806:
1807: return isLoaded;
1808: }
1809:
1810: /**
1811: * Return the list of all loaded web applications.
1812: * @return The list of deployed web applications
1813: */
1814: public List getDeployedWars() {
1815: ArrayList al = new ArrayList();
1816: for (Enumeration wars = warDeployed.elements(); wars
1817: .hasMoreElements();) {
1818: War war = (War) wars.nextElement();
1819: URL warURL = war.getWarURL();
1820: al.add(warURL.getFile());
1821: }
1822: return al;
1823: }
1824:
1825: /**
1826: * Return the list of installed web applications ready to deploy.
1827: * @return The list of deployable web applications
1828: * @throws Exception if the list can't be retrieved
1829: */
1830: public List getDeployableWars() throws Exception {
1831: List al = getInstalledWars();
1832: al.removeAll(getDeployedWars());
1833: return al;
1834: }
1835:
1836: /**
1837: * Return the list of "autoload" directories for web applications.
1838: * @return The list of all "autoload" directories
1839: */
1840: public List getAutoloadDirectories() {
1841: ArrayList al = new ArrayList();
1842: for (Iterator it = autoloadDirectories.iterator(); it.hasNext();) {
1843: try {
1844: al.add(new File((String) it.next()).toURL().getPath());
1845: } catch (Exception e) {
1846: if (logger.isLoggable(BasicLevel.DEBUG)) {
1847: logger.log(BasicLevel.DEBUG,
1848: "Can't get autoload directories "
1849: + e.getMessage());
1850: }
1851: // none
1852: }
1853: }
1854: return al;
1855: }
1856:
1857: /**
1858: * Return the WebApps directory.
1859: * @return The WebApps directory
1860: */
1861: public String getWebappsDirectory() {
1862: String sRet = null;
1863: try {
1864: sRet = (new File(WEBAPPS_DIR)).toURL().getPath();
1865: } catch (Exception e) {
1866: if (logger.isLoggable(BasicLevel.DEBUG)) {
1867: logger
1868: .log(BasicLevel.DEBUG,
1869: "Can't get webapps directory "
1870: + e.getMessage());
1871: }
1872: // none
1873: }
1874: return sRet;
1875: }
1876:
1877: /**
1878: * Gets the name of the server which is the web container
1879: * @return the name of the server which is the web container
1880: */
1881: public String getServerName() {
1882: if (serverName == null) {
1883: updateServerInfos();
1884: }
1885: return serverName;
1886: }
1887:
1888: /**
1889: * Gets the version of the server which is the web container
1890: * @return the version of the server which is the web container
1891: */
1892: public String getServerVersion() {
1893: if (serverVersion == null) {
1894: updateServerInfos();
1895: }
1896: return serverVersion;
1897: }
1898:
1899: /**
1900: * Update info of the serverName and serverVersion
1901: */
1902: protected abstract void updateServerInfos();
1903:
1904: /**
1905: * Return the Default host name of the web container.
1906: * @return the Default host name of the web container.
1907: * @throws JWebContainerServiceException when it is impossible to get the
1908: * Default Host.
1909: */
1910: public abstract String getDefaultHost()
1911: throws JWebContainerServiceException;
1912:
1913: /**
1914: * Return the Default HTTP port number of the web container (can be null if
1915: * multiple HTTP connector has been set).
1916: * @return the Default HTTP port number of the web container.
1917: * @throws JWebContainerServiceException when it is impossible to get the
1918: * Default Http port.
1919: */
1920: public abstract String getDefaultHttpPort()
1921: throws JWebContainerServiceException;
1922:
1923: /**
1924: * Return the Default HTTPS port number of the web container (can be null if
1925: * multiple HTTPS connector has been set).
1926: * @return the Default HTTPS port number of the web container.
1927: * @throws JWebContainerServiceException when it is impossible to get the
1928: * Default Https port.
1929: */
1930: public abstract String getDefaultHttpsPort()
1931: throws JWebContainerServiceException;
1932:
1933: /**
1934: * @return Returns the logger.
1935: */
1936: protected static Logger getLogger() {
1937: return logger;
1938: }
1939:
1940: /**
1941: * @return Returns the naming.
1942: */
1943: protected ContainerNaming getNaming() {
1944: return naming;
1945: }
1946:
1947: /**
1948: * @return Returns the mbeanServer.
1949: */
1950: protected MBeanServer getMbeanServer() {
1951: return mbeanServer;
1952: }
1953:
1954: /**
1955: * @param serverName The serverName to set.
1956: */
1957: protected void setServerName(String serverName) {
1958: this .serverName = serverName;
1959: }
1960:
1961: /**
1962: * @param serverVersion The serverVersion to set.
1963: */
1964: protected void setServerVersion(String serverVersion) {
1965: this .serverVersion = serverVersion;
1966: }
1967:
1968: /**
1969: * Holds the ClassLoader used to retrieve the WebApp JNDI Context and the
1970: * JOnAS Webapp ClasLoader
1971: * @author Guillaume Sauthier
1972: */
1973: public class WebLoaderHolder {
1974:
1975: /**
1976: * Web ClassLoader used by JOnAS.
1977: */
1978: private URLClassLoader jonasWebLoader;
1979:
1980: /**
1981: * Web ClassLoader used to retrieve the JNDI Context of the webapp.
1982: */
1983: private ClassLoader envWebLoader;
1984:
1985: /**
1986: * Constructs a WebLoaderHolder with jonas Loader and en Loader.
1987: * @param jonas JOnAS Webapp Loader
1988: * @param env Environnement ClassLoader
1989: */
1990: public WebLoaderHolder(final URLClassLoader jonas,
1991: final ClassLoader env) {
1992: jonasWebLoader = jonas;
1993: envWebLoader = env;
1994: }
1995:
1996: /**
1997: * @return Returns the jonasWebLoader.
1998: */
1999: public URLClassLoader getJonasWebLoader() {
2000: return jonasWebLoader;
2001: }
2002:
2003: /**
2004: * @return Returns the envWebLoader.
2005: */
2006: public ClassLoader getEnvWebLoader() {
2007: return envWebLoader;
2008: }
2009:
2010: /**
2011: * @param envWebLoader The envWebLoader to set.
2012: */
2013: public void setEnvWebLoader(ClassLoader envWebLoader) {
2014: this .envWebLoader = envWebLoader;
2015: }
2016:
2017: /**
2018: * @param jonasWebLoader The jonasWebLoader to set.
2019: */
2020: public void setJonasWebLoader(URLClassLoader jonasWebLoader) {
2021: this.jonasWebLoader = jonasWebLoader;
2022: }
2023: }
2024:
2025: }
|