From 9130aa13482c820bdb868869eee22ad0cef4b289 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 13 Nov 2023 15:26:07 +0200 Subject: [PATCH 1/3] Add tests for resources with spaces in their path --- ...NativeImageResourceFileSystemProviderTest.java | 15 +++++++++++++++ .../oracle/svm/test/NativeImageResourceTest.java | 14 ++++++++++++++ .../oracle/svm/test/NativeImageResourceUtils.java | 2 ++ .../src/resources/dir with space/.mxkeep | 1 + 4 files changed, 32 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.test/src/resources/dir with space/.mxkeep 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 6e5ccc7fbe1c..f2e57f26451e 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 @@ -26,6 +26,7 @@ package com.oracle.svm.test; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR; +import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR_WITH_SPACE; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_EMPTY_DIR; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_1; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_2; @@ -231,6 +232,20 @@ public void queryEmptyDir() { } } + /** + * Query a directory with spaces in its name. + */ + @Test + public void queryDirWithSpaces() { + Path dirWithSpaces = fileSystem.getPath(RESOURCE_DIR_WITH_SPACE); + try (Stream stream = Files.walk(dirWithSpaces)) { + Assert.assertEquals(1, stream.count()); + } catch (IOException e) { + e.printStackTrace(); + Assert.fail("IOException occurred during file system walk, starting from the root."); + } + } + /** * Reading from file using {@link java.nio.channels.ByteChannel}. */ diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceTest.java index a4fe9af3cfbf..6af69f777071 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceTest.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceTest.java @@ -26,6 +26,7 @@ package com.oracle.svm.test; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR; +import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_DIR_WITH_SPACE; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_1; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_2; import static com.oracle.svm.test.NativeImageResourceUtils.RESOURCE_FILE_3; @@ -131,6 +132,19 @@ public void classGetDirectoryResource() { resourceNameToURL(nonCanonicalResourceDirectoryName, false); } + @Test + public void classGetDirectoryWithSpaceResource() { + URL url1 = resourceNameToURL(RESOURCE_DIR_WITH_SPACE + "/", true); + Assert.assertTrue("The URL should end with slash!", url1.toString().endsWith("/")); + + URL url2 = resourceNameToURL(RESOURCE_DIR_WITH_SPACE, true); + Assert.assertFalse("The URL should not end with slash!", url2.toString().endsWith("/")); + Assert.assertTrue("Two URLs must be the same!", compareTwoURLs(url1, url2)); + + String nonCanonicalResourceDirectoryName = RESOURCE_DIR_WITH_SPACE + "/./"; + resourceNameToURL(nonCanonicalResourceDirectoryName, false); + } + @Test public void registeredResourceDirectoryHasContent() throws IOException { URL directory = NativeImageResourceUtils.class.getResource(SIMPLE_RESOURCE_DIR); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceUtils.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceUtils.java index 7cd52b889c7a..ab7f692a9755 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceUtils.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/NativeImageResourceUtils.java @@ -44,6 +44,7 @@ public class NativeImageResourceUtils { public static final String RESOURCE_DIR = "/resources"; public static final String SIMPLE_RESOURCE_DIR = "/simpleDir"; public static final String RESOURCE_EMPTY_DIR = RESOURCE_DIR + "/empty"; + public static final String RESOURCE_DIR_WITH_SPACE = RESOURCE_DIR + "/dir with space"; public static final String RESOURCE_FILE_1 = RESOURCE_DIR + "/resource-test1.txt"; public static final String RESOURCE_FILE_2 = RESOURCE_DIR + "/resource-test2.txt"; public static final String RESOURCE_FILE_3 = RESOURCE_DIR + "/resource-test3.html"; @@ -58,6 +59,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR.substring(1)); RuntimeResourceAccess.addResource(resourceModule, SIMPLE_RESOURCE_DIR.substring(1)); RuntimeResourceAccess.addResource(resourceModule, RESOURCE_EMPTY_DIR.substring(1)); + RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR_WITH_SPACE.substring(1)); RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_1.substring(1)); RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_2.substring(1)); RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_3.substring(1)); diff --git a/substratevm/src/com.oracle.svm.test/src/resources/dir with space/.mxkeep b/substratevm/src/com.oracle.svm.test/src/resources/dir with space/.mxkeep new file mode 100644 index 000000000000..5c74e3c55f30 --- /dev/null +++ b/substratevm/src/com.oracle.svm.test/src/resources/dir with space/.mxkeep @@ -0,0 +1 @@ +This file instructs mx to create a jar entry for the parent directory \ No newline at end of file From 3eedd427d999f8cc4d610356c1fd914c67182393 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 13 Nov 2023 17:01:26 +0200 Subject: [PATCH 2/3] Allow resources inclusion from jar files in paths containing spaces Closes https://github.com/quarkusio/quarkus/issues/36998 --- .../src/com/oracle/svm/hosted/ResourcesFeature.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 91a98821fe92..d01ed11544cf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -281,12 +281,12 @@ private void processResourceFromModule(Module module, String resourcePath) { } } - InputStream is = module.getResourceAsStream(resourcePath); boolean isDirectory = Files.isDirectory(Path.of(resourcePath)); if (isDirectory) { String content = getDirectoryContent(resourcePath, false); Resources.singleton().registerDirectoryResource(module, resourcePath, content, false); } else { + InputStream is = module.getResourceAsStream(resourcePath); registerResource(module, resourcePath, false, is); } } catch (IOException e) { @@ -310,13 +310,13 @@ private void processResourceFromClasspath(String resourcePath) { while (urls.hasMoreElements()) { URL url = urls.nextElement(); try { - InputStream is = url.openStream(); boolean fromJar = url.getProtocol().equalsIgnoreCase("jar"); boolean isDirectory = resourceIsDirectory(url, fromJar, resourcePath); if (isDirectory) { String content = getDirectoryContent(fromJar ? url.toString() : Paths.get(url.toURI()).toString(), fromJar); Resources.singleton().registerDirectoryResource(null, resourcePath, content, fromJar); } else { + InputStream is = url.openStream(); registerResource(null, resourcePath, fromJar, is); } } catch (IOException e) { @@ -345,8 +345,8 @@ private void registerResource(Module module, String resourcePath, boolean fromJa /* Util functions for resource attributes calculations */ private String urlToJarPath(URL url) { try { - return ((JarURLConnection) url.openConnection()).getJarFileURL().getFile(); - } catch (IOException e) { + return ((JarURLConnection) url.openConnection()).getJarFileURL().toURI().getPath(); + } catch (IOException | URISyntaxException e) { throw new RuntimeException(e); } } From 2d4c7193ce3f386067954a1599c502d3c91743d4 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Thu, 16 Nov 2023 15:20:56 +0200 Subject: [PATCH 3/3] Add native unit test to test resource inclusion from path with space --- substratevm/mx.substratevm/suite.py | 33 ++++++++ .../native-image.properties | 3 + .../space/test/NativeImageResourceTest.java | 44 +++++++++++ .../space/test/NativeImageResourceUtils.java | 75 +++++++++++++++++++ .../resources/resource-in-jar-with-space.txt | 1 + 5 files changed, 156 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.with.space.test/src/META-INF/native-image/com.oracle.svm.with.space.test/native-image.properties create mode 100644 substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceTest.java create mode 100644 substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceUtils.java create mode 100644 substratevm/src/com.oracle.svm.with.space.test/src/resources/resource-in-jar-with-space.txt diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 7c9555bccb5d..c21b5ce51a94 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -946,6 +946,24 @@ "jacoco" : "exclude", }, + "com.oracle.svm.with.space.test": { + "subDir": "src", + "sourceDirs": ["src"], + "dependencies": [ + "mx:JUNIT_TOOL", + "sdk:NATIVEIMAGE", + ], + "checkstyle": "com.oracle.svm.test", + "workingSets": "SVM", + "annotationProcessors": [ + "compiler:GRAAL_PROCESSOR", + "SVM_PROCESSOR", + ], + "javaCompliance" : "21+", + "spotbugs": "false", + "jacoco" : "exclude", + }, + "com.oracle.svm.configure.test": { "subDir": "src", "sourceDirs": ["src"], @@ -1992,6 +2010,21 @@ "testDistribution" : True, }, + # Special test distribution used for testing inclusion of resources from jar files with a space in their name. + # The space in the distribution name is intentional. + "SVM_TESTS WITH SPACE" : { + "subDir": "src", + "relpath" : True, + "dependencies" : [ + "com.oracle.svm.with.space.test", + ], + "distDependencies": [ + "sdk:NATIVEIMAGE", + "mx:JUNIT_TOOL", + ], + "testDistribution" : True, + }, + "POLYGLOT_NATIVE_API" : { "subDir": "src", "dependencies": [ diff --git a/substratevm/src/com.oracle.svm.with.space.test/src/META-INF/native-image/com.oracle.svm.with.space.test/native-image.properties b/substratevm/src/com.oracle.svm.with.space.test/src/META-INF/native-image/com.oracle.svm.with.space.test/native-image.properties new file mode 100644 index 000000000000..0473d4bbef0e --- /dev/null +++ b/substratevm/src/com.oracle.svm.with.space.test/src/META-INF/native-image/com.oracle.svm.with.space.test/native-image.properties @@ -0,0 +1,3 @@ +Args= \ + --initialize-at-run-time=com.oracle.svm.with.space.test \ + --features=com.oracle.svm.with.space.test.NativeImageResourceUtils$TestFeature \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceTest.java b/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceTest.java new file mode 100644 index 000000000000..e95bb19b21bd --- /dev/null +++ b/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.with.space.test; + +import java.net.URL; +import java.nio.file.Path; + +import org.junit.Assert; +import org.junit.Test; + +public class NativeImageResourceTest { + + @Test + @SuppressWarnings("deprecation") + public void accessFileFromJarWithSpaceInName() { + URL url = NativeImageResourceUtils.resourceNameToURL(NativeImageResourceUtils.RESOURCE_FILE_IN_JAR_WITH_SPACE, true); + Assert.assertNotNull("URL is null!", url); + Path path = NativeImageResourceUtils.resourceNameToPath(NativeImageResourceUtils.RESOURCE_FILE_IN_JAR_WITH_SPACE, true); + Assert.assertNotNull("Path is null!", path); + } +} diff --git a/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceUtils.java b/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceUtils.java new file mode 100644 index 000000000000..3e5f1b3ed64f --- /dev/null +++ b/substratevm/src/com.oracle.svm.with.space.test/src/com/oracle/svm/with/space/test/NativeImageResourceUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.svm.with.space.test; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; +import org.junit.Assert; + +public class NativeImageResourceUtils { + + public static final String ROOT_DIRECTORY = "/"; + public static final String RESOURCE_DIR = "/resources"; + public static final String RESOURCE_FILE_IN_JAR_WITH_SPACE = RESOURCE_DIR + "/resource-in-jar-with-space.txt"; + + // Register resources. + public static final class TestFeature implements Feature { + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + // Remove leading / for the resource patterns + Module resourceModule = TestFeature.class.getModule(); + RuntimeResourceAccess.addResource(resourceModule, RESOURCE_DIR.substring(1)); + RuntimeResourceAccess.addResource(resourceModule, RESOURCE_FILE_IN_JAR_WITH_SPACE.substring(1)); + } + } + + public static URL resourceNameToURL(String resourceName, boolean failIfNotExists) { + URL resource = NativeImageResourceUtils.class.getResource(resourceName); + Assert.assertFalse("Resource " + resourceName + " is not found!", resource == null && failIfNotExists); + return resource; + } + + public static URI resourceNameToURI(String resourceName, boolean failIfNotExists) { + try { + URL url = resourceNameToURL(resourceName, failIfNotExists); + return url != null ? url.toURI() : null; + } catch (URISyntaxException e) { + Assert.fail("Bad URI syntax!"); + } + return null; + } + + public static Path resourceNameToPath(String resourceName, boolean failIfNotExists) { + URI uri = resourceNameToURI(resourceName, failIfNotExists); + return uri != null ? Paths.get(uri) : null; + } +} diff --git a/substratevm/src/com.oracle.svm.with.space.test/src/resources/resource-in-jar-with-space.txt b/substratevm/src/com.oracle.svm.with.space.test/src/resources/resource-in-jar-with-space.txt new file mode 100644 index 000000000000..2e8a16722306 --- /dev/null +++ b/substratevm/src/com.oracle.svm.with.space.test/src/resources/resource-in-jar-with-space.txt @@ -0,0 +1 @@ +I am in a jar with spaces in its name! \ No newline at end of file