From a4aef0e0e980ff9af5850eaf1b909dbaf60a82fe Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 2 Jun 2013 12:24:51 -0700 Subject: [PATCH] [bs-52] Allow war files to run in place Update AbstractEmbeddedServletContainerFactory to detect the document root from a classically packaged war file. [#48386505] [bs-52] Support for running "traditional" webapps in place --- .../ManagementAutoConfiguration.java | 1 + .../OnManagementContextCondition.java | 1 - .../bootstrap/launcher/Launcher.java | 4 +- ...stractEmbeddedServletContainerFactory.java | 54 +++++++++++++++++-- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementAutoConfiguration.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementAutoConfiguration.java index 9760f4c59ca..fc1684739e3 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementAutoConfiguration.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/ManagementAutoConfiguration.java @@ -57,6 +57,7 @@ public class ManagementAutoConfiguration implements ApplicationContextAware { .getName() + ".MEMO"; private ApplicationContext parent; + private ConfigurableApplicationContext context; @Autowired diff --git a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/OnManagementContextCondition.java b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/OnManagementContextCondition.java index 1a623527833..7e408c1d429 100644 --- a/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/OnManagementContextCondition.java +++ b/spring-bootstrap-actuator/src/main/java/org/springframework/bootstrap/actuate/autoconfigure/OnManagementContextCondition.java @@ -34,7 +34,6 @@ import org.springframework.core.type.AnnotationMetadata; * (the application context with the management endpoints). * * @author Dave Syer - * * @see ConditionalOnManagementContext */ public class OnManagementContextCondition implements Condition { diff --git a/spring-bootstrap-launcher/src/main/java/org/springframework/bootstrap/launcher/Launcher.java b/spring-bootstrap-launcher/src/main/java/org/springframework/bootstrap/launcher/Launcher.java index 101cb4b2cc6..9919c926e6e 100644 --- a/spring-bootstrap-launcher/src/main/java/org/springframework/bootstrap/launcher/Launcher.java +++ b/spring-bootstrap-launcher/src/main/java/org/springframework/bootstrap/launcher/Launcher.java @@ -96,12 +96,12 @@ public abstract class Launcher { Enumeration jarEntries = jarFile.entries(); while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); - this.logger.fine("Adding: " + jarEntry.getName()); if (isNestedJarFile(jarEntry)) { + this.logger.fine("Adding: " + jarEntry.getName()); lib.add(jarFile.getNestedJarFile(jarEntry)); } } - this.logger.fine("Done"); + this.logger.fine("Added " + lib.size() + " entries"); postProcessLib(jarFile, lib); ClassLoader classLoader = createClassLoader(lib); launch(args, jarFile, classLoader); diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java index 37e68e02e45..257b37008b3 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/context/embedded/AbstractEmbeddedServletContainerFactory.java @@ -17,7 +17,12 @@ package org.springframework.bootstrap.context.embedded; import java.io.File; +import java.io.IOException; import java.net.InetAddress; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.security.CodeSource; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -37,6 +42,9 @@ import org.springframework.util.Assert; public abstract class AbstractEmbeddedServletContainerFactory implements ConfigurableEmbeddedServletContainerFactory { + private static final String[] COMMON_DOC_ROOTS = { "src/main/webapp", "public", + "static" }; + private final Log logger = LogFactory.getLog(getClass()); private String contextPath = ""; @@ -291,7 +299,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements } /** - * @return the JS{ servlet class name + * @return the JSP servlet class name */ protected String getJspServletClassName() { return this.jspServletClassName; @@ -318,18 +326,54 @@ public abstract class AbstractEmbeddedServletContainerFactory implements * warning and returning {@code null} otherwise. */ protected final File getValidDocumentRoot() { - File[] roots = new File[] { getDocumentRoot(), new File("src/main/webapp"), - new File("public"), new File("static") }; - for (File root : roots) { + + // User specified + if (getDocumentRoot() != null) { + return getDocumentRoot(); + } + + // Packaged as a WAR file + File warFile = getCodeSourceArchive(); + if (warFile.exists() && !warFile.isDirectory() + && warFile.getName().toLowerCase().endsWith(".war")) { + return warFile.getAbsoluteFile(); + } + + // Common DocRoots + for (String commonDocRoot : COMMON_DOC_ROOTS) { + File root = new File(commonDocRoot); if (root != null && root.exists() && root.isDirectory()) { return root.getAbsoluteFile(); } } + if (this.logger.isWarnEnabled()) { - this.logger.warn("None of the document roots " + roots + this.logger.warn("None of the document roots " + + Arrays.asList(COMMON_DOC_ROOTS) + " point to a directory and will be ignored."); } return null; } + private File getCodeSourceArchive() { + try { + CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); + URL location = (codeSource == null ? null : codeSource.getLocation()); + if (location == null) { + return null; + } + String path = location.getPath(); + URLConnection connection = location.openConnection(); + if (connection instanceof JarURLConnection) { + path = ((JarURLConnection) connection).getJarFile().getName(); + } + if (path.indexOf("!/") != -1) { + path = path.substring(0, path.indexOf("!/")); + } + return new File(path); + } catch (IOException e) { + return null; + } + } + }