* Issue #11548 - Replication as jetty-ee10-webapp testcase * Correct order of WebAppContext.stop --------- Co-authored-by: Jan Bartel <janb@webtide.com> Co-authored-by: gregw <gregw@webtide.com>
This commit is contained in:
parent
5ca620e0e6
commit
9defd5d416
|
@ -771,14 +771,17 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Alias
|
||||||
protected void doStop() throws Exception
|
protected void doStop() throws Exception
|
||||||
{
|
{
|
||||||
_context.call(super::doStop, null);
|
_context.call(super::doStop, null);
|
||||||
|
cleanupAfterStop();
|
||||||
|
_tempDirectoryCreated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cleanupAfterStop() throws Exception
|
||||||
|
{
|
||||||
File tempDirectory = getTempDirectory();
|
File tempDirectory = getTempDirectory();
|
||||||
|
|
||||||
// if we're not persisting the temp dir contents delete it
|
// if we're not persisting the temp dir contents delete it
|
||||||
if (tempDirectory != null && tempDirectory.exists() && !isTempDirectoryPersistent())
|
if (tempDirectory != null && tempDirectory.exists() && !isTempDirectoryPersistent())
|
||||||
IO.delete(tempDirectory);
|
IO.delete(tempDirectory);
|
||||||
|
|
||||||
_tempDirectoryCreated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkVirtualHost(Request request)
|
public boolean checkVirtualHost(Request request)
|
||||||
|
|
|
@ -50,6 +50,7 @@ import org.eclipse.jetty.security.SecurityHandler;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.Deployable;
|
import org.eclipse.jetty.server.Deployable;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.util.ExceptionUtil;
|
import org.eclipse.jetty.util.ExceptionUtil;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
@ -1228,6 +1229,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
protected void stopContext() throws Exception
|
protected void stopContext() throws Exception
|
||||||
{
|
{
|
||||||
stopWebapp();
|
stopWebapp();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (int i = _configurations.size(); i-- > 0; )
|
for (int i = _configurations.size(); i-- > 0; )
|
||||||
|
@ -1250,6 +1252,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
}
|
}
|
||||||
|
|
||||||
_unavailableException = null;
|
_unavailableException = null;
|
||||||
|
|
||||||
|
super.cleanupAfterStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,6 +1275,16 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
super.stopContext();
|
super.stopContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent the temp directory from being deleted during the normal stop sequence, and require that
|
||||||
|
* {@link ContextHandler#cleanupAfterStop()} is explicitly called after the webapp classloader is closed
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void cleanupAfterStop() throws Exception
|
||||||
|
{
|
||||||
|
//intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> setServletSecurity(Dynamic registration, ServletSecurityElement servletSecurityElement)
|
public Set<String> setServletSecurity(Dynamic registration, ServletSecurityElement servletSecurityElement)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,12 +14,14 @@
|
||||||
package org.eclipse.jetty.ee10.webapp;
|
package org.eclipse.jetty.ee10.webapp;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -56,6 +58,7 @@ import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
import org.eclipse.jetty.util.URIUtil;
|
||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
import org.eclipse.jetty.util.resource.FileSystemPool;
|
import org.eclipse.jetty.util.resource.FileSystemPool;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
import org.eclipse.jetty.util.resource.ResourceFactory;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -829,6 +832,99 @@ public class WebAppContextTest
|
||||||
assertThat("URL[0]", urls[0].toURI(), is(extLibs.toUri()));
|
assertThat("URL[0]", urls[0].toURI(), is(extLibs.toUri()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRestartWebApp(WorkDir workDir) throws Exception
|
||||||
|
{
|
||||||
|
Server server = newServer();
|
||||||
|
|
||||||
|
// Create war
|
||||||
|
Path tempDir = workDir.getEmptyPathDir();
|
||||||
|
Path testWebappDir = MavenPaths.projectBase().resolve("src/test/webapp");
|
||||||
|
assertTrue(Files.exists(testWebappDir));
|
||||||
|
Path warFile = tempDir.resolve("demo.war");
|
||||||
|
|
||||||
|
Map<String, String> env = new HashMap<>();
|
||||||
|
env.put("create", "true");
|
||||||
|
|
||||||
|
URI uri = URI.create("jar:" + warFile.toUri().toASCIIString());
|
||||||
|
// Use ZipFS so that we can create paths that are just "/"
|
||||||
|
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env))
|
||||||
|
{
|
||||||
|
Path root = zipfs.getPath("/");
|
||||||
|
IO.copyDir(testWebappDir, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create WebAppContext
|
||||||
|
WebAppContext context = new WebAppContext();
|
||||||
|
ResourceFactory resourceFactory = context.getResourceFactory();
|
||||||
|
Resource warResource = resourceFactory.newResource(warFile);
|
||||||
|
context.setContextPath("/");
|
||||||
|
context.setWarResource(warResource);
|
||||||
|
context.setExtractWAR(true);
|
||||||
|
|
||||||
|
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
|
||||||
|
List<String> actualRefs = getWebAppClassLoaderUrlRefs(context);
|
||||||
|
String[] expectedRefs = new String[]{
|
||||||
|
"/webapp/WEB-INF/classes/",
|
||||||
|
"/webapp/WEB-INF/lib/acme.jar!/",
|
||||||
|
"/webapp/WEB-INF/lib/alpha.jar!/",
|
||||||
|
"/webapp/WEB-INF/lib/omega.jar!/"
|
||||||
|
};
|
||||||
|
|
||||||
|
assertThat("URLs (sub) refs", actualRefs, containsInAnyOrder(expectedRefs));
|
||||||
|
|
||||||
|
// Simulate a reload
|
||||||
|
LOG.info("Stopping Initial Context");
|
||||||
|
context.stop();
|
||||||
|
LOG.info("Stopped Initial Context - waiting 2 seconds");
|
||||||
|
Thread.sleep(2000);
|
||||||
|
LOG.info("Touch War File: {}", warFile);
|
||||||
|
touch(warFile);
|
||||||
|
LOG.info("ReStarting Context");
|
||||||
|
context.start();
|
||||||
|
|
||||||
|
actualRefs = getWebAppClassLoaderUrlRefs(context);
|
||||||
|
expectedRefs = new String[]{
|
||||||
|
"/webapp/WEB-INF/classes/",
|
||||||
|
"/webapp/WEB-INF/lib/acme.jar!/",
|
||||||
|
"/webapp/WEB-INF/lib/alpha.jar!/",
|
||||||
|
"/webapp/WEB-INF/lib/omega.jar!/"
|
||||||
|
};
|
||||||
|
assertThat("URLs (sub) refs", actualRefs, containsInAnyOrder(expectedRefs));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void touch(Path path) throws IOException
|
||||||
|
{
|
||||||
|
FileTime now = FileTime.fromMillis(System.currentTimeMillis());
|
||||||
|
Files.setLastModifiedTime(path, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getWebAppClassLoaderUrlRefs(WebAppContext context)
|
||||||
|
{
|
||||||
|
ClassLoader contextClassLoader = context.getClassLoader();
|
||||||
|
assertThat(contextClassLoader, instanceOf(WebAppClassLoader.class));
|
||||||
|
WebAppClassLoader webAppClassLoader = (WebAppClassLoader)contextClassLoader;
|
||||||
|
String webappTempDir = context.getTempDirectory().toString();
|
||||||
|
List<String> actualRefs = new ArrayList<>();
|
||||||
|
URL[] urls = webAppClassLoader.getURLs();
|
||||||
|
for (URL url: urls)
|
||||||
|
{
|
||||||
|
String ref = url.toExternalForm();
|
||||||
|
int idx = ref.indexOf(webappTempDir);
|
||||||
|
// strip temp directory from URL (to make test easier to write)
|
||||||
|
if (idx >= 0)
|
||||||
|
ref = ref.substring(idx + webappTempDir.length());
|
||||||
|
actualRefs.add(ref);
|
||||||
|
}
|
||||||
|
return actualRefs;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetServerPropagation()
|
public void testSetServerPropagation()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#org.eclipse.jetty.LEVEL=DEBUG
|
#org.eclipse.jetty.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.webapp.LEVEL=DEBUG
|
#org.eclipse.jetty.webapp.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.util.LEVEL=DEBUG
|
#org.eclipse.jetty.util.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.util.resource.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.util.IO.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.ee10.webapp.MetaInfConfiguration.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.ee10.webapp.WebInfConfiguration.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.util.PathWatcher.Noisy.LEVEL=OFF
|
#org.eclipse.jetty.util.PathWatcher.Noisy.LEVEL=OFF
|
||||||
|
|
Loading…
Reference in New Issue