Skip to content

Commit

Permalink
Issue #4430 Quickstart duplicate servlets,filters,listeners from cont…
Browse files Browse the repository at this point in the history
…ext xml

Signed-off-by: Jan Bartel <[email protected]>
  • Loading branch information
janbartel committed Sep 22, 2020
1 parent a283c4c commit ec04a8b
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
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;
Expand Down Expand Up @@ -212,6 +213,9 @@ public void generateQuickStartWebXml(WebAppContext context, OutputStream stream)
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();
Expand All @@ -223,14 +227,20 @@ public void generateQuickStartWebXml(WebAppContext context, OutputStream stream)
{
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)
Expand Down Expand Up @@ -265,6 +275,8 @@ public void generateQuickStartWebXml(WebAppContext context, OutputStream stream)
{
for (ServletHolder holder : servlets.getServlets())
{
if (holder.getSource() == Source.EMBEDDED)
continue;
outholder(out, md, holder);
}
}
Expand All @@ -273,6 +285,10 @@ public void generateQuickStartWebXml(WebAppContext context, OutputStream stream)
{
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -42,17 +46,11 @@
*/
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();
}

Expand All @@ -65,6 +63,11 @@ public void tearDown() throws Exception
@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());

Expand All @@ -87,27 +90,36 @@ public void testProgrammaticOverrideOfDefaultServletMapping() throws Exception

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());

Expand All @@ -132,7 +144,7 @@ public void testDefaultContextPath() throws Exception
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);
Expand All @@ -146,6 +158,11 @@ public void testDefaultContextPath() throws Exception
@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());

Expand All @@ -168,7 +185,7 @@ public void testDefaultRequestAndResponseEncodings() throws Exception
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);
Expand All @@ -181,6 +198,11 @@ public void testDefaultRequestAndResponseEncodings() throws Exception
@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());

Expand All @@ -203,4 +225,69 @@ public void testListenersNotCalledInPreConfigure() throws Exception
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());
}
}
57 changes: 57 additions & 0 deletions jetty-quickstart/src/test/resources/context.xml
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit ec04a8b

Please sign in to comment.