From 446dbd57c9d448dc7d0f49dcaf723521736eda0a Mon Sep 17 00:00:00 2001 From: dyrpsf Date: Mon, 22 Jun 2026 17:16:32 +0530 Subject: [PATCH 1/4] Fix #97: Allow custom native library directory via system property --- .../java/com/uber/h3core/H3CoreLoader.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/uber/h3core/H3CoreLoader.java b/src/main/java/com/uber/h3core/H3CoreLoader.java index 9533e649..83caad5c 100644 --- a/src/main/java/com/uber/h3core/H3CoreLoader.java +++ b/src/main/java/com/uber/h3core/H3CoreLoader.java @@ -94,16 +94,35 @@ public static NativeMethods loadNatives() throws IOException { } private static File createTempLibraryFile(OperatingSystem os) throws IOException { + // Check if the user specified a custom directory for native libraries + String customDir = System.getProperty("h3.native.dir"); + File dir = customDir != null ? new File(customDir) : null; + + // Ensure the custom directory exists + if (dir != null && !dir.exists()) { + dir.mkdirs(); + } + if (os.isPosix()) { // Note this is already done by the implementation of Files.createTempFile that I looked at, // but the javadoc does not seem to gaurantee the permissions will be restricted to owner // write. final FileAttribute> attr = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")); - return Files.createTempFile("libh3-java", os.getSuffix(), attr).toFile(); + + if (dir != null) { + return Files.createTempFile(dir.toPath(), "libh3-java", os.getSuffix(), attr).toFile(); + } else { + return Files.createTempFile("libh3-java", os.getSuffix(), attr).toFile(); + } } else { // When not a POSIX OS, try to ensure the permissions are secure - final File f = Files.createTempFile("libh3-java", os.getSuffix()).toFile(); + final File f; + if (dir != null) { + f = Files.createTempFile(dir.toPath(), "libh3-java", os.getSuffix()).toFile(); + } else { + f = Files.createTempFile("libh3-java", os.getSuffix()).toFile(); + } f.setReadable(true, true); f.setWritable(true, true); f.setExecutable(true, true); From 023bc51724930dacea276ffb75bbc7d9d9ee0a11 Mon Sep 17 00:00:00 2001 From: dyrpsf Date: Mon, 22 Jun 2026 21:55:21 +0530 Subject: [PATCH 2/4] style: apply spotless formatting --- src/main/java/com/uber/h3core/H3CoreLoader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/uber/h3core/H3CoreLoader.java b/src/main/java/com/uber/h3core/H3CoreLoader.java index 83caad5c..26a1561f 100644 --- a/src/main/java/com/uber/h3core/H3CoreLoader.java +++ b/src/main/java/com/uber/h3core/H3CoreLoader.java @@ -97,7 +97,7 @@ private static File createTempLibraryFile(OperatingSystem os) throws IOException // Check if the user specified a custom directory for native libraries String customDir = System.getProperty("h3.native.dir"); File dir = customDir != null ? new File(customDir) : null; - + // Ensure the custom directory exists if (dir != null && !dir.exists()) { dir.mkdirs(); @@ -109,7 +109,7 @@ private static File createTempLibraryFile(OperatingSystem os) throws IOException // write. final FileAttribute> attr = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")); - + if (dir != null) { return Files.createTempFile(dir.toPath(), "libh3-java", os.getSuffix(), attr).toFile(); } else { From c87ce50cdfe7b624430eeb42c0b8cab2edaf7c30 Mon Sep 17 00:00:00 2001 From: dyrpsf Date: Sat, 15 Aug 2026 14:28:19 +0530 Subject: [PATCH 3/4] test: add unit test for h3.native.dir extraction logic --- .../com/uber/h3core/TestH3CoreLoader.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/java/com/uber/h3core/TestH3CoreLoader.java b/src/test/java/com/uber/h3core/TestH3CoreLoader.java index 34e44458..3fe0074f 100644 --- a/src/test/java/com/uber/h3core/TestH3CoreLoader.java +++ b/src/test/java/com/uber/h3core/TestH3CoreLoader.java @@ -68,4 +68,31 @@ void extractNonexistant() throws IOException { UnsatisfiedLinkError.class, () -> H3CoreLoader.copyResource("/nonexistant-resource", tempFile)); } + + @Test + void testCustomNativeDir() throws Exception { + String customDir = System.getProperty("java.io.tmpdir") + "/h3-custom-test-dir"; + System.setProperty("h3.native.dir", customDir); + + try { + H3CoreLoader.OperatingSystem currentOs = + H3CoreLoader.detectOs(System.getProperty("java.vendor"), System.getProperty("os.name")); + + java.lang.reflect.Method method = + H3CoreLoader.class.getDeclaredMethod( + "createTempLibraryFile", H3CoreLoader.OperatingSystem.class); + method.setAccessible(true); + + File tempFile = (File) method.invoke(null, currentOs); + + org.junit.jupiter.api.Assertions.assertTrue( + tempFile.getAbsolutePath().startsWith(new File(customDir).getAbsolutePath()), + "File should be created inside the custom directory"); + + tempFile.delete(); + new File(customDir).delete(); + } finally { + System.clearProperty("h3.native.dir"); + } + } } From 0a005b3da7e11b718f02f35e4e1a44ffdc354d0a Mon Sep 17 00:00:00 2001 From: dyrpsf Date: Mon, 17 Aug 2026 10:06:02 +0530 Subject: [PATCH 4/4] refactor: make createTempLibraryFile package-private and simplify test --- src/main/java/com/uber/h3core/H3CoreLoader.java | 2 +- src/test/java/com/uber/h3core/TestH3CoreLoader.java | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/uber/h3core/H3CoreLoader.java b/src/main/java/com/uber/h3core/H3CoreLoader.java index 26a1561f..f8863c79 100644 --- a/src/main/java/com/uber/h3core/H3CoreLoader.java +++ b/src/main/java/com/uber/h3core/H3CoreLoader.java @@ -93,7 +93,7 @@ public static NativeMethods loadNatives() throws IOException { return loadNatives(os, arch); } - private static File createTempLibraryFile(OperatingSystem os) throws IOException { + static File createTempLibraryFile(OperatingSystem os) throws IOException { // Check if the user specified a custom directory for native libraries String customDir = System.getProperty("h3.native.dir"); File dir = customDir != null ? new File(customDir) : null; diff --git a/src/test/java/com/uber/h3core/TestH3CoreLoader.java b/src/test/java/com/uber/h3core/TestH3CoreLoader.java index 3fe0074f..3864a57f 100644 --- a/src/test/java/com/uber/h3core/TestH3CoreLoader.java +++ b/src/test/java/com/uber/h3core/TestH3CoreLoader.java @@ -78,12 +78,8 @@ void testCustomNativeDir() throws Exception { H3CoreLoader.OperatingSystem currentOs = H3CoreLoader.detectOs(System.getProperty("java.vendor"), System.getProperty("os.name")); - java.lang.reflect.Method method = - H3CoreLoader.class.getDeclaredMethod( - "createTempLibraryFile", H3CoreLoader.OperatingSystem.class); - method.setAccessible(true); - - File tempFile = (File) method.invoke(null, currentOs); + // Call the package-private method directly! No reflection needed. + File tempFile = H3CoreLoader.createTempLibraryFile(currentOs); org.junit.jupiter.api.Assertions.assertTrue( tempFile.getAbsolutePath().startsWith(new File(customDir).getAbsolutePath()),