Skip to content

Commit 2745ebf

Browse files
committed
[GR-37154] Fix handling of resources with trailing slashes.
PullRequest: graal/11203
2 parents ec77126 + dfa1ec9 commit 2745ebf

File tree

5 files changed

+42
-25
lines changed

5 files changed

+42
-25
lines changed

substratevm/mx.substratevm/suite.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pylint: disable=line-too-long
22
suite = {
3-
"mxversion": "5.316.15",
3+
"mxversion": "5.319.0",
44
"name": "substratevm",
55
"version" : "22.1.0",
66
"release" : False,

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.io.InputStream;
3030
import java.net.MalformedURLException;
3131
import java.net.URL;
32-
import java.nio.charset.StandardCharsets;
3332
import java.util.ArrayList;
3433
import java.util.Collections;
3534
import java.util.Enumeration;
@@ -43,7 +42,6 @@
4342
import org.graalvm.nativeimage.hosted.Feature;
4443

4544
import com.oracle.svm.core.annotate.AutomaticFeature;
46-
import com.oracle.svm.core.jdk.resources.NativeImageResourcePath;
4745
import com.oracle.svm.core.jdk.resources.ResourceStorageEntry;
4846
import com.oracle.svm.core.util.ImageHeapMap;
4947
import com.oracle.svm.core.util.VMError;
@@ -85,9 +83,13 @@ public static byte[] inputStreamToByteArray(InputStream is) {
8583
}
8684
}
8785

