Merge pull request #10178 from eclipse/fix/12.0.x/spec-webapp-testing
Fix demo-spec webapp failures
This commit is contained in:
commit
4fe2b041c3
|
@ -27,16 +27,21 @@ import java.io.PrintWriter;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.GatheringByteChannel;
|
import java.nio.channels.GatheringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.CopyOption;
|
||||||
import java.nio.file.FileVisitResult;
|
import java.nio.file.FileVisitResult;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -218,6 +223,37 @@ public class IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the contents of a directory from one directory to another.
|
||||||
|
*
|
||||||
|
* @param srcDir the source directory
|
||||||
|
* @param destDir the destination directory
|
||||||
|
* @throws IOException if unable to copy the file
|
||||||
|
*/
|
||||||
|
public static void copyDir(Path srcDir, Path destDir, CopyOption... copyOptions) throws IOException
|
||||||
|
{
|
||||||
|
if (!Files.isDirectory(Objects.requireNonNull(srcDir)))
|
||||||
|
throw new IllegalArgumentException("Source is not a directory: " + srcDir);
|
||||||
|
if (!Files.isDirectory(Objects.requireNonNull(destDir)))
|
||||||
|
throw new IllegalArgumentException("Dest is not a directory: " + destDir);
|
||||||
|
|
||||||
|
try (Stream<Path> sourceStream = Files.walk(srcDir, 20))
|
||||||
|
{
|
||||||
|
Iterator<Path> iterFiles = sourceStream
|
||||||
|
.filter(Files::isRegularFile)
|
||||||
|
.iterator();
|
||||||
|
while (iterFiles.hasNext())
|
||||||
|
{
|
||||||
|
Path sourceFile = iterFiles.next();
|
||||||
|
URI relativeSrc = srcDir.toUri().relativize(sourceFile.toUri());
|
||||||
|
Path destFile = destDir.resolve(relativeSrc.toASCIIString());
|
||||||
|
if (!Files.exists(destFile.getParent()))
|
||||||
|
Files.createDirectories(destFile.getParent());
|
||||||
|
Files.copy(sourceFile, destFile, copyOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void copyFile(File from, File to) throws IOException
|
public static void copyFile(File from, File to) throws IOException
|
||||||
{
|
{
|
||||||
try (InputStream in = new FileInputStream(from);
|
try (InputStream in = new FileInputStream(from);
|
||||||
|
|
|
@ -83,8 +83,8 @@ public class FooInitializer implements ServletContainerInitializer
|
||||||
if (context.getAttribute("org.example.Foo") != null)
|
if (context.getAttribute("org.example.Foo") != null)
|
||||||
throw new IllegalStateException("FooInitializer on Startup already called");
|
throw new IllegalStateException("FooInitializer on Startup already called");
|
||||||
|
|
||||||
context.setAttribute("org.example.Foo", new ArrayList<Class>(classes));
|
context.setAttribute("org.example.Foo", new ArrayList<>(classes));
|
||||||
ServletRegistration.Dynamic reg = context.addServlet("AnnotationTest", "org.example.AnnotationTest");
|
ServletRegistration.Dynamic reg = context.addServlet("AnnotationTest", "org.example.test.AnnotationTest");
|
||||||
context.setAttribute("org.example.AnnotationTest.complete", (reg == null));
|
context.setAttribute("org.example.AnnotationTest.complete", (reg == null));
|
||||||
context.addListener(new FooListener());
|
context.addListener(new FooListener());
|
||||||
|
|
||||||
|
|
|
@ -207,20 +207,30 @@
|
||||||
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||||
<artifactId>jetty-ee10-demo-container-initializer</artifactId>
|
<artifactId>jetty-ee10-demo-container-initializer</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
<!-- deliberately old version to test classloading -->
|
<groupId>org.eclipse.jetty.ee10</groupId>
|
||||||
<!-- TODO uncomment and update the following once 9.4.19 is released with a fix for #3726
|
<artifactId>jetty-ee10-webapp</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty.ee10</groupId>
|
||||||
|
<artifactId>jetty-ee10-annotations</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||||
|
<artifactId>jetty-ee10-demo-mock-resources</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-util</artifactId>
|
<artifactId>jetty-client</artifactId>
|
||||||
<version>9.4.19.vXXXXXXXX</version>
|
<scope>test</scope>
|
||||||
<exclusions>
|
</dependency>
|
||||||
<exclusion>
|
<dependency>
|
||||||
<groupId>jakarta.servlet</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jakarta.servlet-api</artifactId>
|
<artifactId>jetty-slf4j-impl</artifactId>
|
||||||
</exclusion>
|
<scope>test</scope>
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
|
||||||
|
//
|
||||||
|
// This program and the accompanying materials are made available under the
|
||||||
|
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.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.ee10.demos;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.client.ContentResponse;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.ee10.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.eclipse.jetty.security.HashLoginService;
|
||||||
|
import org.eclipse.jetty.security.SecurityHandler;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.toolchain.test.FS;
|
||||||
|
import org.eclipse.jetty.toolchain.test.MavenPaths;
|
||||||
|
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
|
||||||
|
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.util.resource.ResourceFactory;
|
||||||
|
import org.example.MockDataSource;
|
||||||
|
import org.example.MockUserTransaction;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
@ExtendWith(WorkDirExtension.class)
|
||||||
|
public class SpecWebAppTest
|
||||||
|
{
|
||||||
|
private Server server;
|
||||||
|
private HttpClient client;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup(WorkDir workDir) throws Exception
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
Path webappDir = prepareWebAppDir(workDir);
|
||||||
|
|
||||||
|
WebAppContext webapp = new WebAppContext();
|
||||||
|
ResourceFactory resourceFactory = ResourceFactory.of(webapp);
|
||||||
|
webapp.setContextPath("/");
|
||||||
|
webapp.setWarResource(resourceFactory.newResource(webappDir));
|
||||||
|
webapp.setAttribute(
|
||||||
|
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
|
||||||
|
".*/jakarta.servlet-api-[^/]*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
|
||||||
|
|
||||||
|
HashLoginService hashLoginService = new HashLoginService();
|
||||||
|
hashLoginService.setName("Test Realm");
|
||||||
|
Path realmFile = MavenPaths.findTestResourceFile("ee10-demo-realm.properties");
|
||||||
|
Resource realmResource = ResourceFactory.of(server).newResource(realmFile);
|
||||||
|
hashLoginService.setConfig(realmResource);
|
||||||
|
SecurityHandler securityHandler = webapp.getSecurityHandler();
|
||||||
|
securityHandler.setLoginService(hashLoginService);
|
||||||
|
|
||||||
|
new org.eclipse.jetty.ee10.plus.jndi.Resource(webapp, "jdbc/mydatasource", new MockDataSource());
|
||||||
|
new org.eclipse.jetty.ee10.plus.jndi.Transaction("ee10", new MockUserTransaction());
|
||||||
|
|
||||||
|
server.setHandler(webapp);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
client = new HttpClient();
|
||||||
|
client.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path prepareWebAppDir(WorkDir workDir) throws IOException
|
||||||
|
{
|
||||||
|
Path webappDir = workDir.getEmptyPathDir();
|
||||||
|
Path srcWebapp = MavenPaths.projectBase().resolve("src/main/webapp");
|
||||||
|
IO.copyDir(srcWebapp, webappDir);
|
||||||
|
|
||||||
|
Path webappClassesDir = webappDir.resolve("WEB-INF/classes");
|
||||||
|
FS.ensureDirExists(webappClassesDir);
|
||||||
|
Path classesDir = MavenPaths.projectBase().resolve("target/classes");
|
||||||
|
IO.copyDir(classesDir, webappClassesDir);
|
||||||
|
|
||||||
|
Path libDir = webappDir.resolve("WEB-INF/lib");
|
||||||
|
FS.ensureDirExists(libDir);
|
||||||
|
copyDependency("jetty-ee10-demo-container-initializer", libDir);
|
||||||
|
copyDependency("jetty-ee10-demo-web-fragment", libDir);
|
||||||
|
|
||||||
|
return webappDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyDependency(String depName, Path libDir) throws IOException
|
||||||
|
{
|
||||||
|
Path depPath = MavenPaths.projectBase().resolve("../" + depName).normalize();
|
||||||
|
if (!Files.isDirectory(depPath))
|
||||||
|
fail("Dependency not found: " + depPath);
|
||||||
|
Path outputJar = libDir.resolve(depName + ".jar");
|
||||||
|
Map<String, String> env = new HashMap<>();
|
||||||
|
env.put("create", "true");
|
||||||
|
|
||||||
|
URI uri = URI.create("jar:" + outputJar.toUri().toASCIIString());
|
||||||
|
try (FileSystem fs = FileSystems.newFileSystem(uri, env))
|
||||||
|
{
|
||||||
|
Path root = fs.getPath("/");
|
||||||
|
IO.copyDir(depPath.resolve("target/classes"), root);
|
||||||
|
IO.copyDir(depPath.resolve("src/main/resources"), root, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void teardown()
|
||||||
|
{
|
||||||
|
LifeCycle.stop(client);
|
||||||
|
LifeCycle.stop(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoFailures() throws InterruptedException, ExecutionException, TimeoutException
|
||||||
|
{
|
||||||
|
ContentResponse response = client.newRequest(server.getURI().resolve("/test/"))
|
||||||
|
.followRedirects(false)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
assertThat("response status", response.getStatus(), is(HttpStatus.OK_200));
|
||||||
|
// Look for 0 entries that fail.
|
||||||
|
assertThat("response", response.getContentAsString(), not(containsString(">FAIL<")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#
|
||||||
|
# This file defines users passwords and roles for a HashUserRealm
|
||||||
|
#
|
||||||
|
# The format is
|
||||||
|
# <username>: <password>[,<rolename> ...]
|
||||||
|
#
|
||||||
|
# Passwords may be clear text, obfuscated or checksummed. The class
|
||||||
|
# org.eclipse.util.Password should be used to generate obfuscated
|
||||||
|
# passwords or password checksums
|
||||||
|
#
|
||||||
|
# If DIGEST Authentication is used, the password must be in a recoverable
|
||||||
|
# format, either plain text or OBF:.
|
||||||
|
#
|
||||||
|
jetty: MD5:164c88b302622e17050af52c89945d44,user
|
||||||
|
admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user
|
||||||
|
other: OBF:1xmk1w261u9r1w1c1xmq,user
|
||||||
|
plain: plain,user
|
||||||
|
user: password,user
|
||||||
|
|
||||||
|
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
|
||||||
|
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user
|
|
@ -0,0 +1,11 @@
|
||||||
|
## Jetty Logging using jetty-slf4j-impl
|
||||||
|
org.eclipse.jetty.LEVEL=INFO
|
||||||
|
#org.eclipse.jetty.STACKS=true
|
||||||
|
#org.eclipse.jetty.ee10.annotations.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.STACKS=false
|
||||||
|
#org.eclipse.jetty.io.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.io.ssl.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.server.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.ee10.servlets.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.alpn.LEVEL=DEBUG
|
||||||
|
#org.eclipse.jetty.jmx.LEVEL=DEBUG
|
Loading…
Reference in New Issue