Skip to content

Commit

Permalink
improvements for resolving java home (#1465)
Browse files Browse the repository at this point in the history
* don't use `--setup` flag

* allow for java version >= than the chosen one

* add additional logging to resolving java

* mkdir if doesn't exist

* simply run ${javaHome}/bin/java

* add `-version` to java coursier command

* check if file exists before getting its info

* wrap "java -version" in a try clause
  • Loading branch information
kasiaMarek authored Feb 28, 2024
1 parent 8ea1330 commit e53717d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 22 deletions.
47 changes: 29 additions & 18 deletions packages/metals-languageclient/src/getJavaHome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { toPromise } from "./util";
import fs from "fs";
import path from "path";
import { spawn } from "promisify-child-process";
import { OutputChannel } from "./interfaces/OutputChannel";

export type JavaVersion = "11" | "17" | "21";

Expand All @@ -26,44 +27,54 @@ export type JavaVersion = "11" | "17" | "21";
* @param javaVersion metals.javaVersion value as read from the configuration or default
*/
export async function getJavaHome(
javaVersion: JavaVersion
javaVersion: JavaVersion,
outputChannel: OutputChannel
): Promise<string | undefined> {
const fromEnvValue = await fromEnv(javaVersion);
const fromEnvValue = await fromEnv(javaVersion, outputChannel);
return fromEnvValue ? fromEnvValue : await locate(javaVersion);
}

const versionRegex = /\d+\.\d+\.\d+/;
async function validateJavaVersion(
javaHome: string,
javaVersion: JavaVersion
javaVersion: JavaVersion,
outputChannel: OutputChannel
): Promise<boolean> {
const javaBins = [
path.join(javaHome, "bin", "java"),
path.join(javaHome, "bin", "java.exe"),
path.join(javaHome, "bin", "jre", "java"),
path.join(javaHome, "bin", "jre", "java.exe"),
].filter(fs.existsSync);

if (javaBins.length != 0) {
const javaBin = javaBins[0];
const javaVersionOut = await spawn(javaBin, ["-version"], {
const javaBin = path.join(javaHome, "bin", "java");
try {
const javaVersionOut = spawn(javaBin, ["-version"], {
encoding: "utf8",
});
const javaInfoStr = javaVersionOut.stderr as string;

javaVersionOut.stderr?.on("data", (out: Buffer) => {
outputChannel.appendLine(`${javaBin} -version:`);
const msg = out.toString().trim();
outputChannel.appendLine(msg);
});

const javaInfoStr = (await javaVersionOut).stderr as string;
const matches = javaInfoStr.match(versionRegex);
if (matches) {
return matches[0].slice(0, 2) == javaVersion;
return +matches[0].slice(0, 2) >= +javaVersion;
}
} catch (error) {
outputChannel.appendLine(`failed while running ${javaBin} -version`);
outputChannel.appendLine(`${error}`);
}
return false;
}

export async function fromEnv(
javaVersion: JavaVersion
javaVersion: JavaVersion,
outputChannel: OutputChannel
): Promise<string | undefined> {
const javaHome = process.env["JAVA_HOME"];
if (javaHome) {
const isValid = await validateJavaVersion(javaHome, javaVersion);
const isValid = await validateJavaVersion(
javaHome,
javaVersion,
outputChannel
);
if (isValid) return javaHome;
}

Expand All @@ -73,7 +84,7 @@ export async function fromEnv(
function locate(javaVersion: JavaVersion): Promise<undefined | string> {
return toPromise(
pipe(
locateJavaHome({ version: `~${javaVersion}` }),
locateJavaHome({ version: `>=${javaVersion}` }),
chain((javaHomes) => {
if (!javaHomes || javaHomes.length === 0) {
return TE.right(undefined);
Expand Down
10 changes: 7 additions & 3 deletions packages/metals-languageclient/src/setupCoursier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export async function setupCoursier(
const resolveJavaHomeWithCoursier = async (coursier: string) => {
await run(
coursier,
["java", "--jvm", javaVersion, "--setup"],
["java", "--jvm", javaVersion, "-version"],
handleOutput
);

Expand All @@ -71,7 +71,7 @@ export async function setupCoursier(
const coursier = await resolveCoursier();
output.appendLine(`Using coursier located at ${coursier}`);

var javaHome = await getJavaHome(javaVersion);
var javaHome = await getJavaHome(javaVersion, output);

if (!javaHome) {
output.appendLine(
Expand Down Expand Up @@ -100,7 +100,11 @@ export async function validateCoursier(
};

const validateDefault = async () => {
if (defaultCoursier && fs.statSync(defaultCoursier).isFile()) {
if (
defaultCoursier &&
fs.existsSync(defaultCoursier) &&
fs.statSync(defaultCoursier).isFile()
) {
return validate(defaultCoursier);
} else {
return undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/metals-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ async function fetchAndLaunchMetals(
const metalsDirPath = metalsDir(ConfigurationTarget.Global);

if (!fs.existsSync(metalsDirPath)) {
fs.existsSync(metalsDirPath);
fs.mkdirSync(metalsDirPath);
}

const { coursier, javaHome } = await metalsLanguageClient.setupCoursier(
Expand Down

0 comments on commit e53717d

Please sign in to comment.