From b90c7e5c22570aa740be17e677a50871951562f6 Mon Sep 17 00:00:00 2001 From: Max Rydahl Andersen Date: Sat, 3 Aug 2024 11:38:00 +0200 Subject: [PATCH 1/4] feat: liunxdistro jdk provider adds `linuxdistro` provider which for now searches `/usr/lib/jvm` for jdks. It is not enabled by default as it is not possible to safely determine the version and build of the jdk present or needed to be installed if mising. Meaning to get it user need to select it `--jdk-provider=linuxdistro` or just enable all providers `--jdk-provider=all` on command line or run `jbang config set jdk-provider linuxdistro` to make it default for all jbang invocations. --- src/main/java/dev/jbang/net/JdkManager.java | 13 +++--- src/main/java/dev/jbang/net/JdkProvider.java | 2 + .../jdkproviders/LinuxDistroJdkProvider.java | 40 +++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java diff --git a/src/main/java/dev/jbang/net/JdkManager.java b/src/main/java/dev/jbang/net/JdkManager.java index 0102888b5..02342b547 100644 --- a/src/main/java/dev/jbang/net/JdkManager.java +++ b/src/main/java/dev/jbang/net/JdkManager.java @@ -21,13 +21,7 @@ import dev.jbang.Settings; import dev.jbang.cli.ExitException; -import dev.jbang.net.jdkproviders.CurrentJdkProvider; -import dev.jbang.net.jdkproviders.DefaultJdkProvider; -import dev.jbang.net.jdkproviders.JBangJdkProvider; -import dev.jbang.net.jdkproviders.JavaHomeJdkProvider; -import dev.jbang.net.jdkproviders.PathJdkProvider; -import dev.jbang.net.jdkproviders.ScoopJdkProvider; -import dev.jbang.net.jdkproviders.SdkmanJdkProvider; +import dev.jbang.net.jdkproviders.*; import dev.jbang.util.JavaUtil; import dev.jbang.util.Util; @@ -36,7 +30,7 @@ public class JdkManager { // TODO Don't hard-code this list public static final String[] PROVIDERS_ALL = new String[] { "current", "default", "javahome", "path", "jbang", - "sdkman", "scoop" }; + "sdkman", "scoop", "linuxdistro" }; public static final String[] PROVIDERS_DEFAULT = new String[] { "current", "default", "javahome", "path", "jbang" }; public static void initProvidersByName(String... providerNames) { @@ -74,6 +68,9 @@ public static void initProvidersByName(List providerNames) { case "scoop": provider = new ScoopJdkProvider(); break; + case "linuxdistro": + provider = new LinuxDistroJdkProvider(); + break; default: Util.warnMsg("Unknown JDK provider: " + name); continue; diff --git a/src/main/java/dev/jbang/net/JdkProvider.java b/src/main/java/dev/jbang/net/JdkProvider.java index 80c57eb5d..79140c1f9 100644 --- a/src/main/java/dev/jbang/net/JdkProvider.java +++ b/src/main/java/dev/jbang/net/JdkProvider.java @@ -121,6 +121,8 @@ default Jdk createJdk(@Nonnull String id, @Nullable Path home, @Nonnull String v default String name() { String nm = getClass().getSimpleName(); + // TODO: this 11 is here assuming it ends in "JdkProvider" - dont make that + // broken assumption return nm.substring(0, nm.length() - 11).toLowerCase(); } diff --git a/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java b/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java new file mode 100644 index 000000000..51a0093e1 --- /dev/null +++ b/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java @@ -0,0 +1,40 @@ +package dev.jbang.net.jdkproviders; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This JDK provider is intended to detects JDKs that have been installed in + * standard location of the users linux distro. + * + * For now just using `/usr/lib/jvm` as apparently fedora, debian, ubuntu and + * centos/rhel use it. + * + * If need different behavior per linux distro its intended this provider will + * adjust based on identified distro. + * + */ +public class LinuxDistroJdkProvider extends BaseFoldersJdkProvider { + private static final Path JDKS_ROOT = Paths.get("/usr/lib/jvm"); + + @Nonnull + @Override + protected Path getJdksRoot() { + return JDKS_ROOT; + } + + @Nullable + @Override + protected String jdkId(String name) { + return name + "-nixdistro"; + } + + @Override + public boolean canUse() { + return Files.isDirectory(JDKS_ROOT); + } +} From a2697359535f0a811bc9f75e7d6bf12b0b9b0211 Mon Sep 17 00:00:00 2001 From: Max Rydahl Andersen Date: Tue, 6 Aug 2024 23:38:26 +0200 Subject: [PATCH 2/4] fix: check before assuning name is jdkprovider --- src/main/java/dev/jbang/net/JdkProvider.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/jbang/net/JdkProvider.java b/src/main/java/dev/jbang/net/JdkProvider.java index 79140c1f9..9a2e00715 100644 --- a/src/main/java/dev/jbang/net/JdkProvider.java +++ b/src/main/java/dev/jbang/net/JdkProvider.java @@ -121,9 +121,11 @@ default Jdk createJdk(@Nonnull String id, @Nullable Path home, @Nonnull String v default String name() { String nm = getClass().getSimpleName(); - // TODO: this 11 is here assuming it ends in "JdkProvider" - dont make that - // broken assumption - return nm.substring(0, nm.length() - 11).toLowerCase(); + if (nm.endsWith("JdkProvider")) { + return nm.substring(0, nm.length() - 11).toLowerCase(); + } else { + return nm.toLowerCase(); + } } /** From f2f82b37a2abe07e3e070be3546848e4c18a1df0 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Wed, 28 Aug 2024 21:16:16 +0200 Subject: [PATCH 3/4] fix: make sure linux distro JDKs are valid --- .../jdkproviders/BaseFoldersJdkProvider.java | 10 +++++++--- .../jdkproviders/LinuxDistroJdkProvider.java | 19 +++++++++++++++++++ src/test/java/dev/jbang/cli/TestJdk.java | 6 ++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/jbang/net/jdkproviders/BaseFoldersJdkProvider.java b/src/main/java/dev/jbang/net/jdkproviders/BaseFoldersJdkProvider.java index d680e352b..9426a14f0 100644 --- a/src/main/java/dev/jbang/net/jdkproviders/BaseFoldersJdkProvider.java +++ b/src/main/java/dev/jbang/net/jdkproviders/BaseFoldersJdkProvider.java @@ -87,7 +87,7 @@ protected Path getJdkPath(@Nonnull String jdk) { return getJdksRoot().resolve(jdk); } - private Predicate sameJdk(Path jdkRoot) { + protected Predicate sameJdk(Path jdkRoot) { Path release = jdkRoot.resolve("release"); return (Path p) -> { try { @@ -100,7 +100,7 @@ private Predicate sameJdk(Path jdkRoot) { protected Stream listJdkPaths() throws IOException { if (Files.isDirectory(getJdksRoot())) { - return Files.list(getJdksRoot()); + return Files.list(getJdksRoot()).filter(this::acceptFolder); } return Stream.empty(); } @@ -114,12 +114,16 @@ protected Path getJdksRoot() { protected Jdk createJdk(Path home) { String name = home.getFileName().toString(); Optional version = JavaUtil.resolveJavaVersionStringFromPath(home); - if (version.isPresent()) { + if (version.isPresent() && acceptFolder(home)) { return createJdk(jdkId(name), home, version.get()); } return null; } + protected boolean acceptFolder(Path jdkFolder) { + return Util.searchPath("javac", jdkFolder.resolve("bin").toString()) != null; + } + protected boolean isValidId(String id) { return id.endsWith("-" + name()); } diff --git a/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java b/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java index 51a0093e1..e8f6c448d 100644 --- a/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java +++ b/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java @@ -1,5 +1,6 @@ package dev.jbang.net.jdkproviders; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -37,4 +38,22 @@ protected String jdkId(String name) { public boolean canUse() { return Files.isDirectory(JDKS_ROOT); } + + @Override + protected boolean acceptFolder(Path jdkFolder) { + return super.acceptFolder(jdkFolder) && !isSameFolderSymLink(jdkFolder); + } + + // Returns true if a path is a symlink to an entry in the same folder + private boolean isSameFolderSymLink(Path jdkFolder) { + Path absFolder = jdkFolder.toAbsolutePath(); + if (Files.isSymbolicLink(absFolder)) { + try { + Path realPath = absFolder.toRealPath(); + return Files.isSameFile(absFolder.getParent(), realPath.getParent()); + } catch (IOException e) { + /* ignore */ } + } + return false; + } } diff --git a/src/test/java/dev/jbang/cli/TestJdk.java b/src/test/java/dev/jbang/cli/TestJdk.java index b2efc58df..0d11ed857 100644 --- a/src/test/java/dev/jbang/cli/TestJdk.java +++ b/src/test/java/dev/jbang/cli/TestJdk.java @@ -451,9 +451,15 @@ private void initMockJdkDir(Path jdkPath, String version) { private void initMockJdkDir(Path jdkPath, String version, String key) { Util.mkdirs(jdkPath); + Path jdkBinPath = jdkPath.resolve("bin"); + Util.mkdirs(jdkBinPath); String rawJavaVersion = key + "=\"" + version + "\""; Path release = jdkPath.resolve("release"); try { + Path javacPath = jdkBinPath.resolve("javac"); + Util.writeString(javacPath, "dummy"); + javacPath.toFile().setExecutable(true, true); + Util.writeString(jdkBinPath.resolve("javac.exe"), "dummy"); Util.writeString(release, rawJavaVersion); } catch (IOException e) { throw new RuntimeException(e); From fd263c8adc816e7a15b8ed0dc0739d459d16c2f6 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Thu, 29 Aug 2024 13:07:09 +0200 Subject: [PATCH 4/4] chore: simplified LinuxDistroJdkProvider name and id --- src/main/java/dev/jbang/net/JdkManager.java | 6 +++--- .../{LinuxDistroJdkProvider.java => LinuxJdkProvider.java} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/main/java/dev/jbang/net/jdkproviders/{LinuxDistroJdkProvider.java => LinuxJdkProvider.java} (93%) diff --git a/src/main/java/dev/jbang/net/JdkManager.java b/src/main/java/dev/jbang/net/JdkManager.java index 02342b547..e5279cefa 100644 --- a/src/main/java/dev/jbang/net/JdkManager.java +++ b/src/main/java/dev/jbang/net/JdkManager.java @@ -30,7 +30,7 @@ public class JdkManager { // TODO Don't hard-code this list public static final String[] PROVIDERS_ALL = new String[] { "current", "default", "javahome", "path", "jbang", - "sdkman", "scoop", "linuxdistro" }; + "sdkman", "scoop", "linux" }; public static final String[] PROVIDERS_DEFAULT = new String[] { "current", "default", "javahome", "path", "jbang" }; public static void initProvidersByName(String... providerNames) { @@ -68,8 +68,8 @@ public static void initProvidersByName(List providerNames) { case "scoop": provider = new ScoopJdkProvider(); break; - case "linuxdistro": - provider = new LinuxDistroJdkProvider(); + case "linux": + provider = new LinuxJdkProvider(); break; default: Util.warnMsg("Unknown JDK provider: " + name); diff --git a/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java b/src/main/java/dev/jbang/net/jdkproviders/LinuxJdkProvider.java similarity index 93% rename from src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java rename to src/main/java/dev/jbang/net/jdkproviders/LinuxJdkProvider.java index e8f6c448d..c8dd49b84 100644 --- a/src/main/java/dev/jbang/net/jdkproviders/LinuxDistroJdkProvider.java +++ b/src/main/java/dev/jbang/net/jdkproviders/LinuxJdkProvider.java @@ -19,7 +19,7 @@ * adjust based on identified distro. * */ -public class LinuxDistroJdkProvider extends BaseFoldersJdkProvider { +public class LinuxJdkProvider extends BaseFoldersJdkProvider { private static final Path JDKS_ROOT = Paths.get("/usr/lib/jvm"); @Nonnull @@ -31,7 +31,7 @@ protected Path getJdksRoot() { @Nullable @Override protected String jdkId(String name) { - return name + "-nixdistro"; + return name + "-linux"; } @Override