diff --git a/src/main/java/dev/jbang/devkitman/jdkproviders/BaseFoldersJdkProvider.java b/src/main/java/dev/jbang/devkitman/jdkproviders/BaseFoldersJdkProvider.java index 609c924..44f4c19 100644 --- a/src/main/java/dev/jbang/devkitman/jdkproviders/BaseFoldersJdkProvider.java +++ b/src/main/java/dev/jbang/devkitman/jdkproviders/BaseFoldersJdkProvider.java @@ -4,6 +4,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; @@ -130,7 +131,35 @@ protected Stream listJdkPaths() throws IOException { } protected boolean acceptFolder(@NonNull Path jdkFolder) { - return jdkFolder.startsWith(jdksRoot) && JavaUtils.hasJavacCmd(jdkFolder); + return isUnderRoot(jdkFolder) && JavaUtils.hasJavacCmd(jdkFolder); + } + + /** + * Checks if the given path is under the jdksRoot directory. This method handles + * the case where the paths may have different canonical forms (e.g. /var vs + * /private/var on macOS) by falling back to toRealPath() comparison when a + * simple startsWith check fails. + */ + protected boolean isUnderRoot(@NonNull Path jdkFolder) { + if (jdkFolder.startsWith(jdksRoot)) { + return true; + } + try { + return jdkFolder.toRealPath().startsWith(realJdksRoot()); + } catch (IOException e) { + return false; + } + } + + private final AtomicReference realJdksRootCache = new AtomicReference<>(); + + private Path realJdksRoot() throws IOException { + Path cached = realJdksRootCache.get(); + if (cached == null) { + cached = jdksRoot.toRealPath(); + realJdksRootCache.set(cached); + } + return cached; } private final Pattern validId = Pattern.compile("^[a-zA-Z0-9._+-]+$"); diff --git a/src/main/java/dev/jbang/devkitman/jdkproviders/DefaultJdkProvider.java b/src/main/java/dev/jbang/devkitman/jdkproviders/DefaultJdkProvider.java index 0ab6476..104bb93 100644 --- a/src/main/java/dev/jbang/devkitman/jdkproviders/DefaultJdkProvider.java +++ b/src/main/java/dev/jbang/devkitman/jdkproviders/DefaultJdkProvider.java @@ -158,7 +158,7 @@ protected Path getJdkPath(@NonNull String id) { } protected boolean acceptFolder(@NonNull Path jdkFolder) { - if (!jdkFolder.equals(defaultJdkLink) && !jdkFolder.startsWith(jdksRoot)) { + if (!jdkFolder.equals(defaultJdkLink) && !isUnderRoot(jdkFolder)) { return false; } String nm = jdkFolder.getFileName().toString();