Skip to content

Commit 50218dc

Browse files
committed
[GR-50220] Allow resources inclusion from jar files in paths containing spaces #7815.
PullRequest: graal/16146
2 parents 26519af + 2d4c719 commit 50218dc

File tree

10 files changed

+193
-5
lines changed

10 files changed

+193
-5
lines changed

substratevm/mx.substratevm/suite.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,24 @@
946946
"jacoco" : "exclude",
947947
},
948948

949+
"com.oracle.svm.with.space.test": {
950+
"subDir": "src",
951+
"sourceDirs": ["src"],
952+
"dependencies": [
953+
"mx:JUNIT_TOOL",
954+
"sdk:NATIVEIMAGE",
955+
],
956+
"checkstyle": "com.oracle.svm.test",
957+
"workingSets": "SVM",
958+
"annotationProcessors": [
959+
"compiler:GRAAL_PROCESSOR",
960+
"SVM_PROCESSOR",
961+
],
962+
"javaCompliance" : "21+",
963+
"spotbugs": "false",
964+
"jacoco" : "exclude",
965+
},
966+
949967
"com.oracle.svm.configure.test": {
950968
"subDir": "src",
951969
"sourceDirs": ["src"],
@@ -1992,6 +2010,21 @@
19922010
"testDistribution" : True,
19932011
},
19942012

