Skip to content

Commit 4c0df75

Browse files
Find Java version from release file (#922)
1 parent 78bd1f5 commit 4c0df75

File tree

2 files changed

+77
-26
lines changed

2 files changed

+77
-26
lines changed

src/configurationProvider.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { buildWorkspace } from "./build";
1212
import { populateStepFilters, substituteFilterVariables } from "./classFilter";
1313
import * as commands from "./commands";
1414
import * as lsPlugin from "./languageServerPlugin";
15-
import { addMoreHelpfulVMArgs, detectLaunchCommandStyle, validateRuntime } from "./launchCommand";
15+
import { addMoreHelpfulVMArgs, getJavaVersion, getShortenApproachForCLI, validateRuntimeCompatibility } from "./launchCommand";
1616
import { logger, Type } from "./logger";
1717
import { mainClassPicker } from "./mainClassPicker";
1818
import { resolveJavaProcess } from "./processPicker";
@@ -271,17 +271,18 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
271271
// Populate the class filters to the debug configuration.
272272
await populateStepFilters(config);
273273

274+
const targetJavaVersion: number = await getJavaVersion(config.javaExec);
274275
// Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag.
275276
if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) {
276277
config.vmArgs = (config.vmArgs || "") + " --enable-preview";
277-
validateRuntime(config);
278+
validateRuntimeCompatibility(targetJavaVersion);
278279
}
279280

280281
// Add more helpful vmArgs.
281-
await addMoreHelpfulVMArgs(config);
282+
await addMoreHelpfulVMArgs(config, targetJavaVersion);
282283

283284
if (!config.shortenCommandLine || config.shortenCommandLine === "auto") {
284-
config.shortenCommandLine = await detectLaunchCommandStyle(config);
285+
config.shortenCommandLine = await getShortenApproachForCLI(config, targetJavaVersion);
285286
}
286287

287288
if (process.platform === "win32" && config.console !== "internalConsole") {

src/launchCommand.ts

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33
import * as cp from "child_process";
4+
import * as fs from "fs";
45
import * as _ from "lodash";
56
import * as path from "path";
67
import * as vscode from "vscode";
@@ -17,19 +18,25 @@ enum shortenApproach {
1718

1819
const HELPFUL_NPE_VMARGS = "-XX:+ShowCodeDetailsInExceptionMessages";
1920

20-
export async function detectLaunchCommandStyle(config: vscode.DebugConfiguration): Promise<shortenApproach> {
21-
const javaExec: string = config.javaExec || path.join(await getJavaHome(), "bin", "java");
22-
const javaVersion = await checkJavaVersion(javaExec);
23-
const recommendedShortenApproach = javaVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile;
21+
/**
22+
* Returns the recommended approach to shorten the command line length.
23+
* @param config the launch configuration
24+
* @param runtimeVersion the target runtime version
25+
*/
26+
export async function getShortenApproachForCLI(config: vscode.DebugConfiguration, runtimeVersion: number): Promise<shortenApproach> {
27+
const recommendedShortenApproach = runtimeVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile;
2428
return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none;
2529
}
2630

27-
export async function validateRuntime(config: vscode.DebugConfiguration) {
31+
/**
32+
* Validates whether the specified runtime version could be supported by the Java tooling.
33+
* @param runtimeVersion the target runtime version
34+
*/
35+
export async function validateRuntimeCompatibility(runtimeVersion: number) {
2836
try {
2937
const platformSettings = await fetchPlatformSettings();
3038
if (platformSettings && platformSettings.latestSupportedJavaVersion) {
3139
const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion);
32-
const runtimeVersion = await checkJavaVersion(config.javaExec || path.join(await getJavaHome(), "bin", "java"));
3340
if (latestSupportedVersion < runtimeVersion) {
3441
showWarningMessageWithTroubleshooting({
3542
message: "The compiled classes are not compatible with the runtime JDK. To mitigate the issue, please refer to \"Learn More\".",
@@ -42,11 +49,14 @@ export async function validateRuntime(config: vscode.DebugConfiguration) {
4249
}
4350
}
4451

45-
export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration) {
52+
/**
53+
* Add some helpful VM arguments to the launch configuration based on the target runtime version.
54+
* @param config the launch configuration
55+
* @param runtimeVersion the target runtime version
56+
*/
57+
export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration, runtimeVersion: number) {
4658
try {
47-
const javaExec = config.javaExec || path.join(await getJavaHome(), "bin", "java");
48-
const version = await checkJavaVersion(javaExec);
49-
if (version >= 14) {
59+
if (runtimeVersion >= 14) {
5060
// JEP-358: https://openjdk.java.net/jeps/358
5161
if (config.vmArgs && config.vmArgs.indexOf(HELPFUL_NPE_VMARGS) >= 0) {
5262
return;
@@ -59,23 +69,63 @@ export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration) {
5969
}
6070
}
6171

62-
function checkJavaVersion(javaExec: string): Promise<number> {
63-
return new Promise((resolve, _reject) => {
64-
cp.execFile(javaExec, ["-version"], {}, (_error, _stdout, stderr) => {
65-
const javaVersion = parseMajorVersion(stderr);
66-
resolve(javaVersion);
67-
});
68-
});
72+
/**
73+
* Returns the target runtime version. If the javaExec is not specified, then return the current Java version
74+
* that the Java tooling used.
75+
* @param javaExec the path of the Java executable
76+
*/
77+
export async function getJavaVersion(javaExec: string): Promise<number> {
78+
javaExec = javaExec || path.join(await getJavaHome(), "bin", "java");
79+
let javaVersion = await checkVersionInReleaseFile(path.resolve(javaExec, "..", ".."));
80+
if (!javaVersion) {
81+
javaVersion = await checkVersionByCLI(javaExec);
82+
}
83+
return javaVersion;
6984
}
7085

71-
function parseMajorVersion(content: string): number {
72-
const regexp = /version "(.*)"/g;
73-
const match = regexp.exec(content);
74-
if (!match) {
86+
async function checkVersionInReleaseFile(javaHome: string): Promise<number> {
87+
if (!javaHome) {
7588
return 0;
7689
}
90+
const releaseFile = path.join(javaHome, "release");
91+
if (!await fs.existsSync(releaseFile)) {
92+
return 0;
93+
}
94+
95+
try {
96+
const content = fs.readFileSync(releaseFile);
97+
const regexp = /^JAVA_VERSION="(.*)"/gm;
98+
const match = regexp.exec(content.toString());
99+
if (!match) {
100+
return 0;
101+
}
102+
const majorVersion = flattenMajorVersion(match[1]);
103+
return majorVersion;
104+
} catch (error) {
105+
// ignore
106+
}
107+
108+
return 0;
109+
}
77110

78-
return flattenMajorVersion(match[1]);
111+
/**
112+
* Get version by parsing `JAVA_HOME/bin/java -version`
113+
*/
114+
async function checkVersionByCLI(javaExec: string): Promise<number> {
115+
if (!javaExec) {
116+
return 0;
117+
}
118+
return new Promise((resolve) => {
119+
cp.execFile(javaExec, ["-version"], {}, (_error, _stdout, stderr) => {
120+
const regexp = /version "(.*)"/g;
121+
const match = regexp.exec(stderr);
122+
if (!match) {
123+
return resolve(0);
124+
}
125+
const javaVersion = flattenMajorVersion(match[1]);
126+
resolve(javaVersion);
127+
});
128+
});
79129
}
80130

81131
function flattenMajorVersion(version: string): number {

0 commit comments

Comments
 (0)