Issue #4430 Quickstart duplicate servlets,filters,listeners from context xml (#5311)

Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2020-09-22 18:24:35 +02:00 committed by GitHub
parent 592dfb85fc
commit 1a9c68c905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 222 additions and 15 deletions

View File

@ -51,6 +51,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.servlet.Source;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.resource.Resource;
@ -212,6 +213,9 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
if (context.getServletHandler().getListeners() != null)
for (ListenerHolder e : context.getServletHandler().getListeners())
{
if (e.getSource() == Source.EMBEDDED)
continue;
out.openTag("listener", origin(md, e.getClassName() + ".listener"))
.tag("listener-class", e.getClassName())
.closeTag();
@ -223,14 +227,20 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
{
for (FilterHolder holder : servlets.getFilters())
{
if (holder.getSource() == Source.EMBEDDED)
continue;
outholder(out, md, holder);
}
}
if (servlets.getFilterMappings() != null)
{
for (FilterMapping mapping : servlets.getFilterMappings())
for (FilterMapping mapping :servlets.getFilterMappings())
{
FilterHolder f = servlets.getFilter(mapping.getFilterName());
if (f != null && f.getSource() == Source.EMBEDDED)
continue;
out.openTag("filter-mapping");
out.tag("filter-name", mapping.getFilterName());
if (mapping.getPathSpecs() != null)
@ -265,6 +275,8 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
{
for (ServletHolder holder : servlets.getServlets())
{
if (holder.getSource() == Source.EMBEDDED)
continue;
outholder(out, md, holder);
}
}
@ -273,6 +285,10 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration
{
for (ServletMapping mapping : servlets.getServletMappings())
{
ServletHolder sh = servlets.getServlet(mapping.getServletName());
if (sh != null && sh.getSource() == Source.EMBEDDED)
continue;
out.openTag("servlet-mapping", origin(md, mapping.getServletName() + ".servlet.mappings"));
out.tag("servlet-name", mapping.getServletName());
if (mapping.getPathSpecs() != null)

View File

@ -0,0 +1,47 @@
//
// ========================================================================
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under
// the terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0
//
// This Source Code may also be made available under the following
// Secondary Licenses when the conditions for such availability set
// forth in the Eclipse Public License, v. 2.0 are satisfied:
// the Apache License v2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.quickstart;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class FooFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
chain.doFilter(request, response);
}
@Override
public void destroy()
{
}
}

View File

@ -19,19 +19,23 @@
package org.eclipse.jetty.quickstart;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ListenerHolder;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -42,17 +46,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
public class TestQuickStart
{
File testDir;
File webInf;
Server server;
@BeforeEach
public void setUp()
{
testDir = MavenTestingUtils.getTargetTestingDir("foo");
FS.ensureEmpty(testDir);
webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
server = new Server();
}
@ -65,6 +63,11 @@ public class TestQuickStart
@Test
public void testProgrammaticOverrideOfDefaultServletMapping() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("pgoverride");
FS.ensureEmpty(testDir);
File webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
@ -87,27 +90,36 @@ public class TestQuickStart
assertTrue(quickstartXml.exists());
//now run the webapp again purely from the generated quickstart
//now run the webapp again
WebAppContext webapp = new WebAppContext();
webapp.setResourceBase(testDir.getAbsolutePath());
webapp.addConfiguration(new QuickStartConfiguration());
webapp.getServerClassMatcher().exclude("org.eclipse.jetty.quickstart.");
webapp.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.QUICKSTART);
webapp.setClassLoader(new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()));
//add in the servlet
webapp.getServletHandler().addServlet(fooHolder);
//add in the listener
webapp.getServletHandler().addListener(lholder);
server.setHandler(webapp);
server.setDryRun(false);
server.start();
server.dumpStdErr();
//verify that FooServlet is now mapped to / and not the DefaultServlet
ServletHolder sh = webapp.getServletHandler().getMappedServlet("/").getServletHolder();
assertNotNull(sh);
assertEquals("foo", sh.getName());
assertThat(sh.getClassName(), Matchers.equalTo("org.eclipse.jetty.quickstart.FooServlet"));
}
@Test
public void testDefaultContextPath() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("dfltcp");
FS.ensureEmpty(testDir);
File webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
@ -132,7 +144,7 @@ public class TestQuickStart
webapp.addConfiguration(new QuickStartConfiguration());
quickstart.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.QUICKSTART);
webapp.setResourceBase(testDir.getAbsolutePath());
webapp.setClassLoader(new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()));
webapp.getServerClassMatcher().exclude("org.eclipse.jetty.quickstart.");
server.setHandler(webapp);
server.setDryRun(false);
@ -146,6 +158,11 @@ public class TestQuickStart
@Test
public void testDefaultRequestAndResponseEncodings() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("dfltenc");
FS.ensureEmpty(testDir);
File webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
@ -168,7 +185,7 @@ public class TestQuickStart
webapp.addConfiguration(new QuickStartConfiguration());
quickstart.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.QUICKSTART);
webapp.setResourceBase(testDir.getAbsolutePath());
webapp.setClassLoader(new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()));
webapp.getServerClassMatcher().exclude("org.eclipse.jetty.quickstart.");
server.setHandler(webapp);
server.setDryRun(false);
@ -181,6 +198,11 @@ public class TestQuickStart
@Test
public void testListenersNotCalledInPreConfigure() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("listeners");
FS.ensureEmpty(testDir);
File webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
@ -203,4 +225,69 @@ public class TestQuickStart
assertTrue(quickstartXml.exists());
assertEquals(0, FooContextListener.___initialized);
}
@Test
public void testDuplicateGenerationFromContextXml() throws Exception
{
File testDir = MavenTestingUtils.getTargetTestingDir("dups");
FS.ensureEmpty(testDir);
File webInf = new File(testDir, "WEB-INF");
FS.ensureDirExists(webInf);
File quickstartXml = new File(webInf, "quickstart-web.xml");
assertFalse(quickstartXml.exists());
//no servlets, filters or listeners defined in web.xml
WebAppContext quickstart = new WebAppContext();
quickstart.addConfiguration(new QuickStartConfiguration());
quickstart.setWar(testDir.toURI().toURL().toExternalForm());
quickstart.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.GENERATE);
quickstart.setDescriptor(MavenTestingUtils.getTestResourceFile("web.xml").getAbsolutePath());
//apply the context xml file
XmlConfiguration xmlConfig = new XmlConfiguration(Resource.newResource(MavenTestingUtils.getTestResourceFile("context.xml")));
xmlConfig.configure(quickstart);
//generate the quickstart
server.setHandler(quickstart);
server.setDryRun(true);
server.start();
assertTrue(quickstartXml.exists());
assertTrue(server.isStopped());
//Make a new webappcontext to mimic starting the server over again with
//a freshly applied context xml
quickstart = new WebAppContext();
//need visibility of FooServlet, FooFilter, FooContextListener when we quickstart
quickstart.getServerClassMatcher().exclude("org.eclipse.jetty.quickstart.");
quickstart.addConfiguration(new QuickStartConfiguration());
quickstart.setWar(testDir.toURI().toURL().toExternalForm());
quickstart.setDescriptor(MavenTestingUtils.getTestResourceFile("web.xml").getAbsolutePath());
quickstart.setAttribute(QuickStartConfiguration.MODE, QuickStartConfiguration.Mode.AUTO);
server.setHandler(quickstart);
//apply the context xml file like a restart would
xmlConfig.configure(quickstart);
server.setDryRun(false);
//restart the server
server.start();
//test that we only get 1 FoOServlet, FooFilter and FooContextListener
ServletHolder[] servlets = quickstart.getServletHandler().getServlets();
assertNotNull(servlets);
assertEquals(1,
Arrays.stream(servlets).filter(s -> "org.eclipse.jetty.quickstart.FooServlet".equals(s.getClassName())).count());
FilterHolder[] filters = quickstart.getServletHandler().getFilters();
assertNotNull(filters);
assertEquals(1,
Arrays.stream(filters).filter(f -> "org.eclipse.jetty.quickstart.FooFilter".equals(f.getClassName())).count());
ListenerHolder[] listeners = quickstart.getServletHandler().getListeners();
assertNotNull(listeners);
assertEquals(1,
Arrays.stream(listeners).filter(l -> "org.eclipse.jetty.quickstart.FooContextListener".equals(l.getClassName())).count());
}
}

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<!-- ==================================================================
Configure and deploy the test web application in $(jetty.home)/webapps/test
Note. If this file did not exist or used a context path other that /test
then the default configuration of jetty.xml would discover the test
webapplication with a WebAppDeployer. By specifying a context in this
directory, additional configuration may be specified and hot deployments
detected.
===================================================================== -->
<Configure id="testWebapp" class="org.eclipse.jetty.webapp.WebAppContext">
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Required minimal context configuration : -->
<!-- + contextPath -->
<!-- + war OR resourceBase -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<Set name="contextPath">/test</Set>
<Get name="servletHandler">
<Call name="addServletWithMapping">
<Arg>
<New class="org.eclipse.jetty.servlet.ServletHolder">
<Set name="name">FooServlet</Set>
<Set name="className">org.eclipse.jetty.quickstart.FooServlet</Set>
</New>
</Arg>
<Arg>/outer/*</Arg>
</Call>
<Call name="addFilterWithMapping">
<Arg>
<New class="org.eclipse.jetty.servlet.FilterHolder">
<Set name="className">org.eclipse.jetty.quickstart.FooFilter</Set>
<Set name="name">OuterFilter</Set>
</New>
</Arg>
<Arg>/outer/*</Arg>
<Arg type="java.lang.Integer">0</Arg>
</Call>
<Call name="addListener">
<Arg>
<New class="org.eclipse.jetty.servlet.ListenerHolder">
<Set name="listener">
<New class="org.eclipse.jetty.quickstart.FooContextListener"></New>
</Set>
</New>
</Arg>
</Call>
</Get>
</Configure>