From 6fec10e51ee904b560ee98f77e21dd2bd879e219 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 25 Jan 2024 11:00:13 -0600 Subject: [PATCH] Issue #11260 - Allow `QuickStartConfiguration` to be used in mixed contexts environment where some do not have a WEB-INF/quickstart-web.xml (#11261) * QuickStartConfiguration updated Signed-off-by: Joakim Erdfelt --- .../quickstart/QuickStartConfiguration.java | 97 +++++++++++++------ .../jetty/quickstart/PreconfigureSpecWar.java | 3 +- .../jetty/quickstart/QuickStartTest.java | 42 ++++++++ .../src/test/webapps/no-web-xml/index.html | 1 + 4 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 tests/test-quickstart/src/test/webapps/no-web-xml/index.html diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java index d7a4641abcd..50d593bb00e 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java @@ -48,6 +48,7 @@ public class QuickStartConfiguration extends AbstractConfiguration public static final String ORIGIN_ATTRIBUTE = "org.eclipse.jetty.quickstart.origin"; public static final String QUICKSTART_WEB_XML = "org.eclipse.jetty.quickstart.xml"; public static final String MODE = "org.eclipse.jetty.quickstart.mode"; + private static final Mode DEFAULT_MODE = Mode.AUTO; static { @@ -72,13 +73,10 @@ public class QuickStartConfiguration extends AbstractConfiguration public enum Mode { GENERATE, // Generate quickstart-web.xml and then stop - AUTO, // use or generate depending on the existance of quickstart-web.xml + AUTO, // use quickstart depending on the existence of quickstart-web.xml QUICKSTART // Use quickstart-web.xml } - private Mode _mode = Mode.AUTO; - private boolean _quickStart; - public QuickStartConfiguration() { super(true); @@ -86,36 +84,46 @@ public class QuickStartConfiguration extends AbstractConfiguration addDependents(WebXmlConfiguration.class); } + private Mode getModeForContext(WebAppContext context) + { + Mode mode = (Mode)context.getAttribute(MODE); + if (mode == null) + return DEFAULT_MODE; + return mode; + } + @Override public void preConfigure(WebAppContext context) throws Exception { - //check that webapp is suitable for quick start - it is not a packed war + // check that webapp is suitable for quick start - it is not a packed war String war = context.getWar(); - if (war == null || war.length() <= 0 || !context.getBaseResource().isDirectory()) - throw new IllegalStateException("Bad Quickstart location"); + if (StringUtil.isBlank(war) || !context.getBaseResource().isDirectory()) + throw new IllegalStateException("Invalid Quickstart location"); - //look for quickstart-web.xml in WEB-INF of webapp + // look for quickstart-web.xml in WEB-INF of webapp Resource quickStartWebXml = getQuickStartWebXml(context); - LOG.debug("quickStartWebXml={} exists={}", quickStartWebXml, quickStartWebXml.exists()); - //Get the mode - Mode mode = (Mode)context.getAttribute(MODE); - if (mode != null) - _mode = mode; - - _quickStart = false; - - switch (_mode) + // Get the mode + Mode mode = getModeForContext(context); + + if (LOG.isDebugEnabled()) + LOG.debug("mode={} quickStartWebXml={} exists={} for {}", + mode, + quickStartWebXml, + quickStartWebXml.exists(), + context); + + switch (mode) { case GENERATE: { if (quickStartWebXml.exists()) - LOG.info("Regenerating {}", quickStartWebXml); + LOG.info("Regenerating {} for {}", quickStartWebXml, context); else - LOG.info("Generating {}", quickStartWebXml); - + LOG.info("Generating {} for {}", quickStartWebXml, context); + super.preConfigure(context); - //generate the quickstart file then abort + // generate the quickstart file then abort QuickStartGeneratorConfiguration generator = new QuickStartGeneratorConfiguration(true); configure(generator, context); context.addConfiguration(generator); @@ -130,20 +138,25 @@ public class QuickStartConfiguration extends AbstractConfiguration else { if (LOG.isDebugEnabled()) - LOG.debug("No quickstart xml file, starting webapp {} normally", context); + LOG.debug("No quickstart-web.xml found, starting webapp {} normally", context); super.preConfigure(context); } break; } case QUICKSTART: + { if (quickStartWebXml.exists()) + { quickStart(context); + } else - throw new IllegalStateException("No " + quickStartWebXml); + { + throw new IllegalStateException("No WEB-INF/quickstart-web.xml file for " + context); + } break; - + } default: - throw new IllegalStateException(_mode.toString()); + throw new IllegalStateException("Unhandled QuickStart.Mode: " + mode); } } @@ -160,7 +173,9 @@ public class QuickStartConfiguration extends AbstractConfiguration @Override public void configure(WebAppContext context) throws Exception { - if (!_quickStart) + Resource quickStartWebXml = getQuickStartWebXml(context); + // Don't run configure() if quickstart-web.xml does not exist + if (quickStartWebXml == null || !quickStartWebXml.exists()) { super.configure(context); } @@ -203,7 +218,6 @@ public class QuickStartConfiguration extends AbstractConfiguration throws Exception { LOG.info("Quickstarting {}", context); - _quickStart = true; context.setConfigurations(context.getConfigurations().stream() .filter(c -> !__replacedConfigurations.contains(c.replaces()) && !__replacedConfigurations.contains(c.getClass())) .collect(Collectors.toList()).toArray(new Configuration[]{})); @@ -225,15 +239,34 @@ public class QuickStartConfiguration extends AbstractConfiguration if (attr instanceof Resource) return (Resource)attr; + Resource qstart; Resource webInf = context.getWebInf(); if (webInf == null || !webInf.exists()) { - File tmp = new File(context.getBaseResource().getFile(), "WEB-INF"); - tmp.mkdirs(); - webInf = context.getWebInf(); + switch (getModeForContext(context)) + { + case GENERATE: + // This mode allow for generation of quickstart-web.xml + // So we should be safe to attempt to create the missing WEB-INF directory. + File tmp = new File(context.getBaseResource().getFile(), "WEB-INF"); + if (!tmp.mkdirs()) + { + throw new IllegalStateException("Unable to create directory " + tmp); + } + webInf = context.getWebInf(); + break; + case AUTO: + case QUICKSTART: + // These modes do not allow for generation of quickstart-web.xml, so do not + // create the missing WEB-INF directory. + + // Establish a Resource suitable for callers of this method (does not exist) + qstart = context.getBaseResource().addPath("WEB-INF/quickstart-web.xml"); + context.setAttribute(QUICKSTART_WEB_XML, qstart); + return qstart; + } } - Resource qstart; if (attr == null || StringUtil.isBlank(attr.toString())) { qstart = webInf.addPath("quickstart-web.xml"); @@ -253,6 +286,6 @@ public class QuickStartConfiguration extends AbstractConfiguration context.setAttribute(QUICKSTART_WEB_XML, qstart); } context.setAttribute(QUICKSTART_WEB_XML, qstart); - return qstart; + return qstart; } } diff --git a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java index 0c58454b7d2..e887208e1c8 100644 --- a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java +++ b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/PreconfigureSpecWar.java @@ -13,7 +13,6 @@ package org.eclipse.jetty.quickstart; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -52,10 +51,12 @@ public class PreconfigureSpecWar LOG.info("Preconfigured in {}ms", NanoTime.millisSince(__start)); + /* Path quickStartXml = target.resolve("WEB-INF/quickstart-web.xml"); try (InputStream in = Files.newInputStream(quickStartXml)) { IO.copy(in, System.out); } + */ } } diff --git a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java index 949fa80cf86..4fa5dc3bfca 100644 --- a/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java +++ b/tests/test-quickstart/src/test/java/org/eclipse/jetty/quickstart/QuickStartTest.java @@ -24,6 +24,8 @@ import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.PlusConfiguration; import org.eclipse.jetty.server.NetworkConnector; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.toolchain.test.FS; +import org.eclipse.jetty.toolchain.test.MavenPaths; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.resource.PathResource; @@ -34,6 +36,8 @@ import org.eclipse.jetty.xml.XmlConfiguration; import org.eclipse.jetty.xml.XmlParser.Node; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,6 +45,44 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class QuickStartTest { + /** + * Test of an exploded webapp directory, no WEB-INF/quickstart-web.xml, + * with QuickStartConfiguration enabled. + */ + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void testExplodedWebAppDirNoWebXml(boolean defaultMode) throws Exception + { + Path jettyHome = MavenPaths.targetDir(); + Path webappDir = MavenPaths.targetTestDir("no-web-xml"); + Path src = MavenPaths.projectBase().resolve("src/test/webapps/no-web-xml"); + FS.ensureEmpty(webappDir); + org.eclipse.jetty.toolchain.test.IO.copyDir(src, webappDir); + + System.setProperty("jetty.home", jettyHome.toString()); + + Server server = new Server(0); + + WebAppContext webapp = new WebAppContext(); + webapp.addConfiguration(new QuickStartConfiguration(), + new EnvConfiguration(), + new PlusConfiguration(), + new AnnotationConfiguration()); + // Default mode should allow this style of exploded webapp dir. + if (!defaultMode) + webapp.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.AUTO); + webapp.setWarResource(new PathResource(webappDir)); + webapp.setContextPath("/"); + server.setHandler(webapp); + server.start(); + + URL url = new URL("http://127.0.0.1:" + server.getBean(NetworkConnector.class).getLocalPort() + "/index.html"); + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + assertEquals(200, connection.getResponseCode()); + assertThat(IO.toString((InputStream)connection.getContent()), Matchers.containsString("

Contents of no-web-xml

")); + + server.stop(); + } @Test public void testStandardTestWar() throws Exception diff --git a/tests/test-quickstart/src/test/webapps/no-web-xml/index.html b/tests/test-quickstart/src/test/webapps/no-web-xml/index.html new file mode 100644 index 00000000000..199996b48c5 --- /dev/null +++ b/tests/test-quickstart/src/test/webapps/no-web-xml/index.html @@ -0,0 +1 @@ +

Contents of no-web-xml

\ No newline at end of file