Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

This commit is contained in:
Joakim Erdfelt 2020-09-22 09:15:59 -05:00
commit be07e84cd7
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
12 changed files with 439 additions and 613 deletions

View File

@ -96,6 +96,19 @@
<artifactId>jetty-slf4j-impl</artifactId> <artifactId>jetty-slf4j-impl</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>jetty-http-tools</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty.toolchain</groupId> <groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId> <artifactId>jetty-test-helper</artifactId>

View File

@ -20,7 +20,6 @@ package org.eclipse.jetty.webapp;
import java.io.InputStream; import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.file.Path; import java.nio.file.Path;
@ -45,6 +44,7 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue;
@ -79,7 +79,7 @@ public class WebAppClassLoaderTest
assertThat("Can Load Class [" + clazz + "]", _loader.loadClass(clazz), notNullValue()); assertThat("Can Load Class [" + clazz + "]", _loader.loadClass(clazz), notNullValue());
} }
public void assertCanLoadResource(String res) throws ClassNotFoundException public void assertCanLoadResource(String res)
{ {
assertThat("Can Load Resource [" + res + "]", _loader.getResource(res), notNullValue()); assertThat("Can Load Resource [" + res + "]", _loader.getResource(res), notNullValue());
} }
@ -112,7 +112,7 @@ public class WebAppClassLoaderTest
assertCantLoadClass("org.eclipse.jetty.webapp.Configuration"); assertCantLoadClass("org.eclipse.jetty.webapp.Configuration");
Class<?> clazzA = _loader.loadClass("org.acme.webapp.ClassInJarA"); Class<?> clazzA = _loader.loadClass("org.acme.webapp.ClassInJarA");
assertTrue(clazzA.getField("FROM_PARENT") != null); assertNotNull(clazzA.getField("FROM_PARENT"));
} }
@Test @Test
@ -131,21 +131,18 @@ public class WebAppClassLoaderTest
Class<?> clazzA = _loader.loadClass("org.acme.webapp.ClassInJarA"); Class<?> clazzA = _loader.loadClass("org.acme.webapp.ClassInJarA");
assertThrows(NoSuchFieldException.class, () -> assertThrows(NoSuchFieldException.class, () ->
{ clazzA.getField("FROM_PARENT"));
clazzA.getField("FROM_PARENT");
});
} }
@Test @Test
public void testClassFileTranslations() throws Exception public void testClassFileTranslations() throws Exception
{ {
final List<Object> results = new ArrayList<Object>(); final List<Object> results = new ArrayList<>();
_loader.addTransformer(new ClassFileTransformer() _loader.addTransformer(new ClassFileTransformer()
{ {
@Override @Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{ {
results.add(loader); results.add(loader);
byte[] b = new byte[classfileBuffer.length]; byte[] b = new byte[classfileBuffer.length];
@ -160,7 +157,6 @@ public class WebAppClassLoaderTest
{ {
@Override @Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{ {
results.add(className); results.add(className);
byte[] b = new byte[classfileBuffer.length]; byte[] b = new byte[classfileBuffer.length];
@ -196,7 +192,6 @@ public class WebAppClassLoaderTest
{ {
@Override @Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{ {
return null; return null;
} }
@ -235,7 +230,6 @@ public class WebAppClassLoaderTest
assertCantLoadClass("org.eclipse.jetty.webapp.JarScanner"); assertCantLoadClass("org.eclipse.jetty.webapp.JarScanner");
} }
@SuppressWarnings("deprecation")
@Test @Test
public void testSystemServerClassDeprecated() throws Exception public void testSystemServerClassDeprecated() throws Exception
{ {
@ -377,7 +371,7 @@ public class WebAppClassLoaderTest
} }
@Test @Test
public void ordering() throws Exception public void testClashingResource() throws Exception
{ {
// The existence of a URLStreamHandler changes the behavior // The existence of a URLStreamHandler changes the behavior
assumeTrue(URLStreamHandlerUtil.getFactory() == null, "URLStreamHandler changes behavior, skip test"); assumeTrue(URLStreamHandlerUtil.getFactory() == null, "URLStreamHandler changes behavior, skip test");

View File

@ -1,216 +0,0 @@
//
// ========================================================================
// 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.webapp;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.resource.PathResource;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class WebAppContextExtraClasspathTest
{
private Server server;
private Server newServer()
{
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
return server;
}
@AfterEach
public void tearDown()
{
LifeCycle.stop(server);
}
@Test
public void testBaseResourceAbsolutePath() throws Exception
{
Server server = newServer();
WebAppContext context = new WebAppContext();
context.setContextPath("/");
Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
warPath = warPath.toAbsolutePath();
assertTrue(warPath.isAbsolute(), "Path should be absolute: " + warPath);
// Use String reference to war
// On Unix / Linux this should have no issue.
// On Windows with fully qualified paths such as "E:\mybase\webapps\dump.war" the
// resolution of the Resource can trigger various URI issues with the "E:" portion of the provided String.
context.setResourceBase(warPath.toString());
server.setHandler(context);
server.start();
assertTrue(context.isAvailable(), "WebAppContext should be available");
}
public static Stream<Arguments> extraClasspathGlob()
{
List<Arguments> references = new ArrayList<>();
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
// Absolute reference with trailing slash and glob
references.add(Arguments.of(extLibs.toString() + File.separator + "*"));
// Establish a relative extraClassPath reference
String relativeExtLibsDir = MavenTestingUtils.getBasePath().relativize(extLibs).toString();
// This will be in the String form similar to "src/test/resources/ext/*" (with trailing slash and glob)
references.add(Arguments.of(relativeExtLibsDir + File.separator + "*"));
return references.stream();
}
/**
* Test using WebAppContext.setExtraClassPath(String) with a reference to a glob
*/
@ParameterizedTest
@MethodSource("extraClasspathGlob")
public void testExtraClasspathGlob(String extraClasspathGlobReference) throws Exception
{
Server server = newServer();
WebAppContext context = new WebAppContext();
context.setContextPath("/");
Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
context.setBaseResource(new PathResource(warPath));
context.setExtraClasspath(extraClasspathGlobReference);
server.setHandler(context);
server.start();
// Should not have failed the start of the WebAppContext
assertTrue(context.isAvailable(), "WebAppContext should be available");
// Test WebAppClassLoader contents for expected jars
ClassLoader contextClassLoader = context.getClassLoader();
assertThat(contextClassLoader, instanceOf(WebAppClassLoader.class));
WebAppClassLoader webAppClassLoader = (WebAppClassLoader)contextClassLoader;
Path extLibsDir = MavenTestingUtils.getTestResourcePathDir("ext");
extLibsDir = extLibsDir.toAbsolutePath();
List<Path> expectedPaths = Files.list(extLibsDir)
.filter(Files::isRegularFile)
.filter((path) -> path.toString().endsWith(".jar"))
.collect(Collectors.toList());
List<Path> actualPaths = new ArrayList<>();
for (URL url : webAppClassLoader.getURLs())
{
actualPaths.add(Paths.get(url.toURI()));
}
assertThat("WebAppClassLoader.urls.length", actualPaths.size(), is(expectedPaths.size()));
for (Path expectedPath : expectedPaths)
{
boolean found = false;
for (Path actualPath : actualPaths)
{
if (Files.isSameFile(actualPath, expectedPath))
{
found = true;
}
}
assertTrue(found, "Not able to find expected jar in WebAppClassLoader: " + expectedPath);
}
}
public static Stream<Arguments> extraClasspathDir()
{
List<Arguments> references = new ArrayList<>();
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
// Absolute reference with trailing slash
references.add(Arguments.of(extLibs.toString() + File.separator));
// Absolute reference without trailing slash
references.add(Arguments.of(extLibs.toString()));
// Establish a relative extraClassPath reference
String relativeExtLibsDir = MavenTestingUtils.getBasePath().relativize(extLibs).toString();
// This will be in the String form similar to "src/test/resources/ext/" (with trailing slash)
references.add(Arguments.of(relativeExtLibsDir + File.separator));
// This will be in the String form similar to "src/test/resources/ext/" (without trailing slash)
references.add(Arguments.of(relativeExtLibsDir));
return references.stream();
}
/**
* Test using WebAppContext.setExtraClassPath(String) with a reference to a directory
*/
@ParameterizedTest
@MethodSource("extraClasspathDir")
public void testExtraClasspathDir(String extraClassPathReference) throws Exception
{
Server server = newServer();
WebAppContext context = new WebAppContext();
context.setContextPath("/");
Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
context.setBaseResource(new PathResource(warPath));
context.setExtraClasspath(extraClassPathReference);
server.setHandler(context);
server.start();
// Should not have failed the start of the WebAppContext
assertTrue(context.isAvailable(), "WebAppContext should be available");
// Test WebAppClassLoader contents for expected directory reference
ClassLoader contextClassLoader = context.getClassLoader();
assertThat(contextClassLoader, instanceOf(WebAppClassLoader.class));
WebAppClassLoader webAppClassLoader = (WebAppClassLoader)contextClassLoader;
URL[] urls = webAppClassLoader.getURLs();
assertThat("URLs", urls.length, is(1));
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
assertThat("URL[0]", urls[0].toURI(), is(extLibs.toUri()));
}
}

View File

@ -19,70 +19,83 @@
package org.eclipse.jetty.webapp; package org.eclipse.jetty.webapp;
import java.io.File; import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.GenericServlet; import javax.servlet.GenericServlet;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.tools.HttpTester;
import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.HotSwapHandler;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.resource.PathResource; import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ExtendWith(WorkDirExtension.class)
public class WebAppContextTest public class WebAppContextTest
{ {
public class MySessionListener implements HttpSessionListener public static final Logger LOG = LoggerFactory.getLogger(WebAppContextTest.class);
{ public WorkDir workDir;
@Override private final List<Object> lifeCycles = new ArrayList<>();
public void sessionCreated(HttpSessionEvent se)
{
}
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
}
}
@AfterEach @AfterEach
public void tearDown() public void tearDown()
{ {
lifeCycles.forEach(LifeCycle::stop);
Configurations.cleanKnown(); Configurations.cleanKnown();
} }
private Server newServer()
{
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
lifeCycles.add(server);
return server;
}
@Test @Test
public void testDefaultContextPath() throws Exception public void testDefaultContextPath() throws Exception
{ {
Server server = new Server(); Server server = newServer();
File webXml = MavenTestingUtils.getTestResourceFile("web-with-default-context-path.xml"); File webXml = MavenTestingUtils.getTestResourceFile("web-with-default-context-path.xml");
File webXmlEmptyPath = MavenTestingUtils.getTestResourceFile("web-with-empty-default-context-path.xml"); File webXmlEmptyPath = MavenTestingUtils.getTestResourceFile("web-with-empty-default-context-path.xml");
File webDefaultXml = MavenTestingUtils.getTestResourceFile("web-default-with-default-context-path.xml"); File webDefaultXml = MavenTestingUtils.getTestResourceFile("web-default-with-default-context-path.xml");
@ -92,66 +105,43 @@ public class WebAppContextTest
assertNotNull(overrideWebXml); assertNotNull(overrideWebXml);
assertNotNull(webXmlEmptyPath); assertNotNull(webXmlEmptyPath);
try
{
WebAppContext wac = new WebAppContext();
wac.setResourceBase(MavenTestingUtils.getTargetTestingDir().getAbsolutePath());
server.setHandler(wac);
//test that an empty default-context-path defaults to root
wac.setDescriptor(webXmlEmptyPath.getAbsolutePath());
server.start();
assertEquals("/", wac.getContextPath());
server.stop();
//test web-default.xml value is used
wac.setDescriptor(null);
wac.setDefaultsDescriptor(webDefaultXml.getAbsolutePath());
server.start();
assertEquals("/one", wac.getContextPath());
server.stop();
//test web.xml value is used
wac.setDescriptor(webXml.getAbsolutePath());
server.start();
assertEquals("/two", wac.getContextPath());
server.stop();
//test override-web.xml value is used
wac.setOverrideDescriptor(overrideWebXml.getAbsolutePath());
server.start();
assertEquals("/three", wac.getContextPath());
server.stop();
//test that explicitly set context path is used instead
wac.setContextPath("/foo");
server.start();
assertEquals("/foo", wac.getContextPath());
}
finally
{
server.stop();
}
}
@Test
public void testSessionListeners()
{
Server server = new Server();
WebAppContext wac = new WebAppContext(); WebAppContext wac = new WebAppContext();
wac.setResourceBase(MavenTestingUtils.getTargetTestingDir().getAbsolutePath());
wac.setServer(server);
server.setHandler(wac); server.setHandler(wac);
wac.addEventListener(new MySessionListener());
Collection<MySessionListener> listeners = wac.getSessionHandler().getBeans(MySessionListener.class); //test that an empty default-context-path defaults to root
assertNotNull(listeners); wac.setDescriptor(webXmlEmptyPath.getAbsolutePath());
assertEquals(1, listeners.size()); server.start();
assertEquals("/", wac.getContextPath());
server.stop();
//test web-default.xml value is used
wac.setDescriptor(null);
wac.setDefaultsDescriptor(webDefaultXml.getAbsolutePath());
server.start();
assertEquals("/one", wac.getContextPath());
server.stop();
//test web.xml value is used
wac.setDescriptor(webXml.getAbsolutePath());
server.start();
assertEquals("/two", wac.getContextPath());
server.stop();
//test override-web.xml value is used
wac.setOverrideDescriptor(overrideWebXml.getAbsolutePath());
server.start();
assertEquals("/three", wac.getContextPath());
server.stop();
//test that explicitly set context path is used instead
wac.setContextPath("/foo");
server.start();
assertEquals("/foo", wac.getContextPath());
} }
@Test @Test
@ -159,11 +149,11 @@ public class WebAppContextTest
{ {
Configurations.cleanKnown(); Configurations.cleanKnown();
String[] knownAndEnabled = Configurations.getKnown().stream() String[] knownAndEnabled = Configurations.getKnown().stream()
.filter(c -> c.isEnabledByDefault()) .filter(Configuration::isEnabledByDefault)
.map(c -> c.getClass().getName()) .map(c -> c.getClass().getName())
.toArray(String[]::new); .toArray(String[]::new);
Server server = new Server(); Server server = newServer();
//test if no classnames set, its the defaults //test if no classnames set, its the defaults
WebAppContext wac = new WebAppContext(); WebAppContext wac = new WebAppContext();
@ -174,7 +164,7 @@ public class WebAppContextTest
String[] classNames = wac.getConfigurationClasses(); String[] classNames = wac.getConfigurationClasses();
assertNotNull(classNames); assertNotNull(classNames);
//test if no classname set, and none from server its the defaults // test if no classname set, and none from server its the defaults
wac.setServer(server); wac.setServer(server);
assertTrue(Arrays.equals(classNames, wac.getConfigurationClasses())); assertTrue(Arrays.equals(classNames, wac.getConfigurationClasses()));
} }
@ -214,7 +204,7 @@ public class WebAppContextTest
//test that explicit config instances override any from server //test that explicit config instances override any from server
String[] classNames = {"x.y.z"}; String[] classNames = {"x.y.z"};
Server server = new Server(); Server server = newServer();
server.setAttribute(Configuration.ATTR, classNames); server.setAttribute(Configuration.ATTR, classNames);
wac.setServer(server); wac.setServer(server);
assertThat(wac.getConfigurations(), Matchers.contains(configs)); assertThat(wac.getConfigurations(), Matchers.contains(configs));
@ -223,7 +213,7 @@ public class WebAppContextTest
@Test @Test
public void testRealPathDoesNotExist() throws Exception public void testRealPathDoesNotExist() throws Exception
{ {
Server server = new Server(0); Server server = newServer();
WebAppContext context = new WebAppContext(".", "/"); WebAppContext context = new WebAppContext(".", "/");
server.setHandler(context); server.setHandler(context);
server.start(); server.start();
@ -241,7 +231,7 @@ public class WebAppContextTest
@Test @Test
public void testContextWhiteList() throws Exception public void testContextWhiteList() throws Exception
{ {
Server server = new Server(0); Server server = newServer();
HandlerList handlers = new HandlerList(); HandlerList handlers = new HandlerList();
WebAppContext contextA = new WebAppContext(".", "/A"); WebAppContext contextA = new WebAppContext(".", "/A");
@ -268,22 +258,20 @@ public class WebAppContextTest
@Test @Test
public void testAlias() throws Exception public void testAlias() throws Exception
{ {
File dir = File.createTempFile("dir", null); Path tempDir = workDir.getEmptyPathDir().resolve("dir");
dir.delete(); FS.ensureEmpty(tempDir);
dir.mkdir();
dir.deleteOnExit();
File webinf = new File(dir, "WEB-INF"); Path webinf = tempDir.resolve("WEB-INF");
webinf.mkdir(); FS.ensureEmpty(webinf);
File classes = new File(dir, "classes"); Path classes = tempDir.resolve("classes");
classes.mkdir(); FS.ensureEmpty(classes);
File someclass = new File(classes, "SomeClass.class"); Path someClass = classes.resolve("SomeClass.class");
someclass.createNewFile(); FS.touch(someClass);
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();
context.setBaseResource(new ResourceCollection(dir.getAbsolutePath())); context.setBaseResource(new PathResource(tempDir));
context.setResourceAlias("/WEB-INF/classes/", "/classes/"); context.setResourceAlias("/WEB-INF/classes/", "/classes/");
@ -295,6 +283,7 @@ public class WebAppContextTest
public void testIsProtected() public void testIsProtected()
{ {
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();
assertTrue(context.isProtectedTarget("/web-inf/lib/foo.jar")); assertTrue(context.isProtectedTarget("/web-inf/lib/foo.jar"));
assertTrue(context.isProtectedTarget("/meta-inf/readme.txt")); assertTrue(context.isProtectedTarget("/meta-inf/readme.txt"));
assertFalse(context.isProtectedTarget("/something-else/web-inf")); assertFalse(context.isProtectedTarget("/something-else/web-inf"));
@ -303,11 +292,13 @@ public class WebAppContextTest
@Test @Test
public void testNullPath() throws Exception public void testNullPath() throws Exception
{ {
Server server = new Server(0); Server server = newServer();
HandlerList handlers = new HandlerList(); HandlerList handlers = new HandlerList();
ContextHandlerCollection contexts = new ContextHandlerCollection(); ContextHandlerCollection contexts = new ContextHandlerCollection();
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();
context.setBaseResource(Resource.newResource("./src/test/webapp")); Path testWebapp = MavenTestingUtils.getProjectDirPath("src/test/webapp");
context.setBaseResource(new PathResource(testWebapp));
context.setContextPath("/"); context.setContextPath("/");
server.setHandler(handlers); server.setHandler(handlers);
handlers.addHandler(contexts); handlers.addHandler(contexts);
@ -318,27 +309,24 @@ public class WebAppContextTest
server.start(); server.start();
try String rawResponse = connector.getResponse("GET http://localhost:8080 HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n");
{ HttpTester.Response response = HttpTester.parseResponse(rawResponse);
String response = connector.getResponse("GET http://localhost:8080 HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n"); assertThat("Response OK", response.getStatus(), is(HttpStatus.OK_200));
assertThat("Response OK", response, containsString("200 OK"));
}
finally
{
server.stop();
}
} }
@Test @Test
public void testNullSessionAndSecurityHandler() throws Exception public void testNullSessionAndSecurityHandler() throws Exception
{ {
Server server = new Server(0); Server server = newServer();
HandlerList handlers = new HandlerList(); HandlerList handlers = new HandlerList();
ContextHandlerCollection contexts = new ContextHandlerCollection(); ContextHandlerCollection contexts = new ContextHandlerCollection();
WebAppContext context = new WebAppContext(null, null, null, null, null, new ErrorPageErrorHandler(), WebAppContext context = new WebAppContext(null, null, null, null, null, new ErrorPageErrorHandler(),
ServletContextHandler.NO_SESSIONS | ServletContextHandler.NO_SECURITY); ServletContextHandler.NO_SESSIONS | ServletContextHandler.NO_SECURITY);
context.setContextPath("/"); context.setContextPath("/");
context.setBaseResource(Resource.newResource("./src/test/webapp"));
Path testWebapp = MavenTestingUtils.getProjectDirPath("src/test/webapp");
context.setBaseResource(new PathResource(testWebapp));
server.setHandler(handlers); server.setHandler(handlers);
handlers.addHandler(contexts); handlers.addHandler(contexts);
contexts.addHandler(context); contexts.addHandler(context);
@ -346,18 +334,11 @@ public class WebAppContextTest
LocalConnector connector = new LocalConnector(server); LocalConnector connector = new LocalConnector(server);
server.addConnector(connector); server.addConnector(connector);
try server.start();
{ assertTrue(context.isAvailable());
server.start();
assertTrue(context.isAvailable());
}
finally
{
server.stop();
}
} }
class ServletA extends GenericServlet static class ServletA extends GenericServlet
{ {
@Override @Override
public void service(ServletRequest req, ServletResponse res) public void service(ServletRequest req, ServletResponse res)
@ -366,7 +347,7 @@ public class WebAppContextTest
} }
} }
class ServletB extends GenericServlet static class ServletB extends GenericServlet
{ {
@Override @Override
public void service(ServletRequest req, ServletResponse res) public void service(ServletRequest req, ServletResponse res)
@ -376,120 +357,153 @@ public class WebAppContextTest
} }
@Test @Test
public void testServletContextListener() throws Exception public void testBaseResourceAbsolutePath() throws Exception
{ {
Server server = new Server(); Server server = newServer();
HotSwapHandler swap = new HotSwapHandler();
server.setHandler(swap); WebAppContext context = new WebAppContext();
context.setContextPath("/");
Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
warPath = warPath.toAbsolutePath();
assertTrue(warPath.isAbsolute(), "Path should be absolute: " + warPath);
// Use String reference to war
// On Unix / Linux this should have no issue.
// On Windows with fully qualified paths such as "E:\mybase\webapps\dump.war" the
// resolution of the Resource can trigger various URI issues with the "E:" portion of the provided String.
context.setResourceBase(warPath.toString());
server.setHandler(context);
server.start(); server.start();
ServletContextHandler context = new ServletContextHandler( assertTrue(context.isAvailable(), "WebAppContext should be available");
ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.setResourceBase(System.getProperty("java.io.tmpdir"));
final List<String> history = new ArrayList<>();
context.addEventListener(new ServletContextListener()
{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
history.add("I0");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
history.add("D0");
}
});
context.addEventListener(new ServletContextListener()
{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
history.add("I1");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
history.add("D1");
throw new RuntimeException("Listener1 destroy broken");
}
});
context.addEventListener(new ServletContextListener()
{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
history.add("I2");
throw new RuntimeException("Listener2 init broken");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
history.add("D2");
}
});
context.addEventListener(new ServletContextListener()
{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
history.add("I3");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
history.add("D3");
}
});
try
{
swap.setHandler(context);
context.start();
}
catch (Exception e)
{
history.add(e.getMessage());
}
finally
{
try
{
swap.setHandler(null);
}
catch (Exception e)
{
while (e.getCause() instanceof Exception)
{
e = (Exception)e.getCause();
}
history.add(e.getMessage());
}
}
assertThat(history, contains("I0", "I1", "I2", "Listener2 init broken", "D1", "D0", "Listener1 destroy broken"));
server.stop();
} }
@Test public static Stream<Arguments> extraClasspathGlob()
public void ordering() throws Exception
{ {
Path testWebappDir = MavenTestingUtils.getProjectDirPath("src/test/webapp"); List<Arguments> references = new ArrayList<>();
Resource webapp = new PathResource(testWebappDir);
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
// Absolute reference with trailing slash and glob
references.add(Arguments.of(extLibs.toString() + File.separator + "*"));
// Establish a relative extraClassPath reference
String relativeExtLibsDir = MavenTestingUtils.getBasePath().relativize(extLibs).toString();
// This will be in the String form similar to "src/test/resources/ext/*" (with trailing slash and glob)
references.add(Arguments.of(relativeExtLibsDir + File.separator + "*"));
return references.stream();
}
/**
* Test using WebAppContext.setExtraClassPath(String) with a reference to a glob
*/
@ParameterizedTest
@MethodSource("extraClasspathGlob")
public void testExtraClasspathGlob(String extraClasspathGlobReference) throws Exception
{
Server server = newServer();
WebAppContext context = new WebAppContext(); WebAppContext context = new WebAppContext();
context.setBaseResource(webapp); context.setContextPath("/");
context.setContextPath("/test"); Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
context.setServer(new Server()); context.setBaseResource(new PathResource(warPath));
new MetaInfConfiguration().preConfigure(context); context.setExtraClasspath(extraClasspathGlobReference);
assertEquals(Arrays.asList("acme.jar", "alpha.jar", "omega.jar"),
context.getMetaData().getWebInfResources(false).stream().map(r -> r.getURI().toString().replaceFirst(".+/", "")).collect(Collectors.toList())); server.setHandler(context);
server.start();
// Should not have failed the start of the WebAppContext
assertTrue(context.isAvailable(), "WebAppContext should be available");
// Test WebAppClassLoader contents for expected jars
ClassLoader contextClassLoader = context.getClassLoader();
assertThat(contextClassLoader, instanceOf(WebAppClassLoader.class));
WebAppClassLoader webAppClassLoader = (WebAppClassLoader)contextClassLoader;
Path extLibsDir = MavenTestingUtils.getTestResourcePathDir("ext");
extLibsDir = extLibsDir.toAbsolutePath();
List<Path> expectedPaths = Files.list(extLibsDir)
.filter(Files::isRegularFile)
.filter((path) -> path.toString().endsWith(".jar"))
.collect(Collectors.toList());
List<Path> actualPaths = new ArrayList<>();
for (URL url : webAppClassLoader.getURLs())
{
actualPaths.add(Paths.get(url.toURI()));
}
assertThat("WebAppClassLoader.urls.length", actualPaths.size(), is(expectedPaths.size()));
for (Path expectedPath : expectedPaths)
{
boolean found = false;
for (Path actualPath : actualPaths)
{
if (Files.isSameFile(actualPath, expectedPath))
{
found = true;
}
}
assertTrue(found, "Not able to find expected jar in WebAppClassLoader: " + expectedPath);
}
}
public static Stream<Arguments> extraClasspathDir()
{
List<Arguments> references = new ArrayList<>();
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
// Absolute reference with trailing slash
references.add(Arguments.of(extLibs.toString() + File.separator));
// Absolute reference without trailing slash
references.add(Arguments.of(extLibs.toString()));
// Establish a relative extraClassPath reference
String relativeExtLibsDir = MavenTestingUtils.getBasePath().relativize(extLibs).toString();
// This will be in the String form similar to "src/test/resources/ext/" (with trailing slash)
references.add(Arguments.of(relativeExtLibsDir + File.separator));
// This will be in the String form similar to "src/test/resources/ext/" (without trailing slash)
references.add(Arguments.of(relativeExtLibsDir));
return references.stream();
}
/**
* Test using WebAppContext.setExtraClassPath(String) with a reference to a directory
*/
@ParameterizedTest
@MethodSource("extraClasspathDir")
public void testExtraClasspathDir(String extraClassPathReference) throws Exception
{
Server server = newServer();
WebAppContext context = new WebAppContext();
context.setContextPath("/");
Path warPath = MavenTestingUtils.getTestResourcePathFile("wars/dump.war");
context.setBaseResource(new PathResource(warPath));
context.setExtraClasspath(extraClassPathReference);
server.setHandler(context);
server.start();
// Should not have failed the start of the WebAppContext
assertTrue(context.isAvailable(), "WebAppContext should be available");
// Test WebAppClassLoader contents for expected directory reference
ClassLoader contextClassLoader = context.getClassLoader();
assertThat(contextClassLoader, instanceOf(WebAppClassLoader.class));
WebAppClassLoader webAppClassLoader = (WebAppClassLoader)contextClassLoader;
URL[] urls = webAppClassLoader.getURLs();
assertThat("URLs", urls.length, is(1));
Path extLibs = MavenTestingUtils.getTestResourcePathDir("ext");
extLibs = extLibs.toAbsolutePath();
assertThat("URL[0]", urls[0].toURI(), is(extLibs.toUri()));
} }
} }

View File

@ -18,14 +18,16 @@
package org.eclipse.jetty.server.session; package org.eclipse.jetty.server.session;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.net.HttpCookie; import java.net.HttpCookie;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
@ -34,17 +36,25 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener; import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.in; import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -58,8 +68,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* *
* Test that session listeners are called. * Test that session listeners are called.
*/ */
@ExtendWith(WorkDirExtension.class)
public class SessionListenerTest public class SessionListenerTest
{ {
public WorkDir workDir;
/** /**
* Test that listeners are called when a session is deliberately invalidated. * Test that listeners are called when a session is deliberately invalidated.
*/ */
@ -73,8 +86,8 @@ public class SessionListenerTest
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT); cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); TestSessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)storeFactory).setGracePeriodSec(scavengePeriod); storeFactory.setGracePeriodSec(scavengePeriod);
TestServer server = new TestServer(0, inactivePeriod, scavengePeriod, TestServer server = new TestServer(0, inactivePeriod, scavengePeriod,
cacheFactory, storeFactory); cacheFactory, storeFactory);
@ -99,7 +112,7 @@ public class SessionListenerTest
ContentResponse response1 = client.GET(url + "?action=init"); ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
String sessionCookie = response1.getHeaders().get("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertNotNull(sessionCookie);
assertTrue(TestServlet.bindingListener.bound); assertTrue(TestServlet.bindingListener.bound);
String sessionId = TestServer.extractSessionId(sessionCookie); String sessionId = TestServer.extractSessionId(sessionCookie);
@ -115,12 +128,12 @@ public class SessionListenerTest
} }
finally finally
{ {
client.stop(); LifeCycle.stop(client);
} }
} }
finally finally
{ {
server.stop(); LifeCycle.stop(server);
} }
} }
@ -131,17 +144,20 @@ public class SessionListenerTest
@Test @Test
public void testSessionExpiresWithListener() throws Exception public void testSessionExpiresWithListener() throws Exception
{ {
Path foodir = workDir.getEmptyPathDir();
Path fooClass = foodir.resolve("Foo.class");
//Use a class that would only be known to the webapp classloader //Use a class that would only be known to the webapp classloader
InputStream foostream = Thread.currentThread().getContextClassLoader().getResourceAsStream("Foo.clazz"); try (InputStream foostream = Thread.currentThread().getContextClassLoader().getResourceAsStream("Foo.clazz");
File foodir = new File(MavenTestingUtils.getTargetDir(), "foo"); OutputStream out = Files.newOutputStream(fooClass))
foodir.mkdirs(); {
File fooclass = new File(foodir, "Foo.class"); IO.copy(foostream, out);
IO.copy(foostream, new FileOutputStream(fooclass)); }
assertTrue(fooclass.exists()); assertTrue(Files.exists(fooClass));
assertTrue(fooclass.length() != 0); assertThat(Files.size(fooClass), greaterThan(0L));
URL[] foodirUrls = new URL[]{foodir.toURI().toURL()}; URL[] foodirUrls = new URL[]{foodir.toUri().toURL()};
URLClassLoader contextClassLoader = new URLClassLoader(foodirUrls, Thread.currentThread().getContextClassLoader()); URLClassLoader contextClassLoader = new URLClassLoader(foodirUrls, Thread.currentThread().getContextClassLoader());
String contextPath = "/"; String contextPath = "/";
@ -151,8 +167,8 @@ public class SessionListenerTest
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT); cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); TestSessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)storeFactory).setGracePeriodSec(scavengePeriod); storeFactory.setGracePeriodSec(scavengePeriod);
TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod, TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod,
cacheFactory, storeFactory); cacheFactory, storeFactory);
@ -164,31 +180,38 @@ public class SessionListenerTest
TestHttpSessionListener listener = new TestHttpSessionListenerWithWebappClasses(true); TestHttpSessionListener listener = new TestHttpSessionListenerWithWebappClasses(true);
context.getSessionHandler().addEventListener(listener); context.getSessionHandler().addEventListener(listener);
server1.start();
int port1 = server1.getPort();
try try
{ {
server1.start();
int port1 = server1.getPort();
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
client.start(); try
String url = "http://localhost:" + port1 + contextPath + servletMapping.substring(1); {
client.start();
String url = "http://localhost:" + port1 + contextPath + servletMapping.substring(1);
//make a request to set up a session on the server //make a request to set up a session on the server
ContentResponse response1 = client.GET(url + "?action=init"); ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
String sessionCookie = response1.getHeaders().get("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertNotNull(sessionCookie);
String sessionId = TestServer.extractSessionId(sessionCookie); String sessionId = TestServer.extractSessionId(sessionCookie);
assertThat(sessionId, is(in(listener.createdSessions))); assertThat(sessionId, is(in(listener.createdSessions)));
//and wait until the session should have expired //and wait until the session should have expired
Thread.currentThread().sleep(TimeUnit.SECONDS.toMillis(inactivePeriod + (2 * scavengePeriod))); Thread.sleep(TimeUnit.SECONDS.toMillis(inactivePeriod + (2 * scavengePeriod)));
assertThat(sessionId, is(in(listener.destroyedSessions))); assertThat(sessionId, is(in(listener.destroyedSessions)));
assertNull(listener.ex); assertNull(listener.ex);
}
finally
{
LifeCycle.stop(client);
}
} }
finally finally
{ {
@ -209,8 +232,8 @@ public class SessionListenerTest
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory(); DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT); cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
SessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory(); TestSessionDataStoreFactory storeFactory = new TestSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)storeFactory).setGracePeriodSec(scavengePeriod); storeFactory.setGracePeriodSec(scavengePeriod);
TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod, TestServer server1 = new TestServer(0, inactivePeriod, scavengePeriod,
cacheFactory, storeFactory); cacheFactory, storeFactory);
@ -222,11 +245,11 @@ public class SessionListenerTest
context.getSessionHandler().addEventListener(listener); context.getSessionHandler().addEventListener(listener);
server1.start();
int port1 = server1.getPort();
try try
{ {
server1.start();
int port1 = server1.getPort();
//save a session that has already expired //save a session that has already expired
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
SessionData data = context.getSessionHandler().getSessionCache().getSessionDataStore().newSessionData("1234", now - 10, now - 5, now - 10, 30000); SessionData data = context.getSessionHandler().getSessionCache().getSessionDataStore().newSessionData("1234", now - 10, now - 5, now - 10, 30000);
@ -234,24 +257,31 @@ public class SessionListenerTest
context.getSessionHandler().getSessionCache().getSessionDataStore().store("1234", data); context.getSessionHandler().getSessionCache().getSessionDataStore().store("1234", data);
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
client.start(); try
{
client.start();
port1 = server1.getPort(); port1 = server1.getPort();
String url = "http://localhost:" + port1 + contextPath + servletMapping.substring(1); String url = "http://localhost:" + port1 + contextPath + servletMapping.substring(1);
//make another request using the id of the expired session //make another request using the id of the expired session
Request request = client.newRequest(url + "?action=test"); Request request = client.newRequest(url + "?action=test");
request.cookie(new HttpCookie("JSESSIONID", "1234")); request.cookie(new HttpCookie("JSESSIONID", "1234"));
ContentResponse response = request.send(); ContentResponse response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus()); assertEquals(HttpServletResponse.SC_OK, response.getStatus());
//should be a new session id //should be a new session id
String cookie2 = response.getHeaders().get("Set-Cookie"); String cookie2 = response.getHeaders().get("Set-Cookie");
assertNotEquals("1234", TestServer.extractSessionId(cookie2)); assertNotEquals("1234", TestServer.extractSessionId(cookie2));
assertTrue(listener.destroyedSessions.contains("1234")); assertTrue(listener.destroyedSessions.contains("1234"));
assertNull(listener.ex); assertNull(listener.ex);
}
finally
{
LifeCycle.stop(client);
}
} }
finally finally
{ {
@ -259,6 +289,42 @@ public class SessionListenerTest
} }
} }
public static class MyHttpSessionListener implements HttpSessionListener
{
@Override
public void sessionCreated(HttpSessionEvent se)
{
}
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
}
}
@Test
public void testSessionListeners()
{
Server server = new Server();
try
{
WebAppContext wac = new WebAppContext();
wac.setServer(server);
server.setHandler(wac);
wac.addEventListener(new MyHttpSessionListener());
Collection<MyHttpSessionListener> listeners = wac.getSessionHandler().getBeans(MyHttpSessionListener.class);
assertNotNull(listeners);
assertEquals(1, listeners.size());
}
finally
{
LifeCycle.stop(server);
}
}
public static class MySessionBindingListener implements HttpSessionBindingListener, Serializable public static class MySessionBindingListener implements HttpSessionBindingListener, Serializable
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -314,7 +380,7 @@ public class SessionListenerTest
if ("test".equals(action)) if ("test".equals(action))
{ {
HttpSession session = request.getSession(true); HttpSession session = request.getSession(true);
assertTrue(session != null); assertNotNull(session);
} }
} }
} }

