--- java/org/apache/catalina/core/ContainerBase.java (revision 1201578) +++ java/org/apache/catalina/core/ContainerBase.java (working copy) @@ -794,18 +794,12 @@ // Start child if (started && startChildren && (child instanceof Lifecycle)) { - boolean success = false; try { ((Lifecycle) child).start(); - success = true; } catch (LifecycleException e) { log.error("ContainerBase.addChild: start: ", e); throw new IllegalStateException ("ContainerBase.addChild: start: " + e); - } finally { - if (!success) { - children.remove(child.getName()); - } } } --- java/org/apache/catalina/startup/HostConfig.java (revision 1201578) +++ java/org/apache/catalina/startup/HostConfig.java (working copy) @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -548,24 +549,15 @@ */ protected void deployApps(String name) { - File appBase = appBase(); - File configBase = configBase(); String baseName = getConfigFile(name); String docBase = getDocBase(name); - - // Deploy XML descriptors from configBase - File xml = new File(configBase, baseName + ".xml"); - if (xml.exists()) - deployDescriptor(name, xml, baseName + ".xml"); - // Deploy WARs, and loop if additional descriptors are found - File war = new File(appBase, docBase + ".war"); - if (war.exists()) - deployWAR(name, war, docBase + ".war"); - // Deploy expanded folders - File dir = new File(appBase, docBase); - if (dir.exists()) - deployDirectory(name, dir, docBase); - + + // Deploy XML descriptor from configBase + deployDescriptor(baseName + ".xml", false); + // Deploy WAR + deployWAR(docBase + ".war", false); + // Deploy expanded folder + deployDirectory(docBase, false); } @@ -578,32 +570,45 @@ return; for (int i = 0; i < files.length; i++) { + deployDescriptor(files[i], true); + } - if (files[i].equalsIgnoreCase("META-INF")) - continue; - if (files[i].equalsIgnoreCase("WEB-INF")) - continue; - File contextXml = new File(configBase, files[i]); - if (files[i].toLowerCase().endsWith(".xml")) { + } - // Calculate the context path and make sure it is unique - String nameTmp = files[i].substring(0, files[i].length() - 4); - String contextPath = "/" + nameTmp.replace('#', '/'); - if (nameTmp.equals("ROOT")) { - contextPath = ""; - } - if (isServiced(contextPath)) - continue; - - String file = files[i]; - - deployDescriptor(contextPath, contextXml, file); - - } - + /** + * + * @param file + * Filename of the file in our configBase. If it is not a ".xml" + * file, this call is ignored. + * @param checkServiced + * If true, deployment will not be allowed while + * context is serviced. + */ + private void deployDescriptor(String file, boolean checkServiced) { + if (file.length() <= 4 || file.equalsIgnoreCase("META-INF") + || file.equalsIgnoreCase("WEB-INF")) { + return; } - + String extention = file.substring(file.length() - 4).toLowerCase( + Locale.ENGLISH); + if (!extention.equals(".xml")) { + return; + } + File appBase = appBase(); + // Calculate the context path and make sure it is unique + String contextPath = getContextPathFromFileName(appBase, file, 4); + if (contextPath == null) { + return; + } + if (checkServiced && isServiced(contextPath)) { + return; + } + File contextXml = new File(configBase(), file); + if (!contextXml.isFile()) { + return; + } + deployDescriptor(contextPath, contextXml, file); } @@ -618,6 +623,7 @@ } DeployedApplication deployedApp = new DeployedApplication(contextPath); + boolean success = false; // Assume this is a configuration descriptor and deploy it if(log.isInfoEnabled()) { @@ -725,14 +731,22 @@ (contextXml.getAbsolutePath(), new Long(contextXml.lastModified())); } } + if (context != null && host.findChild(context.getName()) != null) { + deployed.put(contextPath, deployedApp); + success = true; + } } catch (Throwable t) { log.error(sm.getString("hostConfig.deployDescriptor.error", file), t); + } finally { + if (!success) { + deployedApp = new DeployedApplication(contextPath); + deployedApp.redeployResources.put( + contextXml.getAbsolutePath(), + new Long(contextXml.lastModified())); + deployed.put(contextPath, deployedApp); + } } - - if (context != null && host.findChild(context.getName()) != null) { - deployed.put(contextPath, deployedApp); - } } @@ -740,47 +754,49 @@ * Deploy WAR files. */ protected void deployWARs(File appBase, String[] files) { - + if (files == null) return; - + for (int i = 0; i < files.length; i++) { - - if (files[i].equalsIgnoreCase("META-INF")) - continue; - if (files[i].equalsIgnoreCase("WEB-INF")) - continue; - File dir = new File(appBase, files[i]); - if (files[i].toLowerCase().endsWith(".war") && dir.isFile() - && !invalidWars.contains(files[i]) ) { - - // Calculate the context path and make sure it is unique - String contextPath = "/" + files[i].replace('#','/'); - int period = contextPath.lastIndexOf("."); - contextPath = contextPath.substring(0, period); - - // Check for WARs with /../ /./ or similar sequences in the name - if (!validateContextPath(appBase, contextPath)) { - log.error(sm.getString( - "hostConfig.illegalWarName", files[i])); - invalidWars.add(files[i]); - continue; - } + deployWAR(files[i], true); + } - if (contextPath.equals("/ROOT")) - contextPath = ""; - - if (isServiced(contextPath)) - continue; - - String file = files[i]; - - deployWAR(contextPath, dir, file); - + } + + + /** + * Calculates contextPath from the name of a file. + * + * @param fileName + * File name, without path. + * @param extensionSize + * Size of filename extension. Either 0 or 4. + * @return Context path, or null if filename is invalidž + */ + private String getContextPathFromFileName(File appbase, String fileName, + int extensionSize) { + if (extensionSize > 0) { + if (fileName.length() < extensionSize) { + return null; } - + fileName = fileName.substring(0, fileName.length() - extensionSize); } - + if (fileName.equals("ROOT")) { + return ""; + } + String warName = fileName + ".war"; + if (invalidWars.contains(warName)) { + return null; + } + String contextPath = "/" + fileName.replace('#', '/'); + // Check for WARs with /../ /./ or similar sequences in the name + if (!validateContextPath(appBase, contextPath)) { + log.error(sm.getString("hostConfig.illegalWarName", fileName)); + invalidWars.add(warName); + return null; + } + return contextPath; } @@ -821,6 +837,42 @@ } /** + * + * @param file + * Filename of the file in our appBase. If it is not a ".war" + * file, this call is ignored. + * @param checkServiced + * If true, deployment will not be allowed while + * context is serviced. + */ + private void deployWAR(String file, boolean checkServiced) { + if (file.length() <= 4 || file.equalsIgnoreCase("META-INF") + || file.equalsIgnoreCase("WEB-INF")) { + return; + } + String extention = file.substring(file.length() - 4).toLowerCase( + Locale.ENGLISH); + if (!extention.equals(".war")) { + return; + } + File appBase = appBase(); + // Calculate the context path and make sure it is unique + String contextPath = getContextPathFromFileName(appBase, file, 4); + if (contextPath == null) { + return; + } + if (checkServiced && isServiced(contextPath)) { + return; + } + File war = new File(appBase(), file); + if (!war.isFile()) { + return; + } + deployWAR(contextPath, war, file); + } + + + /** * @param contextPath * @param war * @param file @@ -898,7 +950,8 @@ } DeployedApplication deployedApp = new DeployedApplication(contextPath); - + boolean success = false; + // Deploy the application in this WAR file if(log.isInfoEnabled()) log.info(sm.getString("hostConfig.deployJar", file)); @@ -966,11 +1019,18 @@ } else { addWatchedResources(deployedApp, null, context); } + deployed.put(contextPath, deployedApp); + success = true; } catch (Throwable t) { log.error(sm.getString("hostConfig.deployJar.error", file), t); + } finally { + if (!success) { + deployedApp = new DeployedApplication(contextPath); + deployedApp.redeployResources.put(war.getAbsolutePath(), new Long( + war.lastModified())); + deployed.put(contextPath, deployedApp); + } } - - deployed.put(contextPath, deployedApp); } @@ -983,28 +1043,38 @@ return; for (int i = 0; i < files.length; i++) { + deployDirectory(files[i], true); + } - if (files[i].equalsIgnoreCase("META-INF")) - continue; - if (files[i].equalsIgnoreCase("WEB-INF")) - continue; - File dir = new File(appBase, files[i]); - if (dir.isDirectory()) { + } - // Calculate the context path and make sure it is unique - String contextPath = "/" + files[i].replace('#','/'); - if (files[i].equals("ROOT")) - contextPath = ""; - if (isServiced(contextPath)) - continue; - - deployDirectory(contextPath, dir, files[i]); - - } - + /** + * + * @param file + * Filename of the directory in our appBase. + * @param checkServiced + * If true, deployment will not be allowed while + * context is serviced. + */ + private void deployDirectory(String file, boolean checkServiced) { + if (file.equalsIgnoreCase("META-INF") || file.equalsIgnoreCase("WEB-INF")) { + return; } - + File appBase = appBase(); + // Calculate the context path and make sure it is unique + String contextPath = getContextPathFromFileName(appBase, file, 0); + if (contextPath == null) { + return; + } + if (checkServiced && isServiced(contextPath)) { + return; + } + File dir = new File(appBase, file); + if (!dir.isDirectory()) { + return; + } + deployDirectory(contextPath, dir, file); } @@ -1014,11 +1084,12 @@ * @param file */ protected void deployDirectory(String contextPath, File dir, String file) { - DeployedApplication deployedApp = new DeployedApplication(contextPath); - if (deploymentExists(contextPath)) return; + DeployedApplication deployedApp = new DeployedApplication(contextPath); + boolean success = false; + // Deploy the application in this directory if( log.isInfoEnabled() ) log.info(sm.getString("hostConfig.deployDir", file)); @@ -1084,11 +1155,18 @@ (xmlCopy.getAbsolutePath(), new Long(xmlCopy.lastModified())); } addWatchedResources(deployedApp, dir.getAbsolutePath(), context); + deployed.put(contextPath, deployedApp); + success = true; } catch (Throwable t) { log.error(sm.getString("hostConfig.deployDir.error", file), t); + } finally { + if (!success) { + deployedApp = new DeployedApplication(contextPath); + deployedApp.redeployResources.put(dir.getAbsolutePath(), new Long( + dir.lastModified())); + deployed.put(contextPath, deployedApp); + } } - - deployed.put(contextPath, deployedApp); } @@ -1155,18 +1233,20 @@ if (log.isInfoEnabled()) log.info(sm.getString("hostConfig.undeploy", app.name)); ContainerBase context = (ContainerBase) host.findChild(app.name); - try { - host.removeChild(context); - } catch (Throwable t) { - log.warn(sm.getString - ("hostConfig.context.remove", app.name), t); + if (context != null) { + try { + host.removeChild(context); + } catch (Throwable t) { + log.warn(sm.getString + ("hostConfig.context.remove", app.name), t); + } + try { + context.destroy(); + } catch (Throwable t) { + log.warn(sm.getString + ("hostConfig.context.destroy", app.name), t); + } } - try { - context.destroy(); - } catch (Throwable t) { - log.warn(sm.getString - ("hostConfig.context.destroy", app.name), t); - } // Delete other redeploy resources for (int j = i + 1; j < resources.length; j++) { try { @@ -1208,14 +1288,14 @@ if (log.isInfoEnabled()) log.info(sm.getString("hostConfig.undeploy", app.name)); ContainerBase context = (ContainerBase) host.findChild(app.name); - try { - host.removeChild(context); - } catch (Throwable t) { - log.warn(sm.getString - ("hostConfig.context.remove", app.name), t); - } if (context != null) { try { + host.removeChild(context); + } catch (Throwable t) { + log.warn(sm.getString + ("hostConfig.context.remove", app.name), t); + } + try { context.destroy(); } catch (Throwable t) { log.warn(sm.getString @@ -1272,20 +1352,22 @@ if(log.isInfoEnabled()) log.info(sm.getString("hostConfig.reload", app.name)); Container context = host.findChild(app.name); - try { - ((Lifecycle) context).stop(); - } catch (Exception e) { - log.warn(sm.getString - ("hostConfig.context.restart", app.name), e); + if (context != null) { + try { + ((Lifecycle) context).stop(); + } catch (Exception e) { + log.warn(sm.getString + ("hostConfig.context.restart", app.name), e); + } + // If the context was not started (for example an error + // in web.xml) we'll still get to try to start + try { + ((Lifecycle) context).start(); + } catch (Exception e) { + log.warn(sm.getString + ("hostConfig.context.restart", app.name), e); + } } - // If the context was not started (for example an error - // in web.xml) we'll still get to try to start - try { - ((Lifecycle) context).start(); - } catch (Exception e) { - log.warn(sm.getString - ("hostConfig.context.restart", app.name), e); - } // Update times app.reloadResources.put(resources[i], new Long(resource.lastModified())); app.timestamp = System.currentTimeMillis(); @@ -1356,7 +1438,10 @@ (DeployedApplication[]) deployed.values().toArray(new DeployedApplication[0]); for (int i = 0; i < apps.length; i++) { try { - host.removeChild(host.findChild(apps[i].name)); + Container context = host.findChild(apps[i].name); + if (context != null) { + host.removeChild(context); + } } catch (Throwable t) { log.warn(sm.getString ("hostConfig.context.remove", apps[i].name), t); @@ -1461,7 +1546,10 @@ public void unmanageApp(String contextPath) { if(isServiced(contextPath)) { deployed.remove(contextPath); - host.removeChild(host.findChild(contextPath)); + Container context = host.findChild(contextPath); + if (context != null) { + host.removeChild(host.findChild(contextPath)); + } } }