Issue #4287 - Move getUriLastPathSegment() to URIUtil

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2019-11-07 15:52:00 -06:00
parent b119a8f59f
commit 4ab910bdc0
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
5 changed files with 152 additions and 136 deletions

View File

@ -750,6 +750,42 @@ public class URIUtil
return buf.toString();
}
/**
* Given a URI, attempt to get the last segment.
* <p>
* If this is a {@code jar:file://} style URI, then
* the JAR filename is returned (not the deep {@code !/path} location)
* </p>
*
* @param uri the URI to look in
* @return the last segment.
*/
public 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;
}
/**
* Return the parent Path.
* Treat a URI like a directory path and return the parent directory.

View File

@ -18,13 +18,31 @@
package org.eclipse.jetty.util;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
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.junit.jupiter.api.Test;
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;
@ -39,8 +57,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* URIUtil Tests.
*/
@SuppressWarnings("SpellCheckingInspection")
@ExtendWith(WorkDirExtension.class)
public class URIUtilTest
{
private static final Logger LOG = Log.getLogger(URIUtilTest.class);
public WorkDir workDir;
public static Stream<Arguments> encodePathSource()
{
return Stream.of(
@ -548,4 +570,97 @@ public class URIUtilTest
{
assertThat(URIUtil.decodeSpecific(raw, chars), is(expected));
}
public static Stream<Arguments> resourceUriLastSegmentSource()
{
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")
);
}
/**
* Using FileSystem provided URIs, attempt to get last URI path segment
*/
@ParameterizedTest
@MethodSource("resourceUriLastSegmentSource")
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(URIUtil.getUriLastPathSegment(uri), is(expectedName));
}
public static Stream<Arguments> uriLastSegmentSource() throws URISyntaxException, IOException
{
final String TEST_RESOURCE_JAR = "test-base-resource.jar";
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)
{
assertThat(URIUtil.getUriLastPathSegment(uri), is(expectedName));
}
}

View File

@ -844,33 +844,7 @@ public class WebInfConfiguration extends AbstractConfiguration
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;
return URIUtil.getUriLastPathSegment(uri);
}
protected List<Resource> findClassDirs(WebAppContext context)

View File

@ -19,27 +19,14 @@
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.JavaVersion;
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.Test;
@ -47,7 +34,6 @@ import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.api.condition.EnabledOnJre;
import org.junit.jupiter.api.condition.JRE;
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;
@ -66,9 +52,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
@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;
/**
@ -197,96 +180,4 @@ public class WebInfConfigurationTest
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));
}
}