View File

@ -18,6 +18,7 @@
package com.acme.test; package com.acme.test;
import java.util.logging.Logger;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextAttributeListener;
@ -35,69 +36,77 @@ import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; import javax.servlet.http.HttpSessionListener;
@WebListener @WebListener
public class AnnotatedListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener public class AnnotatedListener implements HttpSessionListener,
HttpSessionAttributeListener,
HttpSessionActivationListener,
ServletContextListener,
ServletContextAttributeListener,
ServletRequestListener,
ServletRequestAttributeListener
{ {
private static final Logger LOG = Logger.getLogger(AnnotatedListener.class.getName());
@Resource(mappedName = "maxAmount") @Resource(mappedName = "maxAmount")
private Double maxAmount; private Double maxAmount;
@Override @Override
public void attributeAdded(HttpSessionBindingEvent se) public void attributeAdded(HttpSessionBindingEvent se)
{ {
// System.err.println("attributedAdded "+se); LOG.fine("attributedAdded " + se);
} }
@Override @Override
public void attributeAdded(ServletContextAttributeEvent scab) public void attributeAdded(ServletContextAttributeEvent scae)
{ {
// System.err.println("attributeAdded "+scab); LOG.fine("attributeAdded " + scae);
} }
@Override @Override
public void attributeAdded(ServletRequestAttributeEvent srae) public void attributeAdded(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeAdded "+srae); LOG.fine("attributeAdded " + srae);
} }
@Override @Override
public void attributeRemoved(HttpSessionBindingEvent se) public void attributeRemoved(HttpSessionBindingEvent se)
{ {
// System.err.println("attributeRemoved "+se); LOG.fine("attributeRemoved " + se);
} }
@Override @Override
public void attributeRemoved(ServletContextAttributeEvent scab) public void attributeRemoved(ServletContextAttributeEvent scab)
{ {
// System.err.println("attributeRemoved "+scab); LOG.fine("attributeRemoved " + scab);
} }
@Override @Override
public void attributeRemoved(ServletRequestAttributeEvent srae) public void attributeRemoved(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeRemoved "+srae); LOG.fine("attributeRemoved " + srae);
} }
@Override @Override
public void attributeReplaced(HttpSessionBindingEvent se) public void attributeReplaced(HttpSessionBindingEvent se)
{ {
// System.err.println("attributeReplaced "+se); LOG.fine("attributeReplaced " + se);
} }
@Override @Override
public void attributeReplaced(ServletContextAttributeEvent scab) public void attributeReplaced(ServletContextAttributeEvent scab)
{ {
// System.err.println("attributeReplaced "+scab); LOG.fine("attributeReplaced " + scab);
} }
@Override @Override
public void attributeReplaced(ServletRequestAttributeEvent srae) public void attributeReplaced(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeReplaced "+srae); LOG.fine("attributeReplaced " + srae);
} }
@Override @Override
public void contextDestroyed(ServletContextEvent sce) public void contextDestroyed(ServletContextEvent sce)
{ {
// System.err.println("contextDestroyed "+sce); LOG.fine("contextDestroyed " + sce);
} }
@Override @Override
@ -106,7 +115,7 @@ public class AnnotatedListener implements HttpSessionListener, HttpSessionAttrib
if (sce.getServletContext().getAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest") != null) if (sce.getServletContext().getAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest") != null)
throw new IllegalStateException("AnnotatedListener already initialized"); throw new IllegalStateException("AnnotatedListener already initialized");
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest", Boolean.valueOf(maxAmount != null)); sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclInjectWebListenerTest", maxAmount != null);
boolean setSessionTimeout; boolean setSessionTimeout;
try try
@ -118,7 +127,7 @@ public class AnnotatedListener implements HttpSessionListener, HttpSessionAttrib
{ {
setSessionTimeout = false; setSessionTimeout = false;
} }
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclSetSessionTimeout", Boolean.valueOf(setSessionTimeout)); sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclSetSessionTimeout", setSessionTimeout);
boolean getSessionTimeout; boolean getSessionTimeout;
try try
@ -129,60 +138,42 @@ public class AnnotatedListener implements HttpSessionListener, HttpSessionAttrib
{ {
getSessionTimeout = false; getSessionTimeout = false;
} }
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclGetSessionTimeout", Boolean.valueOf(getSessionTimeout)); sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclGetSessionTimeout", getSessionTimeout);
}
public void requestCompleted(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
} }
@Override @Override
public void requestDestroyed(ServletRequestEvent sre) public void requestDestroyed(ServletRequestEvent sre)
{ {
// System.err.println("requestDestroyed "+sre); LOG.fine("requestDestroyed " + sre);
} }
@Override @Override
public void requestInitialized(ServletRequestEvent sre) public void requestInitialized(ServletRequestEvent sre)
{ {
// System.err.println("requestInitialized "+sre); LOG.fine("requestInitialized " + sre);
}
public void requestResumed(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
public void requestSuspended(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
} }
@Override @Override
public void sessionCreated(HttpSessionEvent se) public void sessionCreated(HttpSessionEvent se)
{ {
// System.err.println("sessionCreated "+se); LOG.fine("sessionCreated " + se);
} }
@Override @Override
public void sessionDestroyed(HttpSessionEvent se) public void sessionDestroyed(HttpSessionEvent se)
{ {
// System.err.println("sessionDestroyed "+se); LOG.fine("sessionDestroyed " + se);
} }
@Override @Override
public void sessionDidActivate(HttpSessionEvent se) public void sessionDidActivate(HttpSessionEvent se)
{ {
// System.err.println("sessionDidActivate "+se); LOG.fine("sessionDidActivate " + se);
} }
@Override @Override
public void sessionWillPassivate(HttpSessionEvent se) public void sessionWillPassivate(HttpSessionEvent se)
{ {
// System.err.println("sessionWillPassivate "+se); LOG.fine("sessionWillPassivate " + se);
} }
} }

