diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 875eb3c72416..5ebeceeda955 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long suite = { - "mxversion": "5.316.15", + "mxversion": "5.319.0", "name": "substratevm", "version" : "22.1.0", "release" : False, diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index b73197196f91..2107197ef39b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -29,7 +29,6 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; @@ -43,7 +42,6 @@ import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.jdk.resources.NativeImageResourcePath; import com.oracle.svm.core.jdk.resources.ResourceStorageEntry; import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.core.util.VMError; @@ -85,9 +83,13 @@ public static byte[] inputStreamToByteArray(InputStream is) { } } + private static String getResourceWithoutTrailingSlash(String name) { + return name.endsWith("/") ? name.substring(0, name.length() - 1) : name; + } + private static void addEntry(String moduleName, String resourceName, boolean isDirectory, byte[] data) { Resources support = singleton(); - Pair key = Pair.create(moduleName, resourceName); + Pair key = Pair.create(moduleName, getResourceWithoutTrailingSlash(resourceName)); ResourceStorageEntry entry = support.resources.get(key); if (entry == null) { entry = new ResourceStorageEntry(isDirectory); @@ -121,21 +123,17 @@ public static void registerDirectoryResource(String moduleName, String resourceD addEntry(moduleName, resourceDirName, true, content.getBytes()); } - /** - * Avoid pulling native file system by using {@link NativeImageResourcePath} implementation to - * convert resourceName to canonical variant. - */ - public static String toCanonicalForm(String resourceName) { - NativeImageResourcePath path = new NativeImageResourcePath(null, resourceName.getBytes(StandardCharsets.UTF_8), true); - return new String(NativeImageResourcePath.getResolved(path)); - } - public static ResourceStorageEntry get(String name) { - return singleton().resources.get(Pair.createRight(name)); + return get(null, name); } public static ResourceStorageEntry get(String moduleName, String resourceName) { - return singleton().resources.get(Pair.create(moduleName, resourceName)); + ResourceStorageEntry resourceStorageEntry = singleton().resources.get(Pair.create(moduleName, getResourceWithoutTrailingSlash(resourceName))); + if (resourceStorageEntry != null && (resourceStorageEntry.isDirectory() || !resourceName.endsWith("/"))) { + return resourceStorageEntry; + } else { + return null; + } } private static URL createURL(String moduleName, String resourceName, int index) { @@ -156,7 +154,7 @@ public static URL createURL(String moduleName, String resourceName) { return null; } - Enumeration urls = createURLs(moduleName, toCanonicalForm(resourceName)); + Enumeration urls = createURLs(moduleName, resourceName); return urls.hasMoreElements() ? urls.nextElement() : null; } @@ -170,7 +168,7 @@ public static InputStream createInputStream(String moduleName, String resourceNa return null; } - ResourceStorageEntry entry = Resources.get(moduleName, toCanonicalForm(resourceName)); + ResourceStorageEntry entry = Resources.get(moduleName, resourceName); if (entry == null) { return null; } @@ -186,19 +184,18 @@ public static Enumeration createURLs(String moduleName, String resourceName if (resourceName == null) { return null; } - String canonicalResourceName = toCanonicalForm(resourceName); List resourcesURLs = new ArrayList<>(); /* If moduleName was unspecified we have to consider all modules in the image */ if (moduleName == null) { for (Module module : BootModuleLayerSupport.instance().getBootLayer().modules()) { - ResourceStorageEntry entry = Resources.get(module.getName(), canonicalResourceName); - addURLEntries(resourcesURLs, entry, module.getName(), canonicalResourceName); + ResourceStorageEntry entry = Resources.get(module.getName(), resourceName); + addURLEntries(resourcesURLs, entry, module.getName(), resourceName); } } - ResourceStorageEntry explicitEntry = Resources.get(moduleName, canonicalResourceName); - addURLEntries(resourcesURLs, explicitEntry, moduleName, canonicalResourceName); + ResourceStorageEntry explicitEntry = Resources.get(moduleName, resourceName); + addURLEntries(resourcesURLs, explicitEntry, moduleName, resourceName); if (resourcesURLs.isEmpty()) { return Collections.emptyEnumeration(); @@ -206,13 +203,13 @@ public static Enumeration createURLs(String moduleName, String resourceName return Collections.enumeration(resourcesURLs); } - private static void addURLEntries(List resourcesURLs, ResourceStorageEntry entry, String moduleName, String canonicalResourceName) { + private static void addURLEntries(List resourcesURLs, ResourceStorageEntry entry, String moduleName, String resourceName) { if (entry == null) { return; } int numberOfResources = entry.getData().size(); for (int index = 0; index < numberOfResources; index++) { - resourcesURLs.add(createURL(moduleName, canonicalResourceName, index)); + resourcesURLs.add(createURL(moduleName, resourceName, index)); } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java index 104b87d65b19..3b9edb0c0c76 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java @@ -58,7 +58,7 @@ public void connect() { throw new IllegalArgumentException("Empty URL path not allowed in " + JavaNetSubstitutions.RESOURCE_PROTOCOL + " URL"); } String resourceName = urlPath.substring(1); - ResourceStorageEntry entry = Resources.get(hostNameOrNull, Resources.toCanonicalForm(resourceName)); + ResourceStorageEntry entry = Resources.get(hostNameOrNull, resourceName); if (entry != null) { List bytes = entry.getData(); String urlRef = url.getRef(); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceFileSystemProviderTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceFileSystemProviderTest.java index 31c7d9971b00..38f0c620ec8b 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceFileSystemProviderTest.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceFileSystemProviderTest.java @@ -85,6 +85,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { // Remove leading / for the resource patterns registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_FILE_1.substring(1)); registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_FILE_2.substring(1)); + registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_DIR.substring(1)); /** Needed for {@link #testURLExternalFormEquivalence()} */ for (Module module : ModuleLayer.boot().modules()) { @@ -631,4 +632,22 @@ public void testURLExternalFormEquivalence() { Assert.fail("Contents of original URL and one created from originals ExternalForm must be the same: " + e); } } + + @Test + public void noCanonicalizationInGetResource() { + Class klass = NativeImageResourceFileSystemProviderTest.class; + URL url = klass.getResource(RESOURCE_DIR + "/"); + Assert.assertNotNull(url); + Assert.assertTrue(url.toString().endsWith("/")); + url = klass.getResource(RESOURCE_DIR); + Assert.assertNotNull(url); + Assert.assertFalse(url.toString().endsWith("/")); + url = klass.getResource(RESOURCE_DIR + "/./"); + Assert.assertNull(url); + url = klass.getResource(RESOURCE_FILE_1); + Assert.assertNotNull(url); + url = klass.getResource(RESOURCE_FILE_1 + "/"); + Assert.assertNull(url); + } + } diff --git a/substratevm/src/com.oracle.svm.test/src/resources/.mxkeep b/substratevm/src/com.oracle.svm.test/src/resources/.mxkeep new file mode 100644 index 000000000000..5c74e3c55f30 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/resources/.mxkeep @@ -0,0 +1 @@ +This file instructs mx to create a jar entry for the parent directory \ No newline at end of file