diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java index f663a228569..8825d08dab0 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java @@ -16,10 +16,12 @@ package org.eclipse.jetty.util; import java.io.File; import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -1640,7 +1642,7 @@ public final class URIUtil // Correct any bad `file:/path` usages, and // force encoding of characters that must be encoded (such as unicode) // for the base - String base = correctFileURI(uri).toASCIIString(); + String base = correctURI(uri).toASCIIString(); // ensure that the base has a safe encoding suitable for both // URI and Paths.get(URI) later usage @@ -1698,8 +1700,36 @@ public final class URIUtil * * @param uri the URI to (possibly) correct * @return the new URI with the {@code file:/} substring corrected, or the original URI. + * @deprecated use {@link #correctURI(URI)} instead, will be removed in Jetty 12.1.0 */ + @Deprecated(since = "12.0.7", forRemoval = true) public static URI correctFileURI(URI uri) + { + return correctURI(uri); + } + + /** + *

+ * Corrects any bad {@code file} based URIs (even within a {@code jar:file:} based URIs) from the bad out-of-spec + * format that various older Java APIs creates (most notably: {@link java.io.File} creates with it's {@link File#toURL()} + * and {@link File#toURI()}, along with the side effects of using {@link URL#toURI()}) + *

+ * + *

+ * This correction is currently limited to only the {@code file:/} substring in the URI. + * If there is a {@code file:/} detected, that substring is corrected to + * {@code file:///}, all other uses of {@code file:}, and URIs without a {@code file:} + * substring are left alone. + *

+ * + *

+ * Note that Windows UNC based URIs are left alone, along with non-absolute URIs. + *

+ * + * @param uri the URI to (possibly) correct + * @return the new URI with the {@code file:} scheme specific part corrected, or the original URI. + */ + public static URI correctURI(URI uri) { if ((uri == null) || (uri.getScheme() == null)) return uri; @@ -1845,10 +1875,60 @@ public final class URIUtil { Objects.requireNonNull(resource); - // Only try URI for string for known schemes, otherwise assume it is a Path - return (ResourceFactory.isSupported(resource)) - ? correctFileURI(URI.create(resource)) - : Paths.get(resource).toUri(); + if (URIUtil.hasScheme(resource)) + { + try + { + URI uri = new URI(resource); + + if (ResourceFactory.isSupported(uri)) + return correctURI(uri); + + // We don't have a supported URI scheme + if (uri.getScheme().length() == 1) + { + // Input is a possible Windows path disguised as a URI "D:/path/to/resource.txt". + try + { + return toURI(Paths.get(resource).toUri().toASCIIString()); + } + catch (InvalidPathException x) + { + LOG.trace("ignored", x); + } + } + + // If we reached this point, that means the input String has a scheme, + // and is not recognized as supported by the registered schemes in ResourceFactory. + if (LOG.isDebugEnabled()) + LOG.debug("URI scheme is not registered: {}", uri.toASCIIString()); + throw new IllegalArgumentException("URI scheme not registered: " + uri.getScheme()); + } + catch (URISyntaxException x) + { + // We have an input string that has what looks like a scheme, but isn't a URI. + // Eg: "C:\path\to\resource.txt" + LOG.trace("ignored", x); + } + } + + // If we reached this point, we have a String with no valid scheme. + // Treat it as a Path, as that's all we have left to investigate. + try + { + return toURI(Paths.get(resource).toUri().toASCIIString()); + } + catch (InvalidPathException x) + { + LOG.trace("ignored", x); + } + + // If we reached this here, that means the input string cannot be used as + // a URI or a File Path. The cause is usually due to bad input (eg: + // characters that are not supported by file system) + if (LOG.isDebugEnabled()) + LOG.debug("Input string cannot be converted to URI \"{}\"", resource); + throw new IllegalArgumentException("Cannot be converted to URI"); } /** @@ -1929,7 +2009,7 @@ public final class URIUtil .map(URL::toString) .map(URI::create) .map(URIUtil::unwrapContainer) - .map(URIUtil::correctFileURI); + .map(URIUtil::correctURI); } private static final Index DEFAULT_PORT_FOR_SCHEME = new Index.Builder() diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java index 6c68b6728de..14013f9d557 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/PathResource.java @@ -171,7 +171,7 @@ public class PathResource extends Resource { String uriString = uri.toASCIIString(); if (!uriString.endsWith("/")) - uri = URIUtil.correctFileURI(URI.create(uriString + "/")); + uri = URIUtil.correctURI(URI.create(uriString + "/")); } this.path = path; diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java index cae05a53dfd..37c417a001e 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java @@ -109,8 +109,8 @@ public abstract class Resource implements Iterable return false; // Ensure that if `file` scheme is used, it's using a consistent convention to allow for startsWith check - String thisURIString = URIUtil.correctFileURI(thisURI).toASCIIString(); - String otherURIString = URIUtil.correctFileURI(otherURI).toASCIIString(); + String thisURIString = URIUtil.correctURI(thisURI).toASCIIString(); + String otherURIString = URIUtil.correctURI(otherURI).toASCIIString(); return otherURIString.startsWith(thisURIString) && (thisURIString.length() == otherURIString.length() || otherURIString.charAt(thisURIString.length()) == '/'); @@ -315,7 +315,7 @@ public abstract class Resource implements Iterable } return; } - throw new UnsupportedOperationException("Directory Resources without a Path must implement copyTo"); + throw new UnsupportedOperationException("Directory Resources without a Path must implement copyTo: " + this); } // Do we have to copy a single file? @@ -326,12 +326,18 @@ public abstract class Resource implements Iterable { // to a directory, preserve the filename Path destPath = destination.resolve(src.getFileName().toString()); - Files.copy(src, destPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + Files.copy(src, destPath, + StandardCopyOption.ATOMIC_MOVE, + StandardCopyOption.COPY_ATTRIBUTES, + StandardCopyOption.REPLACE_EXISTING); } else { // to a file, use destination as-is - Files.copy(src, destination, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + Files.copy(src, destination, + StandardCopyOption.ATOMIC_MOVE, + StandardCopyOption.COPY_ATTRIBUTES, + StandardCopyOption.REPLACE_EXISTING); } return; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactoryInternals.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactoryInternals.java index a870ae70596..847659a0890 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactoryInternals.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/ResourceFactoryInternals.java @@ -213,13 +213,13 @@ class ResourceFactoryInternals // otherwise resolve against the current directory uri = CURRENT_WORKING_DIR.toUri().resolve(uri); - // Correct any `file:/path` to `file:///path` mistakes - uri = URIUtil.correctFileURI(uri); + // Correct any mistakes like `file:/path` (to `file:///path`) + uri = URIUtil.correctURI(uri); } ResourceFactory resourceFactory = RESOURCE_FACTORIES.get(uri.getScheme()); if (resourceFactory == null) - throw new IllegalArgumentException("URI scheme not supported: " + uri); + throw new IllegalArgumentException("URI scheme not registered: " + uri.getScheme()); if (resourceFactory instanceof MountedPathResourceFactory) { FileSystemPool.Mount mount = mountIfNeeded(uri); @@ -233,7 +233,9 @@ class ResourceFactoryInternals } catch (URISyntaxException | ProviderNotFoundException ex) { - throw new IllegalArgumentException("Unable to create resource from: " + uri, ex); + if (LOG.isDebugEnabled()) + LOG.debug("Unable to create resource from: {}", uri, ex); + throw new IllegalArgumentException("Unable to create resource", ex); } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/URLResourceFactory.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/URLResourceFactory.java index cbff9509b49..f186bb23c72 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/URLResourceFactory.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/resource/URLResourceFactory.java @@ -176,7 +176,7 @@ public class URLResourceFactory implements ResourceFactory @Override public URI getURI() { - return URIUtil.correctFileURI(uri); + return URIUtil.correctURI(uri); } @Override diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java index 16a6e55e448..e482337f0b0 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java @@ -57,7 +57,6 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; @ExtendWith(WorkDirExtension.class) public class URIUtilTest { - public WorkDir workDir; public static Stream encodePathSource() @@ -668,10 +667,10 @@ public class URIUtilTest @ParameterizedTest @MethodSource("correctBadFileURICases") - public void testCorrectFileURI(String input, String expected) + public void testCorrectURI(String input, String expected) { URI inputUri = URI.create(input); - URI actualUri = URIUtil.correctFileURI(inputUri); + URI actualUri = URIUtil.correctURI(inputUri); URI expectedUri = URI.create(expected); assertThat(actualUri.toASCIIString(), is(expectedUri.toASCIIString())); } @@ -695,8 +694,8 @@ public class URIUtilTest assertThat(fileUri.toASCIIString(), not(containsString("://"))); assertThat(fileUrlUri.toASCIIString(), not(containsString("://"))); - assertThat(URIUtil.correctFileURI(fileUri).toASCIIString(), is(expectedUri.toASCIIString())); - assertThat(URIUtil.correctFileURI(fileUrlUri).toASCIIString(), is(expectedUri.toASCIIString())); + assertThat(URIUtil.correctURI(fileUri).toASCIIString(), is(expectedUri.toASCIIString())); + assertThat(URIUtil.correctURI(fileUrlUri).toASCIIString(), is(expectedUri.toASCIIString())); } public static Stream encodeSpecific() @@ -1063,6 +1062,49 @@ public class URIUtilTest assertThat(actual.toASCIIString(), is(expected)); } + public static Stream toURICases() + { + List args = new ArrayList<>(); + + if (OS.WINDOWS.isCurrentOs()) + { + // Windows format (absolute and relative) + args.add(Arguments.of("C:\\path\\to\\foo.jar", "file:///C:/path/to/foo.jar")); + args.add(Arguments.of("D:\\path\\to\\bogus.txt", "file:///D:/path/to/bogus.txt")); + args.add(Arguments.of("\\path\\to\\foo.jar", "file:///C:/path/to/foo.jar")); + args.add(Arguments.of("\\path\\to\\bogus.txt", "file:///C:/path/to/bogus.txt")); + // unix format (relative) + args.add(Arguments.of("C:/path/to/foo.jar", "file:///C:/path/to/foo.jar")); + args.add(Arguments.of("D:/path/to/bogus.txt", "file:///D:/path/to/bogus.txt")); + args.add(Arguments.of("/path/to/foo.jar", "file:///C:/path/to/foo.jar")); + args.add(Arguments.of("/path/to/bogus.txt", "file:///C:/path/to/bogus.txt")); + // URI format (absolute) + args.add(Arguments.of("file:///D:/path/to/zed.jar", "file:///D:/path/to/zed.jar")); + args.add(Arguments.of("file:/e:/zed/yotta.txt", "file:///e:/zed/yotta.txt")); + args.add(Arguments.of("jar:file:///E:/path/to/bar.jar", "jar:file:///E:/path/to/bar.jar")); + } + else + { + // URI (and unix) format (relative) + args.add(Arguments.of("/path/to/foo.jar", "file:///path/to/foo.jar")); + args.add(Arguments.of("/path/to/bogus.txt", "file:///path/to/bogus.txt")); + } + // URI format (absolute) + args.add(Arguments.of("file:///path/to/zed.jar", "file:///path/to/zed.jar")); + args.add(Arguments.of("jar:file:///path/to/bar.jar", "jar:file:///path/to/bar.jar")); + + return args.stream(); + } + + @ParameterizedTest + @MethodSource("toURICases") + public void testToURI(String inputRaw, String expectedUri) + { + URI actual = URIUtil.toURI(inputRaw); + URI expected = URI.create(expectedUri); + assertEquals(expected, actual); + } + @Test public void testSplitSingleJar() { diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java index 89434af6509..e07cd7062d6 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/AttributeNormalizerTest.java @@ -13,6 +13,7 @@ package org.eclipse.jetty.util.resource; +import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.file.Files; @@ -335,13 +336,13 @@ public class AttributeNormalizerTest assertThat(normalizer.expand("${WAR.uri}/file1"), containsString("/dir1/file1")); assertThat(normalizer.expand("${WAR.uri}/file2"), containsString("/dir2/file2")); assertThat(normalizer.expand("${WAR.uri}/file3"), containsString("/dir3/file3")); - assertThat(normalizer.expand("${WAR.path}/file1"), containsString("/dir1/file1")); - assertThat(normalizer.expand("${WAR.path}/file2"), containsString("/dir2/file2")); - assertThat(normalizer.expand("${WAR.path}/file3"), containsString("/dir3/file3")); + assertThat(normalizer.expand("${WAR.path}/file1"), containsString(FS.separators("/dir1/file1"))); + assertThat(normalizer.expand("${WAR.path}/file2"), containsString(FS.separators("/dir2/file2"))); + assertThat(normalizer.expand("${WAR.path}/file3"), containsString(FS.separators("/dir3/file3"))); // If file cannot be found it just uses the first resource. assertThat(normalizer.expand("${WAR.uri}/file4"), containsString("/dir1/file4")); - assertThat(normalizer.expand("${WAR.path}/file4"), containsString("/dir1/file4")); + assertThat(normalizer.expand("${WAR.path}/file4"), containsString(File.separator + "dir1/file4")); } public static class Scenario diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java index fb586088fed..f45c7a0ee9e 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/CombinedResourceTest.java @@ -110,9 +110,9 @@ public class CombinedResourceTest .toList(); expected = new String[] { - "dir/1.txt", - "dir/2.txt", - "dir/3.txt" + FS.separators("dir/1.txt"), + FS.separators("dir/2.txt"), + FS.separators("dir/3.txt") }; assertThat(relative, containsInAnyOrder(expected)); @@ -281,9 +281,9 @@ public class CombinedResourceTest "2.txt", "3.txt", "4.txt", - "dir/1.txt", - "dir/2.txt", - "dir/3.txt" + FS.separators("dir/1.txt"), + FS.separators("dir/2.txt"), + FS.separators("dir/3.txt") }; assertThat(actual, contains(expected)); @@ -804,9 +804,9 @@ public class CombinedResourceTest "2.txt", "3.txt", "dir", - "dir/1.txt", - "dir/2.txt", - "dir/3.txt" + FS.separators("dir/1.txt"), + FS.separators("dir/2.txt"), + FS.separators("dir/3.txt") )); } diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java index c3aa50f5345..ab89e145738 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/FileSystemResourceTest.java @@ -172,14 +172,16 @@ public class FileSystemResourceTest Files.createDirectories(testdir); Path pwd = Paths.get(System.getProperty("user.dir")); - Path relativePath = pwd.relativize(testdir); + + // Establish a relative path URI that uses uri "/" path separators (now windows "\") + URI relativePath = pwd.toUri().relativize(testdir.toUri()); // Get a path relative name using unix/uri "/" (not windows "\") - String relativeName = FS.separators(relativePath.toString()); - assertThat("Should not have path navigation entries", relativeName, not(containsString(".."))); + assertThat("Should not have path navigation entries", relativePath.toASCIIString(), not(containsString(".."))); + assertFalse(relativePath.isAbsolute()); - resource = ResourceFactory.root().newResource(new URI(relativeName)); - assertThat("Relative newResource: " + relativeName, resource, notNullValue()); + resource = ResourceFactory.root().newResource(relativePath); + assertThat("Relative newResource: " + relativePath, resource, notNullValue()); assertThat(resource.getURI().toString(), startsWith("file:")); assertThat(resource.getURI().toString(), endsWith("/path/to/resource/")); } @@ -1095,7 +1097,8 @@ public class FileSystemResourceTest if (WINDOWS.isCurrentOs()) { - assertThat("getURI()", r.getPath().toString(), containsString("aa\\/foo.txt")); + // On windows, the extra "\" is stripped when working with java.nio.Path objects + assertThat("getURI()", r.getPath().toString(), containsString("aa\\foo.txt")); assertThat("getURI()", r.getURI().toASCIIString(), containsString("aa%5C/foo.txt")); assertThat("isAlias()", r.isAlias(), is(true)); assertThat("getRealURI()", r.getRealURI(), notNullValue()); @@ -1279,7 +1282,16 @@ public class FileSystemResourceTest Resource r = base.resolve("file.txt"); assertThat("Exists: " + r, r.exists(), is(true)); - assertThat("Is Not Alias: " + r, r, isNotAlias()); + if (WINDOWS.isCurrentOs()) + { + // On windows, the base.resolve results in a representation of ".../testUtf8Dir/b%C3%A3m/file.txt" + // But that differs from the input URI of ".../testUtf8Dir/bãm/file.txt", so it is viewed as an alias. + assertThat("Is Alias: " + r, r, isAlias()); + URI realURI = r.getRealURI(); + assertThat(realURI, is(file.toUri())); + } + else + assertThat("Is Not Alias: " + r, r, isNotAlias()); } @Test @@ -1287,6 +1299,7 @@ public class FileSystemResourceTest public void testUncPath() { Resource base = ResourceFactory.root().newResource(URI.create("file:////127.0.0.1/path")); + assumeTrue(base != null); Resource resource = base.resolve("WEB-INF/"); assertThat("getURI()", resource.getURI().toASCIIString(), containsString("path/WEB-INF/")); assertThat("isAlias()", resource.isAlias(), is(false)); diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/PathResourceTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/PathResourceTest.java index 24f85ac3e89..a183776aec6 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/PathResourceTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/PathResourceTest.java @@ -38,6 +38,7 @@ import org.eclipse.jetty.util.URIUtil; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -736,8 +737,21 @@ public class PathResourceTest { Path testDir = workDir.getEmptyPathDir(); Path resourcePath = testDir.resolve("resource.txt"); + Path symlinkPath = null; IO.copy(MavenTestingUtils.getTestResourcePathFile("resource.txt").toFile(), resourcePath.toFile()); - Path symlinkPath = Files.createSymbolicLink(testDir.resolve("symlink.txt"), resourcePath); + boolean symlinkSupported; + try + { + symlinkPath = Files.createSymbolicLink(testDir.resolve("symlink.txt"), resourcePath); + symlinkSupported = true; + } + catch (UnsupportedOperationException | FileSystemException e) + { + symlinkSupported = false; + } + + assumeTrue(symlinkSupported, "Symlink not supported"); + assertNotNull(symlinkPath); PathResource fileResource = new PathResource(resourcePath); assertTrue(fileResource.exists()); @@ -786,7 +800,10 @@ public class PathResourceTest Resource rootRes = resourceFactory.newResource(docroot); // Test navigation through a directory that doesn't exist Resource fileResViaBar = rootRes.resolve("bar/../dir/test.txt"); - assertTrue(Resources.missing(fileResViaBar)); + if (OS.WINDOWS.isCurrentOs()) // windows allows navigation through a non-existent directory + assertTrue(Resources.exists(fileResViaBar)); + else + assertTrue(Resources.missing(fileResViaBar)); // Test navigation through a directory that does exist Resource fileResViaFoo = rootRes.resolve("foo/../dir/test.txt"); diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceAliasTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceAliasTest.java index c49e3e4e632..c6a97baaf58 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceAliasTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceAliasTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,7 +74,10 @@ public class ResourceAliasTest Resource rootRes = resourceFactory.newResource(docroot); // Test navigation through a directory that doesn't exist Resource fileResViaBar = rootRes.resolve("bar/../dir/test.txt"); - assertTrue(Resources.missing(fileResViaBar), "File doesn't exist"); + if (OS.WINDOWS.isCurrentOs()) // windows allows navigation through a non-existent directory + assertTrue(Resources.exists(fileResViaBar)); + else + assertTrue(Resources.missing(fileResViaBar), "File doesn't exist"); // Test navigation through a directory that does exist Resource fileResViaFoo = rootRes.resolve("foo/../dir/test.txt"); diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceFactoryTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceFactoryTest.java index ab833cd01ca..b0781a62c3c 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceFactoryTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceFactoryTest.java @@ -135,16 +135,15 @@ public class ResourceFactoryTest // Try this as a normal String input first. // We are subject to the URIUtil.toURI(String) behaviors here. // Since the `ftp` scheme is not registered, it's not recognized as a supported URI. - // This will be treated as a relative path instead. (and the '//' will be compacted) - Resource resource = ResourceFactory.root().newResource("ftp://webtide.com/favicon.ico"); - // Should not find this, as it doesn't exist on the filesystem. - assertNull(resource); + IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, + () -> ResourceFactory.root().newResource("ftp://webtide.com/favicon.ico")); + assertThat(iae.getMessage(), containsString("URI scheme not registered: ftp")); // Now try it as a formal URI object as input. URI uri = URI.create("ftp://webtide.com/favicon.ico"); // This is an unsupported URI scheme - IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, () -> ResourceFactory.root().newResource(uri)); - assertThat(iae.getMessage(), containsString("URI scheme not supported")); + iae = assertThrows(IllegalArgumentException.class, () -> ResourceFactory.root().newResource(uri)); + assertThat(iae.getMessage(), containsString("URI scheme not registered: ftp")); } @Test diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java index bdddb610385..e690b8ee9df 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java @@ -434,7 +434,17 @@ public class ResourceTest Resource resource = resourceFactory.newResource(file); // Requesting a resource that would point to a location called ".../testDotAliasFileExists/foo/bar.txt/." Resource dot = resource.resolve("."); - assertTrue(Resources.missing(dot), "Cannot reference file as a directory"); + if (OS.WINDOWS.isCurrentOs()) + { + // windows allows this reference, but it's an alias. + assertTrue(Resources.exists(dot), "Reference to directory via dot allowed"); + assertTrue(dot.isAlias(), "Reference to dot is an alias to actual bar.txt"); + assertEquals(dot.getRealURI(), file.toUri()); + } + else + { + assertTrue(Resources.missing(dot), "Cannot reference file as a directory"); + } } @Test diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/UrlResourceFactoryTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/UrlResourceFactoryTest.java index 36037417d46..7f028f4b5a9 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/UrlResourceFactoryTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/resource/UrlResourceFactoryTest.java @@ -274,7 +274,7 @@ public class UrlResourceFactoryTest assertThat("resource /path/to/example.jar/WEB-INF/web.xml doesn't exist", webResource.exists(), is(false)); assertThat(webResource.isDirectory(), is(false)); - URI expectedURI = URIUtil.correctFileURI(URI.create("file:" + path.toUri().toASCIIString() + "/WEB-INF/web.xml")); + URI expectedURI = URIUtil.correctURI(URI.create("file:" + path.toUri().toASCIIString() + "/WEB-INF/web.xml")); assertThat(webResource.getURI(), is(expectedURI)); } @@ -296,7 +296,7 @@ public class UrlResourceFactoryTest assertThat("resource /path/to/example.jar/WEB-INF/web.xml doesn't exist", webResource.exists(), is(false)); assertThat(webResource.isDirectory(), is(false)); - URI expectedURI = URIUtil.correctFileURI(URI.create(path.toUri().toASCIIString() + "/WEB-INF/web.xml")); + URI expectedURI = URIUtil.correctURI(URI.create(path.toUri().toASCIIString() + "/WEB-INF/web.xml")); assertThat(webResource.getURI(), is(expectedURI)); } diff --git a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java index 23c8d914676..c4a77082d1f 100644 --- a/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java +++ b/jetty-core/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java @@ -43,6 +43,8 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -381,6 +383,7 @@ public class SslContextFactoryTest } @Test + @DisabledOnOs(value = OS.WINDOWS, disabledReason = "Will result in java.net.SocketException: An established connection was aborted by the software in your host machine during IO.readBytes(input)") public void testSNIWithPKIX() throws Exception { SslContextFactory.Server serverTLS = new SslContextFactory.Server() diff --git a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/MetaInfConfigurationTest.java b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/MetaInfConfigurationTest.java index 6cf334c03ef..3d54cf02593 100644 --- a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/MetaInfConfigurationTest.java +++ b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/MetaInfConfigurationTest.java @@ -562,8 +562,8 @@ public class MetaInfConfigurationTest // we "correct" the bad file URLs that come from the ClassLoader // to be the same as what comes from every non-classloader URL/URI. String[] expectedContainerResources = { - URIUtil.correctFileURI(janbUri).toASCIIString(), - URIUtil.correctFileURI(servletUri).toASCIIString() + URIUtil.correctURI(janbUri).toASCIIString(), + URIUtil.correctURI(servletUri).toASCIIString() }; assertThat("Discovered Container resources", discoveredContainerResources, hasItems(expectedContainerResources)); }