View File

@ -62,29 +62,21 @@ public class AsyncListenerServlet extends HttpServlet
@Override @Override
public void onComplete(AsyncEvent event) throws IOException public void onComplete(AsyncEvent event) throws IOException
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void onTimeout(AsyncEvent event) throws IOException public void onTimeout(AsyncEvent event) throws IOException
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void onError(AsyncEvent event) throws IOException public void onError(AsyncEvent event) throws IOException
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void onStartAsync(AsyncEvent event) throws IOException public void onStartAsync(AsyncEvent event) throws IOException
{ {
// TODO Auto-generated method stub
} }
} }

View File

@ -20,7 +20,6 @@ package com.acme.test;
public class Bar public class Bar
{ {
@com.acme.initializer.Foo(2) @com.acme.initializer.Foo(2)
public void someMethod() public void someMethod()
{ {

View File

@ -38,7 +38,6 @@ public class ClassLoaderServlet extends HttpServlet
{ {
try try
{ {
PrintWriter writer = resp.getWriter(); PrintWriter writer = resp.getWriter();
writer.println("<html>"); writer.println("<html>");
writer.println("<HEAD><link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\"/></HEAD>"); writer.println("<HEAD><link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\"/></HEAD>");

View File

@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
* *
* Use DeclareRolesAnnotations from within Jetty. * Use DeclareRolesAnnotations from within Jetty.
*/ */
@DeclareRoles({"server-administrator", "user"}) @DeclareRoles({"server-administrator", "user"})
public class RoleAnnotationTest extends HttpServlet public class RoleAnnotationTest extends HttpServlet
{ {

View File

@ -20,7 +20,6 @@ package com.acme.test;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint; import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
@ -32,10 +31,9 @@ import javax.servlet.http.HttpServletResponse;
@ServletSecurity(@HttpConstraint(rolesAllowed = "admin")) @ServletSecurity(@HttpConstraint(rolesAllowed = "admin"))
public class SecuredServlet extends HttpServlet public class SecuredServlet extends HttpServlet
{ {
@Override @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException throws IOException
{ {
PrintWriter writer = resp.getWriter(); PrintWriter writer = resp.getWriter();
writer.println("<html>"); writer.println("<html>");

View File

@ -19,6 +19,7 @@
package com.acme.test; package com.acme.test;
import java.util.EventListener; import java.util.EventListener;
import java.util.logging.Logger;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextAttributeListener;
@ -38,69 +39,76 @@ import javax.servlet.http.HttpSessionListener;
@com.acme.initializer.Foo(1) @com.acme.initializer.Foo(1)
@WebListener @WebListener
public class TestListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener public class TestListener implements HttpSessionListener,
HttpSessionAttributeListener,
HttpSessionActivationListener,
ServletContextListener,
ServletContextAttributeListener,
ServletRequestListener,
ServletRequestAttributeListener
{ {
private static final Logger LOG = Logger.getLogger(TestListener.class.getName());
@Resource(mappedName = "maxAmount") @Resource(mappedName = "maxAmount")
private Double maxAmount; private Double maxAmount;
@Override @Override
public void attributeAdded(HttpSessionBindingEvent se) public void attributeAdded(HttpSessionBindingEvent se)
{ {
// System.err.println("attributedAdded "+se); LOG.fine("attributeAdded " + se);
} }
@Override @Override
public void attributeAdded(ServletContextAttributeEvent scab) public void attributeAdded(ServletContextAttributeEvent scab)
{ {
// System.err.println("attributeAdded "+scab); LOG.fine("attributeAdded " + scab);
} }
@Override @Override
public void attributeAdded(ServletRequestAttributeEvent srae) public void attributeAdded(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeAdded "+srae); LOG.fine("attributeAdded " + srae);
} }
@Override @Override
public void attributeRemoved(HttpSessionBindingEvent se) public void attributeRemoved(HttpSessionBindingEvent se)
{ {
// System.err.println("attributeRemoved "+se); LOG.fine("attributeRemoved " + se);
} }
@Override @Override
public void attributeRemoved(ServletContextAttributeEvent scab) public void attributeRemoved(ServletContextAttributeEvent scab)
{ {
// System.err.println("attributeRemoved "+scab); LOG.fine("attributeRemoved " + scab);
} }
@Override @Override
public void attributeRemoved(ServletRequestAttributeEvent srae) public void attributeRemoved(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeRemoved "+srae); LOG.fine("attributeRemoved " + srae);
} }
@Override @Override
public void attributeReplaced(HttpSessionBindingEvent se) public void attributeReplaced(HttpSessionBindingEvent se)
{ {
// System.err.println("attributeReplaced "+se); LOG.fine("attributeReplaced " + se);
} }
@Override @Override
public void attributeReplaced(ServletContextAttributeEvent scab) public void attributeReplaced(ServletContextAttributeEvent scab)
{ {
// System.err.println("attributeReplaced "+scab); LOG.fine("attributeReplaced " + scab);
} }
@Override @Override
public void attributeReplaced(ServletRequestAttributeEvent srae) public void attributeReplaced(ServletRequestAttributeEvent srae)
{ {
// System.err.println("attributeReplaced "+srae); LOG.fine("attributeReplaced " + srae);
} }
@Override @Override
public void contextDestroyed(ServletContextEvent sce) public void contextDestroyed(ServletContextEvent sce)
{ {
// System.err.println("contextDestroyed "+sce); LOG.fine("contextDestroyed " + sce);
} }
@Override @Override
@ -109,9 +117,9 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
if (sce.getServletContext().getAttribute("com.acme.AnnotationTest.sclInjectTest") != null) if (sce.getServletContext().getAttribute("com.acme.AnnotationTest.sclInjectTest") != null)
throw new IllegalStateException("TestListener already initialized"); throw new IllegalStateException("TestListener already initialized");
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclInjectTest", Boolean.valueOf(maxAmount != null)); sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclInjectTest", maxAmount != null);
//Can't add a ServletContextListener from a ServletContextListener even if it is declared in web.xml // Can't add a ServletContextListener from a ServletContextListener even if it is declared in web.xml
try try
{ {
sce.getServletContext().addListener(new NaughtyServletContextListener()); sce.getServletContext().addListener(new NaughtyServletContextListener());
@ -126,7 +134,7 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclFromSclRegoTest", Boolean.FALSE); sce.getServletContext().setAttribute("com.acme.AnnotationTest.sclFromSclRegoTest", Boolean.FALSE);
} }
//Can't add an EventListener not part of the specified list for addListener() // Can't add an EventListener not part of the specified list for addListener()
try try
{ {
sce.getServletContext().addListener(new InvalidListener()); sce.getServletContext().addListener(new InvalidListener());
@ -141,11 +149,11 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
sce.getServletContext().setAttribute("com.acme.AnnotationTest.invalidListenerRegoTest", Boolean.FALSE); sce.getServletContext().setAttribute("com.acme.AnnotationTest.invalidListenerRegoTest", Boolean.FALSE);
} }
//Programmatically add a listener and make sure its injected // Programmatically add a listener and make sure its injected
try try
{ {
ValidListener l = sce.getServletContext().createListener(ValidListener.class); ValidListener l = sce.getServletContext().createListener(ValidListener.class);
sce.getServletContext().setAttribute("com.acme.AnnotationTest.programListenerInjectTest", Boolean.valueOf(l != null && l.maxAmount != null)); sce.getServletContext().setAttribute("com.acme.AnnotationTest.programListenerInjectTest", l != null && l.maxAmount != null);
} }
catch (Exception e) catch (Exception e)
{ {
@ -153,58 +161,28 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
} }
} }
public void requestCompleted(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
@Override @Override
public void requestDestroyed(ServletRequestEvent sre) public void requestDestroyed(ServletRequestEvent sre)
{ {
// System.err.println("requestDestroyed "+sre); LOG.fine("requestDestroyed " + sre);
} }
@Override @Override
public void requestInitialized(ServletRequestEvent sre) public void requestInitialized(ServletRequestEvent sre)
{ {
// System.err.println("requestInitialized "+sre); LOG.fine("requestInitialized " + sre);
}
public void requestResumed(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
}
public void requestSuspended(ServletRequestEvent rre)
{
// TODO Auto-generated method stub
} }
@Override @Override
public void sessionCreated(HttpSessionEvent se) public void sessionCreated(HttpSessionEvent se)
{ {
// System.err.println("sessionCreated "+se); LOG.fine("sessionCreated " + se);
} }
@Override @Override
public void sessionDestroyed(HttpSessionEvent se) public void sessionDestroyed(HttpSessionEvent se)
{ {
// System.err.println("sessionDestroyed "+se); LOG.fine("sessionDestroyed " + se);
}
@Override
public void sessionDidActivate(HttpSessionEvent se)
{
// System.err.println("sessionDidActivate "+se);
}
@Override
public void sessionWillPassivate(HttpSessionEvent se)
{
// System.err.println("sessionWillPassivate "+se);
} }
public static class NaughtyServletContextListener implements ServletContextListener public static class NaughtyServletContextListener implements ServletContextListener
@ -242,7 +220,6 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeLi
@Override @Override
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) public void sessionIdChanged(HttpSessionEvent event, String oldSessionId)
{ {
} }
} }
} }