Skip to content

Commit

Permalink
refactor: allow JDKs to be filtered for the commands they support
Browse files Browse the repository at this point in the history
This can be used to determine which JDKs are actually JREs and which
ones are full JDKs.
  • Loading branch information
quintesse committed Feb 14, 2023
1 parent 6a7e52b commit d32a2f5
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/java/dev/jbang/cli/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ public static boolean needsSetup() {
*/
public static boolean guessWithJava() {
boolean withJava;
JdkProvider.Jdk defJdk = JdkManager.getJdk(null, false);
JdkProvider.Jdk defJdk = JdkManager.getJdk(null, "javac", false);
String javaHome = System.getenv("JAVA_HOME");
Path javacCmd = Util.searchPath("javac");
withJava = defJdk != null
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/jbang/cli/Info.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public ScriptInfo(Project prj, BuildContext ctx) {
requestedJavaVersion = prj.getJavaVersion();

try {
JdkProvider.Jdk jdk = JdkManager.getJdk(requestedJavaVersion, false);
JdkProvider.Jdk jdk = JdkManager.getJdk(requestedJavaVersion, null, false);
if (jdk != null && jdk.isInstalled()) {
availableJdkPath = jdk.getHome().toString();
}
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/dev/jbang/cli/Jdk.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ public Integer install(
@CommandLine.Parameters(paramLabel = "existingJdkPath", index = "1", description = "Pre installed JDK path", arity = "0..1") String path)
throws IOException {
jdkProvidersMixin.initJdkProviders();
JdkProvider.Jdk jdk = JdkManager.getInstalledJdk(versionOrId, true);
JdkProvider.Jdk jdk = JdkManager.getInstalledJdk(versionOrId, "javac", true);
if (force || jdk == null) {
if (!Util.isNullOrBlankString(path)) {
JdkManager.linkToExistingJdk(path, Integer.parseInt(versionOrId));
} else {
if (jdk == null) {
jdk = JdkManager.getJdk(versionOrId, true);
jdk = JdkManager.getJdk(versionOrId, null, true);
}
jdk.install();
}
Expand Down Expand Up @@ -157,7 +157,7 @@ public int compareTo(JdkOut o) {
public Integer uninstall(
@CommandLine.Parameters(paramLabel = "version", index = "0", description = "The version to install", arity = "1") String versionOrId) {
jdkProvidersMixin.initJdkProviders();
JdkProvider.Jdk jdk = JdkManager.getInstalledJdk(versionOrId, true);
JdkProvider.Jdk jdk = JdkManager.getInstalledJdk(versionOrId, null, true);
if (jdk == null) {
throw new ExitException(EXIT_INVALID_INPUT, "JDK " + versionOrId + " is not installed");
}
Expand Down Expand Up @@ -222,7 +222,7 @@ public Integer javaEnv(
}

private Path getJdkPath(String versionOrId) {
JdkProvider.Jdk jdk = JdkManager.getOrInstallJdk(versionOrId);
JdkProvider.Jdk jdk = JdkManager.getOrInstallJdk(versionOrId, null);
return jdk.getHome();
}

Expand All @@ -232,7 +232,7 @@ public Integer defaultJdk(
jdkProvidersMixin.initJdkProviders();
JdkProvider.Jdk defjdk = JdkManager.getDefaultJdk();
if (versionOrId != null) {
JdkProvider.Jdk jdk = JdkManager.getOrInstallJdk(versionOrId);
JdkProvider.Jdk jdk = JdkManager.getOrInstallJdk(versionOrId, "javac");
if (!jdk.equals(defjdk)) {
JdkManager.setDefaultJdk(jdk);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/jbang/dependencies/ModularClassPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public List<String> getAutoDectectedModuleArguments(String requestedVersion) {
}

protected boolean supportsModules(String requestedVersion) {
return JavaUtil.javaVersion(requestedVersion) >= 9;
return JavaUtil.javaVersion(requestedVersion, "javac") >= 9;
}

public List<ArtifactInfo> getArtifacts() {
Expand Down
80 changes: 57 additions & 23 deletions src/main/java/dev/jbang/net/JdkManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,23 @@ private static List<JdkProvider> updatableProviders() {
* necessary.
*
* @param versionOrId A version pattern, id or <code>null</code>
* @param command The name of a command that must be available in the JDK to
* be considered as a valid result. Can be <code>null</code>
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all or if one failed to
* install
*/
@Nonnull
public static JdkProvider.Jdk getOrInstallJdk(String versionOrId) {
public static JdkProvider.Jdk getOrInstallJdk(@Nullable String versionOrId, @Nullable String command) {
if (versionOrId != null) {
if (JavaUtil.isRequestedVersion(versionOrId)) {
return getOrInstallJdkByVersion(JavaUtil.minRequestedVersion(versionOrId),
JavaUtil.isOpenVersion(versionOrId), false);
JavaUtil.isOpenVersion(versionOrId), command, false);
} else {
return getOrInstallJdkById(versionOrId, false);
return getOrInstallJdkById(versionOrId, command, false);
}
} else {
return getOrInstallJdkByVersion(0, true, false);
return getOrInstallJdkByVersion(0, true, command, false);
}
}

Expand All @@ -141,16 +143,19 @@ public static JdkProvider.Jdk getOrInstallJdk(String versionOrId) {
*
* @param requestedVersion The (minimal) version to return, can be 0
* @param openVersion Return newer version if exact is not available
* @param command The name of a command that must be available in the
* JDK to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all or if one failed to
* install
*/
@Nonnull
private static JdkProvider.Jdk getOrInstallJdkByVersion(int requestedVersion, boolean openVersion,
boolean updatableOnly) {
@Nullable String command, boolean updatableOnly) {
Util.verboseMsg("Looking for JDK: " + requestedVersion);
JdkProvider.Jdk jdk = getJdkByVersion(requestedVersion, openVersion, updatableOnly);
JdkProvider.Jdk jdk = getJdkByVersion(requestedVersion, openVersion, command, updatableOnly);
if (jdk == null) {
if (requestedVersion > 0) {
throw new ExitException(EXIT_UNEXPECTED_STATE,
Expand All @@ -172,15 +177,19 @@ private static JdkProvider.Jdk getOrInstallJdkByVersion(int requestedVersion, bo
* if necessary.
*
* @param requestedId The id of the JDK to return
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all or if one failed to
* install
*/
@Nonnull
private static JdkProvider.Jdk getOrInstallJdkById(@Nonnull String requestedId, boolean updatableOnly) {
private static JdkProvider.Jdk getOrInstallJdkById(@Nonnull String requestedId, @Nullable String command,
boolean updatableOnly) {
Util.verboseMsg("Looking for JDK: " + requestedId);
JdkProvider.Jdk jdk = getJdkById(requestedId, updatableOnly);
JdkProvider.Jdk jdk = getJdkById(requestedId, command, updatableOnly);
if (jdk == null) {
throw new ExitException(EXIT_UNEXPECTED_STATE,
"No suitable JDK was found for requested id: " + requestedId);
Expand Down Expand Up @@ -217,21 +226,25 @@ private static JdkProvider.Jdk ensureInstalled(JdkProvider.Jdk jdk) {
* performed. See <code>getOrInstallJdk()</code> for that.
*
* @param versionOrId A version pattern, id or <code>null</code>
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all
*/
@Nullable
public static JdkProvider.Jdk getJdk(@Nullable String versionOrId, boolean updatableOnly) {
public static JdkProvider.Jdk getJdk(@Nullable String versionOrId, @Nullable String command,
boolean updatableOnly) {
if (versionOrId != null) {
if (JavaUtil.isRequestedVersion(versionOrId)) {
return getJdkByVersion(JavaUtil.minRequestedVersion(versionOrId), JavaUtil.isOpenVersion(versionOrId),
updatableOnly);
command, updatableOnly);
} else {
return getJdkById(versionOrId, updatableOnly);
return getJdkById(versionOrId, command, updatableOnly);
}
} else {
return getJdkByVersion(0, true, updatableOnly);
return getJdkByVersion(0, true, command, updatableOnly);
}
}

Expand All @@ -245,18 +258,22 @@ public static JdkProvider.Jdk getJdk(@Nullable String versionOrId, boolean updat
*
* @param requestedVersion The (minimal) version to return, can be 0
* @param openVersion Return newer version if exact is not available
* @param command The name of a command that must be available in the
* JDK to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all
*/
@Nullable
private static JdkProvider.Jdk getJdkByVersion(int requestedVersion, boolean openVersion, boolean updatableOnly) {
JdkProvider.Jdk jdk = getInstalledJdkByVersion(requestedVersion, openVersion, updatableOnly);
private static JdkProvider.Jdk getJdkByVersion(int requestedVersion, boolean openVersion, @Nullable String command,
boolean updatableOnly) {
JdkProvider.Jdk jdk = getInstalledJdkByVersion(requestedVersion, openVersion, command, updatableOnly);
if (jdk == null) {
if (requestedVersion > 0 && (requestedVersion >= Settings.getDefaultJavaVersion() || !openVersion)) {
jdk = getAvailableJdkByVersion(requestedVersion, false);
} else {
jdk = getJdkByVersion(Settings.getDefaultJavaVersion(), true, updatableOnly);
jdk = getJdkByVersion(Settings.getDefaultJavaVersion(), true, command, updatableOnly);
}
}
return jdk;
Expand All @@ -271,13 +288,17 @@ private static JdkProvider.Jdk getJdkByVersion(int requestedVersion, boolean ope
* to be performed. See <code>getOrInstallJdkByVersion()</code> for that.
*
* @param requestedId The id of the JDK to return
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
* @throws ExitException If no JDK could be found at all
*/
@Nullable
private static JdkProvider.Jdk getJdkById(@Nonnull String requestedId, boolean updatableOnly) {
JdkProvider.Jdk jdk = getInstalledJdkById(requestedId, updatableOnly);
private static JdkProvider.Jdk getJdkById(@Nonnull String requestedId, @Nullable String command,
boolean updatableOnly) {
JdkProvider.Jdk jdk = getInstalledJdkById(requestedId, command, updatableOnly);
if (jdk == null) {
jdk = getAvailableJdkById(requestedId);
}
Expand All @@ -290,20 +311,23 @@ private static JdkProvider.Jdk getJdkById(@Nonnull String requestedId, boolean u
* currently installed.
*
* @param versionOrId A version pattern, id or <code>null</code>
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
*/
@Nullable
public static JdkProvider.Jdk getInstalledJdk(String versionOrId, boolean updatableOnly) {
public static JdkProvider.Jdk getInstalledJdk(String versionOrId, @Nullable String command, boolean updatableOnly) {
if (versionOrId != null) {
if (JavaUtil.isRequestedVersion(versionOrId)) {
return getInstalledJdkByVersion(JavaUtil.minRequestedVersion(versionOrId),
JavaUtil.isOpenVersion(versionOrId), updatableOnly);
JavaUtil.isOpenVersion(versionOrId), command, updatableOnly);
} else {
return getInstalledJdkById(versionOrId, updatableOnly);
return getInstalledJdkById(versionOrId, command, updatableOnly);
}
} else {
return getInstalledJdkByVersion(0, true, updatableOnly);
return getInstalledJdkByVersion(0, true, command, updatableOnly);
}
}

Expand All @@ -314,15 +338,20 @@ public static JdkProvider.Jdk getInstalledJdk(String versionOrId, boolean updata
*
* @param version The (major) version of the JDK to return
* @param openVersion Return newer version if exact is not available
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
*/
@Nullable
private static JdkProvider.Jdk getInstalledJdkByVersion(int version, boolean openVersion, boolean updatableOnly) {
private static JdkProvider.Jdk getInstalledJdkByVersion(int version, boolean openVersion, @Nullable String command,
boolean updatableOnly) {
return providers() .stream()
.filter(p -> !updatableOnly || p.canUpdate())
.map(p -> p.getJdkByVersion(version, openVersion))
.filter(Objects::nonNull)
.filter(jdk -> command == null || jdk.hasCommand(command))
.findFirst()
.orElse(null);
}
Expand All @@ -332,15 +361,20 @@ private static JdkProvider.Jdk getInstalledJdkByVersion(int version, boolean ope
* Will return <code>null</code> if no JDK with that id is currently installed.
*
* @param requestedId The id of the JDK to return
* @param command The name of a command that must be available in the JDK
* to be considered as a valid result. Can be
* <code>null</code>
* @param updatableOnly Only return JDKs from updatable providers or not
* @return A <code>Jdk</code> object or <code>null</code>
*/
@Nullable
private static JdkProvider.Jdk getInstalledJdkById(String requestedId, boolean updatableOnly) {
private static JdkProvider.Jdk getInstalledJdkById(String requestedId, @Nullable String command,
boolean updatableOnly) {
return providers() .stream()
.filter(p -> !updatableOnly || p.canUpdate())
.map(p -> p.getJdkById(requestedId))
.filter(Objects::nonNull)
.filter(jdk -> command == null || jdk.hasCommand(command))
.findFirst()
.orElse(null);
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/dev/jbang/net/JdkProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import javax.annotation.Nullable;

import dev.jbang.util.JavaUtil;
import dev.jbang.util.Util;

/**
* This interface must be implemented by providers that are able to give access
Expand Down Expand Up @@ -89,6 +90,10 @@ public boolean isInstalled() {
return home != null;
}

public boolean hasCommand(String command) {
return home != null && Util.searchPath(command, home.resolve("bin").toString()) != null;
}

@Override
public boolean equals(Object o) {
if (this == o)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public Jdk install(@Nonnull String jdk) {
}
}
String msg = "Required Java version not possible to download or install.";
Jdk defjdk = JdkManager.getJdk(null, false);
Jdk defjdk = JdkManager.getJdk(null, null, false);
if (defjdk != null) {
msg += " You can run with '--java " + defjdk.getMajorVersion()
+ "' to force using the default installed Java.";
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/jbang/source/AppBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Project build() throws IOException {
// We already have a Jar, check if we can still use it
if (!ctx.isUpToDate()) {
Util.verboseMsg("Building as previous build jar found but it or its dependencies not up-to-date.");
} else if (JavaUtil.javaVersion(requestedJavaVersion) < JavaUtil.minRequestedVersion(
} else if (JavaUtil.javaVersion(requestedJavaVersion, "java") < JavaUtil.minRequestedVersion(
jarProject.getJavaVersion())) {
Util.verboseMsg(
String.format(
Expand Down
7 changes: 1 addition & 6 deletions src/main/java/dev/jbang/source/buildsteps/JarBuildStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,7 @@ public static void createJar(Project prj, Path compileDir, Path jarFile) throws
// options set on the Source)
List<String> rtArgs = prj.getRuntimeOptions();
String runtimeOpts = CommandBuffer.of(rtArgs).asCommandLine(Util.Shell.bash);
// TODO should be removed
// if (!runtimeOpts.isEmpty()) {
// manifest.getMainAttributes()
// .putValue(ATTR_JBANG_JAVA_OPTIONS, runtimeOpts);
// }
int buildJdk = JavaUtil.javaVersion(prj.getJavaVersion());
int buildJdk = JavaUtil.javaVersion(prj.getJavaVersion(), "javac");
if (buildJdk > 0) {
String val = buildJdk >= 9 ? Integer.toString(buildJdk) : "1." + buildJdk;
manifest.getMainAttributes().putValue(ATTR_BUILD_JDK, val);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ protected String generateCommandLineString(List<String> fullArgs) throws IOExcep
if (args.length() > COMMAND_LINE_LENGTH_LIMIT && Util.getShell() != Util.Shell.bash) {
// @file is only available from java 9 onwards.
String requestedJavaVersion = project.getJavaVersion();
int actualVersion = JavaUtil.javaVersion(requestedJavaVersion);
int actualVersion = JavaUtil.javaVersion(requestedJavaVersion, "java");
useArgsFile = actualVersion >= 9;
}
if (useArgsFile) {
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/dev/jbang/source/sources/GroovySource.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public Builder<Project> getBuilder(Project prj, BuildContext ctx) {
}

private static class GroovyAppBuilder extends AppBuilder {
public static final String GROOVY_COMPILER = "groovyc";

public GroovyAppBuilder(Project project, BuildContext ctx) {
super(project, ctx);
}
Expand All @@ -88,15 +90,18 @@ public GroovyCompileBuildStep() {

@Override
protected String getCompilerBinary(String requestedJavaVersion) {
return resolveInGroovyHome("groovyc", ((GroovySource) project.getMainSource()).getGroovyVersion());
return resolveInGroovyHome(GROOVY_COMPILER,
((GroovySource) project.getMainSource()).getGroovyVersion());
}

@Override
protected void runCompiler(ProcessBuilder processBuilder) throws IOException {
if (project.getMainSource() instanceof GroovySource) {
processBuilder .environment()
.put("JAVA_HOME",
JdkManager.getOrInstallJdk(project.getJavaVersion()).getHome().toString());
JdkManager .getOrInstallJdk(project.getJavaVersion(), null)
.getHome()
.toString());
processBuilder.environment().remove("GROOVY_HOME");
}
super.runCompiler(processBuilder);
Expand Down
Loading

0 comments on commit d32a2f5

Please sign in to comment.