86+
private static String getResourceWithoutTrailingSlash(String name) {
87+
return name.endsWith("/") ? name.substring(0, name.length() - 1) : name;
88+
}
89+
8890
private static void addEntry(String moduleName, String resourceName, boolean isDirectory, byte[] data) {
8991
Resources support = singleton();
90-
Pair<String, String> key = Pair.create(moduleName, resourceName);
92+
Pair<String, String> key = Pair.create(moduleName, getResourceWithoutTrailingSlash(resourceName));
9193
ResourceStorageEntry entry = support.resources.get(key);
9294
if (entry == null) {
9395
entry = new ResourceStorageEntry(isDirectory);
@@ -121,21 +123,17 @@ public static void registerDirectoryResource(String moduleName, String resourceD
121123
addEntry(moduleName, resourceDirName, true, content.getBytes());
122124
}
123125

124-
/**
125-
* Avoid pulling native file system by using {@link NativeImageResourcePath} implementation to
126-
* convert <code>resourceName</code> to canonical variant.
127-
*/
128-
public static String toCanonicalForm(String resourceName) {
129-
NativeImageResourcePath path = new NativeImageResourcePath(null, resourceName.getBytes(StandardCharsets.UTF_8), true);
130-
return new String(NativeImageResourcePath.getResolved(path));
131-
}
132-
133126
public static ResourceStorageEntry get(String name) {
134-
return singleton().resources.get(Pair.createRight(name));
127+
return get(null, name);
135128
}
136129

137130
public static ResourceStorageEntry get(String moduleName, String resourceName) {
138-
return singleton().resources.get(Pair.create(moduleName, resourceName));
131+
ResourceStorageEntry resourceStorageEntry = singleton().resources.get(Pair.create(moduleName, getResourceWithoutTrailingSlash(resourceName)));
132+
if (resourceStorageEntry != null && (resourceStorageEntry.isDirectory() || !resourceName.endsWith("/"))) {
133+
return resourceStorageEntry;
134+
} else {
135+
return null;
136+
}
139137
}
140138

141139
private static URL createURL(String moduleName, String resourceName, int index) {
@@ -156,7 +154,7 @@ public static URL createURL(String moduleName, String resourceName) {
156154
return null;
157155
}
158156

159-
Enumeration<URL> urls = createURLs(moduleName, toCanonicalForm(resourceName));
157+
Enumeration<URL> urls = createURLs(moduleName, resourceName);
160158
return urls.hasMoreElements() ? urls.nextElement() : null;
161159
}
162160

@@ -170,7 +168,7 @@ public static InputStream createInputStream(String moduleName, String resourceNa
170168
return null;
171169
}
172170

173-
ResourceStorageEntry entry = Resources.get(moduleName, toCanonicalForm(resourceName));
171+
ResourceStorageEntry entry = Resources.get(moduleName, resourceName);
174172
if (entry == null) {
175173
return null;
176174
}
@@ -186,33 +184,32 @@ public static Enumeration<URL> createURLs(String moduleName, String resourceName
186184
if (resourceName == null) {
187185
return null;
188186
}
189-
String canonicalResourceName = toCanonicalForm(resourceName);
190187

191188
List<URL> resourcesURLs = new ArrayList<>();
192189

193190
/* If moduleName was unspecified we have to consider all modules in the image */
194191
if (moduleName == null) {
195192
for (Module module : BootModuleLayerSupport.instance().getBootLayer().modules()) {
196-
ResourceStorageEntry entry = Resources.get(module.getName(), canonicalResourceName);
197-
addURLEntries(resourcesURLs, entry, module.getName(), canonicalResourceName);
193+
ResourceStorageEntry entry = Resources.get(module.getName(), resourceName);
194+
addURLEntries(resourcesURLs, entry, module.getName(), resourceName);
198195
}
199196
}
200-
ResourceStorageEntry explicitEntry = Resources.get(moduleName, canonicalResourceName);
201-
addURLEntries(resourcesURLs, explicitEntry, moduleName, canonicalResourceName);
197+
ResourceStorageEntry explicitEntry = Resources.get(moduleName, resourceName);
198+
addURLEntries(resourcesURLs, explicitEntry, moduleName, resourceName);
202199

203200
if (resourcesURLs.isEmpty()) {
204201
return Collections.emptyEnumeration();
205202
}
206203
return Collections.enumeration(resourcesURLs);
207204
}
208205

209-
private static void addURLEntries(List<URL> resourcesURLs, ResourceStorageEntry entry, String moduleName, String canonicalResourceName) {
206+
private static void addURLEntries(List<URL> resourcesURLs, ResourceStorageEntry entry, String moduleName, String resourceName) {
210207
if (entry == null) {
211208
return;
212209
}
213210
int numberOfResources = entry.getData().size();
214211
for (int index = 0; index < numberOfResources; index++) {
215-
resourcesURLs.add(createURL(moduleName, canonicalResourceName, index));
212+
resourcesURLs.add(createURL(moduleName, resourceName, index));
216213
}
217214
}
218215
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/ResourceURLConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void connect() {
5858
throw new IllegalArgumentException("Empty URL path not allowed in " + JavaNetSubstitutions.RESOURCE_PROTOCOL + " URL");
5959
}
6060
String resourceName = urlPath.substring(1);
61-
ResourceStorageEntry entry = Resources.get(hostNameOrNull, Resources.toCanonicalForm(resourceName));
61+
ResourceStorageEntry entry = Resources.get(hostNameOrNull, resourceName);
6262
if (entry != null) {
6363
List<byte[]> bytes = entry.getData();
6464
String urlRef = url.getRef();

substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceFileSystemProviderTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
8585
// Remove leading / for the resource patterns
8686
registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_FILE_1.substring(1));
8787
registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_FILE_2.substring(1));
88+
registry.addResources(ConfigurationCondition.alwaysTrue(), RESOURCE_DIR.substring(1));
8889

8990
/** Needed for {@link #testURLExternalFormEquivalence()} */
9091
for (Module module : ModuleLayer.boot().modules()) {
@@ -631,4 +632,22 @@ public void testURLExternalFormEquivalence() {
631632
Assert.fail("Contents of original URL and one created from originals ExternalForm must be the same: " + e);
632633
}
633634
}
635+
636+
@Test
637+
public void noCanonicalizationInGetResource() {
638+
Class<?> klass = NativeImageResourceFileSystemProviderTest.class;
639+
URL url = klass.getResource(RESOURCE_DIR + "/");
640+
Assert.assertNotNull(url);
641+
Assert.assertTrue(url.toString().endsWith("/"));
642+
url = klass.getResource(RESOURCE_DIR);
643+
Assert.assertNotNull(url);
644+
Assert.assertFalse(url.toString().endsWith("/"));
645+
url = klass.getResource(RESOURCE_DIR + "/./");
646+
Assert.assertNull(url);
647+
url = klass.getResource(RESOURCE_FILE_1);
648+
Assert.assertNotNull(url);
649+
url = klass.getResource(RESOURCE_FILE_1 + "/");
650+
Assert.assertNull(url);
651+
}
652+
634653
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This file instructs mx to create a jar entry for the parent directory

0 commit comments

Comments
 (0)