Merge branch 'jetty-9.4.x' into jetty-10.0.x
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com> # Conflicts: # jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java # jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebInfConfigurationTest.java
This commit is contained in:
commit
cc58a74662
|
@ -601,11 +601,11 @@ public class Main
|
||||||
}
|
}
|
||||||
catch (ConnectException e)
|
catch (ConnectException e)
|
||||||
{
|
{
|
||||||
usageExit(e, ERR_NOT_STOPPED, jsvcStartArgs.isTestingModeEnabled());
|
usageExit(e, ERR_NOT_STOPPED, jsvcStartArgs != null && jsvcStartArgs.isTestingModeEnabled());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
usageExit(e, ERR_UNKNOWN, jsvcStartArgs.isTestingModeEnabled());
|
usageExit(e, ERR_UNKNOWN, jsvcStartArgs != null && jsvcStartArgs.isTestingModeEnabled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -381,4 +381,11 @@ public class JarFileResource extends JarResource
|
||||||
URL url = new URL(string);
|
URL url = new URL(string);
|
||||||
return url.sameFile(resource.getURI().toURL());
|
return url.sameFile(resource.getURI().toURL());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getJarFile()
|
||||||
|
{
|
||||||
|
if (_file != null)
|
||||||
|
return _file;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,17 @@ package org.eclipse.jetty.webapp;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.NetworkConnector;
|
import org.eclipse.jetty.server.NetworkConnector;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.util.resource.JarFileResource;
|
||||||
import org.eclipse.jetty.util.resource.JarResource;
|
import org.eclipse.jetty.util.resource.JarResource;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
import org.eclipse.jetty.util.resource.ResourceCollection;
|
import org.eclipse.jetty.util.resource.ResourceCollection;
|
||||||
|
@ -497,7 +499,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Resource base
|
// Resource base
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Resource resource = context.getBaseResource();
|
Resource resource = context.getBaseResource();
|
||||||
|
@ -506,27 +508,21 @@ public class WebInfConfiguration extends AbstractConfiguration
|
||||||
if (context.getWar() == null || context.getWar().length() == 0)
|
if (context.getWar() == null || context.getWar().length() == 0)
|
||||||
throw new IllegalStateException("No resourceBase or war set for context");
|
throw new IllegalStateException("No resourceBase or war set for context");
|
||||||
|
|
||||||
// Set dir or WAR
|
// Set dir or WAR to resource
|
||||||
resource = context.newResource(context.getWar());
|
resource = context.newResource(context.getWar());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource.getURI().getPath() != null)
|
String resourceBaseName = getResourceBaseName(resource);
|
||||||
{
|
canonicalName.append(resourceBaseName);
|
||||||
String tmp = URIUtil.decodePath(resource.getURI().getPath());
|
|
||||||
if (tmp.endsWith("/"))
|
|
||||||
tmp = tmp.substring(0, tmp.length() - 1);
|
|
||||||
if (tmp.endsWith("!"))
|
|
||||||
tmp = tmp.substring(0, tmp.length() - 1);
|
|
||||||
//get just the last part which is the filename
|
|
||||||
int i = tmp.lastIndexOf("/");
|
|
||||||
canonicalName.append(tmp.substring(i + 1, tmp.length()));
|
|
||||||
}
|
|
||||||
canonicalName.append("-");
|
canonicalName.append("-");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOG.warn("Can't generate resourceBase as part of webapp tmp dir name " + e);
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug(e);
|
{
|
||||||
|
LOG.debug("Can't get resource base name", e);
|
||||||
|
}
|
||||||
|
canonicalName.append("-"); // empty resourceBaseName segment
|
||||||
}
|
}
|
||||||
|
|
||||||
//Context name
|
//Context name
|
||||||
|
@ -553,6 +549,70 @@ public class WebInfConfiguration extends AbstractConfiguration
|
||||||
|
|
||||||
canonicalName.append("-");
|
canonicalName.append("-");
|
||||||
|
|
||||||
return canonicalName.toString();
|
return StringUtil.sanitizeFileSystemName(canonicalName.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getResourceBaseName(Resource resource)
|
||||||
|
{
|
||||||
|
// Use File System and File interface if present
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File resourceFile = resource.getFile();
|
||||||
|
if ((resourceFile != null) && (resource instanceof JarFileResource))
|
||||||
|
{
|
||||||
|
resourceFile = ((JarFileResource)resource).getJarFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resourceFile != null)
|
||||||
|
{
|
||||||
|
return resourceFile.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOG.debug("Resource has no File reference: {}", resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use URI itself.
|
||||||
|
URI uri = resource.getURI();
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOG.debug("Resource has no URI reference: {}", resource);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return getUriLastPathSegment(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getUriLastPathSegment(URI uri)
|
||||||
|
{
|
||||||
|
String ssp = uri.getSchemeSpecificPart();
|
||||||
|
// strip off deep jar:file: reference information
|
||||||
|
int idx = ssp.indexOf("!/");
|
||||||
|
if (idx != -1)
|
||||||
|
{
|
||||||
|
ssp = ssp.substring(0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip off trailing '/' if present
|
||||||
|
if (ssp.endsWith("/"))
|
||||||
|
{
|
||||||
|
ssp = ssp.substring(0, ssp.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only interested in last segment
|
||||||
|
idx = ssp.lastIndexOf('/');
|
||||||
|
if (idx != -1)
|
||||||
|
{
|
||||||
|
ssp = ssp.substring(idx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.webapp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.FileVisitOption;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.text.Normalizer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.toolchain.test.FS;
|
||||||
|
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.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.util.resource.PathResource;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.junit.jupiter.api.condition.OS;
|
||||||
|
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 static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebInfConfigurationTest
|
||||||
|
*/
|
||||||
|
@ExtendWith(WorkDirExtension.class)
|
||||||
|
public class WebInfConfigurationTest
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(WebInfConfigurationTest.class);
|
||||||
|
private static final String TEST_RESOURCE_JAR = "test-base-resource.jar";
|
||||||
|
|
||||||
|
public WorkDir workDir;
|
||||||
|
|
||||||
|
public static Stream<Arguments> rawResourceNames()
|
||||||
|
{
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("/", ""),
|
||||||
|
Arguments.of("/a", "a")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("rawResourceNames")
|
||||||
|
public void testTinyGetResourceBaseName(String rawPath, String expectedName) throws IOException
|
||||||
|
{
|
||||||
|
Resource resource = Resource.newResource(rawPath);
|
||||||
|
assertThat(WebInfConfiguration.getResourceBaseName(resource), is(expectedName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> fileBaseResourceNames()
|
||||||
|
{
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("test.war", "test.war"),
|
||||||
|
Arguments.of("a/b/c/test.war", "test.war"),
|
||||||
|
Arguments.of("bar%2Fbaz/test.war", "test.war"),
|
||||||
|
Arguments.of("fizz buzz/test.war", "test.war"),
|
||||||
|
Arguments.of("another one/bites the dust/", "bites the dust"),
|
||||||
|
Arguments.of("another+one/bites+the+dust/", "bites+the+dust"),
|
||||||
|
Arguments.of("another%20one/bites%20the%20dust/", "bites%20the%20dust"),
|
||||||
|
Arguments.of("spanish/n\u00FAmero.war", "n\u00FAmero.war"),
|
||||||
|
Arguments.of("spanish/n%C3%BAmero.war", "n%C3%BAmero.war"),
|
||||||
|
Arguments.of("a/b!/", "b!"),
|
||||||
|
Arguments.of("a/b!/c/", "c"),
|
||||||
|
Arguments.of("a/b!/c/d/", "d"),
|
||||||
|
Arguments.of("a/b%21/", "b%21")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("fileBaseResourceNames")
|
||||||
|
public void testPathGetResourceBaseName(String basePath, String expectedName) throws IOException
|
||||||
|
{
|
||||||
|
Path root = workDir.getPath();
|
||||||
|
Path base = root.resolve(basePath);
|
||||||
|
if (basePath.endsWith("/"))
|
||||||
|
{
|
||||||
|
// we are working with a directory.
|
||||||
|
FS.ensureDirExists(base);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FS.ensureDirExists(base.getParent());
|
||||||
|
FS.touch(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource resource = new PathResource(base);
|
||||||
|
assertThat(WebInfConfiguration.getResourceBaseName(resource), is(expectedName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> fileUriBaseResourceNames()
|
||||||
|
{
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of("test.war", "test.war"),
|
||||||
|
Arguments.of("a/b/c/test.war", "test.war"),
|
||||||
|
Arguments.of("bar%2Fbaz/test.war", "test.war"),
|
||||||
|
Arguments.of("fizz buzz/test.war", "test.war"),
|
||||||
|
Arguments.of("another one/bites the dust/", "bites the dust"),
|
||||||
|
Arguments.of("another+one/bites+the+dust/", "bites+the+dust"),
|
||||||
|
Arguments.of("another%20one/bites%20the%20dust/", "bites%20the%20dust"),
|
||||||
|
Arguments.of("spanish/n\u00FAmero.war", "n\u00FAmero.war"),
|
||||||
|
Arguments.of("spanish/n%C3%BAmero.war", "n%C3%BAmero.war"),
|
||||||
|
Arguments.of("a/b!/", "b"),
|
||||||
|
Arguments.of("a/b!/c/", "b"),
|
||||||
|
Arguments.of("a/b!/c/d/", "b"),
|
||||||
|
Arguments.of("a/b%21/", "b%21")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to testPathGetResourceBaseName, but with "file:" URIs
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("fileUriBaseResourceNames")
|
||||||
|
public void testFileUriGetUriLastPathSegment(String basePath, String expectedName) throws IOException
|
||||||
|
{
|
||||||
|
Path root = workDir.getPath();
|
||||||
|
Path base = root.resolve(basePath);
|
||||||
|
if (basePath.endsWith("/"))
|
||||||
|
{
|
||||||
|
FS.ensureDirExists(base);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FS.ensureDirExists(base.getParent());
|
||||||
|
FS.touch(base);
|
||||||
|
}
|
||||||
|
URI uri = base.toUri();
|
||||||
|
if (OS.MAC.isCurrentOs())
|
||||||
|
{
|
||||||
|
// Normalize Unicode to NFD form that OSX Path/FileSystem produces
|
||||||
|
expectedName = Normalizer.normalize(expectedName, Normalizer.Form.NFD);
|
||||||
|
}
|
||||||
|
assertThat(WebInfConfiguration.getUriLastPathSegment(uri), is(expectedName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> uriLastSegmentSource() throws URISyntaxException, IOException
|
||||||
|
{
|
||||||
|
Path testJar = MavenTestingUtils.getTestResourcePathFile(TEST_RESOURCE_JAR);
|
||||||
|
URI uri = new URI("jar", testJar.toUri().toASCIIString(), null);
|
||||||
|
|
||||||
|
Map<String, Object> env = new HashMap<>();
|
||||||
|
env.put("multi-release", "runtime");
|
||||||
|
|
||||||
|
List<Arguments> arguments = new ArrayList<>();
|
||||||
|
arguments.add(Arguments.of(uri, TEST_RESOURCE_JAR));
|
||||||
|
try (FileSystem zipFs = FileSystems.newFileSystem(uri, env))
|
||||||
|
{
|
||||||
|
FileVisitOption[] fileVisitOptions = new FileVisitOption[]{};
|
||||||
|
|
||||||
|
for (Path root : zipFs.getRootDirectories())
|
||||||
|
{
|
||||||
|
Stream<Path> entryStream = Files.find(root, 10, (path, attrs) -> true, fileVisitOptions);
|
||||||
|
entryStream.forEach((path) ->
|
||||||
|
{
|
||||||
|
if (path.toString().endsWith("!/"))
|
||||||
|
{
|
||||||
|
// skip - JAR entry type not supported by Jetty
|
||||||
|
// TODO: re-enable once we start to use zipfs
|
||||||
|
LOG.warn("Skipping Unsupported entry: " + path.toUri());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arguments.add(Arguments.of(path.toUri(), TEST_RESOURCE_JAR));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arguments.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests of URIs last segment, including "jar:file:" based URIs.
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("uriLastSegmentSource")
|
||||||
|
public void testGetUriLastPathSegment(URI uri, String expectedName) throws IOException
|
||||||
|
{
|
||||||
|
assertThat(WebInfConfiguration.getUriLastPathSegment(uri), is(expectedName));
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -988,7 +988,9 @@ public class HttpClientStreamTest extends AbstractTest<TransportScenario>
|
||||||
public void testUploadWithOutputStreamFailureToConnect(Transport transport) throws Exception
|
public void testUploadWithOutputStreamFailureToConnect(Transport transport) throws Exception
|
||||||
{
|
{
|
||||||
init(transport);
|
init(transport);
|
||||||
scenario.start(new EmptyServerHandler());
|
|
||||||
|
long connectTimeout = 1000;
|
||||||
|
scenario.start(new EmptyServerHandler(), httpClient -> httpClient.setConnectTimeout(connectTimeout));
|
||||||
|
|
||||||
final byte[] data = new byte[512];
|
final byte[] data = new byte[512];
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
@ -1013,7 +1015,7 @@ public class HttpClientStreamTest extends AbstractTest<TransportScenario>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(latch.await(5, TimeUnit.SECONDS));
|
assertTrue(latch.await(2 * connectTimeout, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
@ -1070,7 +1072,9 @@ public class HttpClientStreamTest extends AbstractTest<TransportScenario>
|
||||||
public void testUploadWithConnectFailureClosesStream(Transport transport) throws Exception
|
public void testUploadWithConnectFailureClosesStream(Transport transport) throws Exception
|
||||||
{
|
{
|
||||||
init(transport);
|
init(transport);
|
||||||
scenario.start(new EmptyServerHandler());
|
|
||||||
|
long connectTimeout = 1000;
|
||||||
|
scenario.start(new EmptyServerHandler(), httpClient -> httpClient.setConnectTimeout(connectTimeout));
|
||||||
|
|
||||||
final CountDownLatch closeLatch = new CountDownLatch(1);
|
final CountDownLatch closeLatch = new CountDownLatch(1);
|
||||||
InputStream stream = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8))
|
InputStream stream = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8))
|
||||||
|
@ -1097,7 +1101,7 @@ public class HttpClientStreamTest extends AbstractTest<TransportScenario>
|
||||||
completeLatch.countDown();
|
completeLatch.countDown();
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(completeLatch.await(2 * connectTimeout, TimeUnit.SECONDS));
|
||||||
assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue