From 8e3ea14c1af876e61aee143908136f375f769a5e Mon Sep 17 00:00:00 2001 From: linghengqian Date: Sun, 12 Nov 2023 20:13:46 +0800 Subject: [PATCH] Make JDBCRepositorySQLLoader avoid using `Path#toFile` in GraalVM Native Image --- .../jdbc/sql/JDBCRepositorySQLLoader.java | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java b/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java index 837d5974bdbb87..2d7ea1cb9a7d49 100644 --- a/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java +++ b/mode/type/standalone/repository/provider/jdbc/src/main/java/org/apache/shardingsphere/mode/repository/standalone/jdbc/sql/JDBCRepositorySQLLoader.java @@ -82,7 +82,7 @@ public static JDBCRepositorySQL load(final String type) { } /** - * Under the GraalVM Native Image corresponding to GraalVM CE 21.0.1, although there is + * Under the GraalVM Native Image corresponding to GraalVM CE 23.0.2 For JDK 17.0.9, although there is * `com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystemProvider`, the corresponding * `com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystem` does not autoload. This is mainly to align the * behavior of `ZipFileSystemProvider`, so ShardingSphere need to manually open and close the FileSystem @@ -101,15 +101,50 @@ public static JDBCRepositorySQL load(final String type) { * @see sun.nio.fs.UnixFileSystemProvider */ private static JDBCRepositorySQL loadFromDirectory(final URL url, final String type) throws URISyntaxException, IOException { - if (null != System.getProperty("org.graalvm.nativeimage.imagecode")) { - try (FileSystem ignored = FileSystems.newFileSystem(URI.create("resource:/"), Collections.singletonMap("create", "true"))) { - return loadFromDirectoryLegacy(url, type); - } - } else { + if (null == System.getProperty("org.graalvm.nativeimage.imagecode") || !"runtime".equals(System.getProperty("org.graalvm.nativeimage.imagecode"))) { return loadFromDirectoryLegacy(url, type); + } else { + try (FileSystem ignored = FileSystems.newFileSystem(URI.create("resource:/"), Collections.emptyMap())) { + return loadFromDirectoryInNativeImage(url, type); + } } } + /** + * Affected by oracle/graal#7804, ShardingSphere needs to + * avoid the use of `java.nio.file.Path#toFile` in GraalVM Native Image. + * + * @param url url + * @param type type of JDBC repository SQL + * @return loaded JDBC repository SQL + * @throws URISyntaxException Checked exception thrown to indicate that a string could not be parsed as a URI reference + * @throws IOException Signals that an I/O exception to some sort has occurred + * @see java.nio.file.Path + * @see java.io.File + */ + private static JDBCRepositorySQL loadFromDirectoryInNativeImage(final URL url, final String type) throws URISyntaxException, IOException { + final JDBCRepositorySQL[] result = new JDBCRepositorySQL[1]; + Files.walkFileTree(Paths.get(url.toURI()), new SimpleFileVisitor() { + + @SneakyThrows(JAXBException.class) + @Override + public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException { + if (file.toString().endsWith(FILE_EXTENSION)) { + JDBCRepositorySQL provider = (JDBCRepositorySQL) JAXBContext.newInstance(JDBCRepositorySQL.class).createUnmarshaller().unmarshal(Files.newInputStream(file.toAbsolutePath())); + if (provider.isDefault()) { + result[0] = provider; + } + if (Objects.equals(provider.getType(), type)) { + result[0] = provider; + return FileVisitResult.TERMINATE; + } + } + return FileVisitResult.CONTINUE; + } + }); + return result[0]; + } + private static JDBCRepositorySQL loadFromDirectoryLegacy(final URL url, final String type) throws URISyntaxException, IOException { final JDBCRepositorySQL[] result = new JDBCRepositorySQL[1]; Files.walkFileTree(Paths.get(url.toURI()), new SimpleFileVisitor() {