2013+
# Special test distribution used for testing inclusion of resources from jar files with a space in their name.
2014+
# The space in the distribution name is intentional.
2015+
"SVM_TESTS WITH SPACE" : {
2016+
"subDir": "src",
2017+
"relpath" : True,
2018+
"dependencies" : [
2019+
"com.oracle.svm.with.space.test",
2020+
],
2021+
"distDependencies": [
2022+
"sdk:NATIVEIMAGE",
2023+
"mx:JUNIT_TOOL",
2024+
],
2025+
"testDistribution" : True,
2026+
},
2027+
19952028
"POLYGLOT_NATIVE_API" : {
19962029
"subDir": "src",
19972030
"dependencies": [

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -281,12 +281,12 @@ private void processResourceFromModule(Module module, String resourcePath) {
281281
}
282282
}
283283

284-
InputStream is = module.getResourceAsStream(resourcePath);
285284
boolean isDirectory = Files.isDirectory(Path.of(resourcePath));
286285
if (isDirectory) {
287286
String content = getDirectoryContent(resourcePath, false);
288287
Resources.singleton().registerDirectoryResource(module, resourcePath, content, false);
289288
} else {
289+
InputStream is = module.getResourceAsStream(resourcePath);
290290
registerResource(module, resourcePath, false, is);
291291
}
292292
} catch (IOException e) {
@@ -317,13 +317,13 @@ private void processResourceFromClasspath(String resourcePath) {
317317

318318
alreadyProcessedResources.add(url.toString());
319319
try {
320-
InputStream is = url.openStream();
321320
boolean fromJar = url.getProtocol().equalsIgnoreCase("jar");
322321
boolean isDirectory = resourceIsDirectory(url, fromJar, resourcePath);
323322
if (isDirectory) {
324323
String content = getDirectoryContent(fromJar ? url.toString() : Paths.get(url.toURI()).toString(), fromJar);
325324
Resources.singleton().registerDirectoryResource(null, resourcePath, content, fromJar);
326325
} else {
326+
InputStream is = url.openStream();
327327
registerResource(null, resourcePath, fromJar, is);
328328
}
329329
} catch (IOException e) {
@@ -352,8 +352,8 @@ private void registerResource(Module module, String resourcePath, boolean fromJa
352352
/* Util functions for resource attributes calculations */
353353
private String urlToJarPath(URL url) {
354354
try {
355-
return ((JarURLConnection) url.openConnection()).getJarFileURL().getFile();
356-
} catch (IOException e) {
355+
return ((JarURLConnection) url.openConnection()).getJarFileURL().toURI().getPath();
356+
} catch (IOException | URISyntaxException e) {
357357
throw new RuntimeException(e);
358358
}
359359
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package com.oracle.svm.test;
2727

2828
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR;
29+
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR_WITH_SPACE;
2930
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_EMPTY_DIR;
3031
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_1;
3132
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_2;
@@ -231,6 +232,20 @@ public void queryEmptyDir() {
231232
}
232233
}
233234

235+
/**
236+
* Query a directory with spaces in its name.
237+
*/
238+
@Test
239+
public void queryDirWithSpaces() {
240+
Path dirWithSpaces = fileSystem.getPath(RESOURCE_DIR_WITH_SPACE);
241+
try (Stream<Path> stream = Files.walk(dirWithSpaces)) {
242+
Assert.assertEquals(1, stream.count());
243+
} catch (IOException e) {
244+
e.printStackTrace();
245+
Assert.fail("IOException occurred during file system walk, starting from the root.");
246+
}
247+
}
248+
234249
/**
235250
* Reading from file using {@link java.nio.channels.ByteChannel}.
236251
*/

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package com.oracle.svm.test;
2727

2828
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR;
29+
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR_WITH_SPACE;
2930
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_1;
3031
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_2;
3132
import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_3;
@@ -131,6 +132,19 @@ public void classGetDirectoryResource() {
131132
resourceNameToURL(nonCanonicalResourceDirectoryName, false);
132133
}
133134

135+
@Test
136+
public void classGetDirectoryWithSpaceResource() {
137+
URL url1 = resourceNameToURL(RESOURCE_DIR_WITH_SPACE + "/", true);
138+
Assert.assertTrue("The URL should end with slash!", url1.toString().endsWith("/"));
139+
140+
URL url2 = resourceNameToURL(RESOURCE_DIR_WITH_SPACE, true);
141+
Assert.assertFalse("The URL should not end with slash!", url2.toString().endsWith("/"));
142+
Assert.assertTrue("Two URLs must be the same!", compareTwoURLs(url1, url2));
143+
144+
String nonCanonicalResourceDirectoryName = RESOURCE_DIR_WITH_SPACE + "/./";
145+
resourceNameToURL(nonCanonicalResourceDirectoryName, false);
146+
}
147+
134148
@Test
135149
public void registeredResourceDirectoryHasContent() throws IOException {
136150
URL directory = NativeImageResourceUtils.class.getResource(SIMPLE_RESOURCE_DIR);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class NativeImageResourceUtils {
4444
public static final String RESOURCE_DIR = "/resources";
4545
public static final String SIMPLE_RESOURCE_DIR = "/simpleDir";
4646
public static final String RESOURCE_EMPTY_DIR = RESOURCE_DIR + "/empty";
47+
public static final String RESOURCE_DIR_WITH_SPACE = RESOURCE_DIR + "/dir with space";
4748
public static final String RESOURCE_FILE_1 = RESOURCE_DIR + "/resource-test1.txt";
4849
public static final String RESOURCE_FILE_2 = RESOURCE_DIR + "/resource-test2.txt";
4950
public static final String RESOURCE_FILE_3 = RESOURCE_DIR + "/resource-test3.html";
@@ -58,6 +59,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
5859
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR.substring(1));
5960
RuntimeResourceAccess.addResource(resourceModule, SIMPLE_RESOURCE_DIR.substring(1));
6061
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_EMPTY_DIR.substring(1));
62+
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR_WITH_SPACE.substring(1));
6163
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_1.substring(1));
6264
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_2.substring(1));
6365
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_3.substring(1));
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Args= \
2+
--initialize-at-run-time=com.oracle.svm.with.space.test \
3+
--features=com.oracle.svm.with.space.test.NativeImageResourceUtils$TestFeature
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.oracle.svm.with.space.test;
27+
28+
import java.net.URL;
29+
import java.nio.file.Path;
30+
31+
import org.junit.Assert;
32+
import org.junit.Test;
33+
34+
public class NativeImageResourceTest {
35+
36+
@Test
37+
@SuppressWarnings("deprecation")
38+
public void accessFileFromJarWithSpaceInName() {
39+
URL url = NativeImageResourceUtils.resourceNameToURL(NativeImageResourceUtils.RESOURCE_FILE_IN_JAR_WITH_SPACE, true);
40+
Assert.assertNotNull("URL is null!", url);
41+
Path path = NativeImageResourceUtils.resourceNameToPath(NativeImageResourceUtils.RESOURCE_FILE_IN_JAR_WITH_SPACE, true);
42+
Assert.assertNotNull("Path is null!", path);
43+
}
44+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.oracle.svm.with.space.test;
27+
28+
import java.net.URI;
29+
import java.net.URISyntaxException;
30+
import java.net.URL;
31+
import java.nio.file.Path;
32+
import java.nio.file.Paths;
33+
34+
import org.graalvm.nativeimage.hosted.Feature;
35+
import org.graalvm.nativeimage.hosted.RuntimeResourceAccess;
36+
import org.junit.Assert;
37+
38+
public class NativeImageResourceUtils {
39+
40+
public static final String ROOT_DIRECTORY = "/";
41+
public static final String RESOURCE_DIR = "/resources";
42+
public static final String RESOURCE_FILE_IN_JAR_WITH_SPACE = RESOURCE_DIR + "/resource-in-jar-with-space.txt";
43+
44+
// Register resources.
45+
public static final class TestFeature implements Feature {
46+
@Override
47+
public void beforeAnalysis(BeforeAnalysisAccess access) {
48+
// Remove leading / for the resource patterns
49+
Module resourceModule = TestFeature.class.getModule();
50+
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR.substring(1));
51+
RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_IN_JAR_WITH_SPACE.substring(1));
52+
}
53+
}
54+
55+
public static URL resourceNameToURL(String resourceName, boolean failIfNotExists) {
56+
URL resource = NativeImageResourceUtils.class.getResource(resourceName);
57+
Assert.assertFalse("Resource " + resourceName + " is not found!", resource == null && failIfNotExists);
58+
return resource;
59+
}
60+
61+
public static URI resourceNameToURI(String resourceName, boolean failIfNotExists) {
62+
try {
63+
URL url = resourceNameToURL(resourceName, failIfNotExists);
64+
return url != null ? url.toURI() : null;
65+
} catch (URISyntaxException e) {
66+
Assert.fail("Bad URI syntax!");
67+
}
68+
return null;
69+
}
70+
71+
public static Path resourceNameToPath(String resourceName, boolean failIfNotExists) {
72+
URI uri = resourceNameToURI(resourceName, failIfNotExists);
73+
return uri != null ? Paths.get(uri) : null;
74+
}
75+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
I am in a jar with spaces in its name!

0 commit comments

Comments
 (0)