Find Java version from release file (#922)

This commit is contained in:
Jinbo Wang 2020-12-16 10:26:44 +08:00 committed by GitHub
parent 78bd1f5f42
commit 4c0df75129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 26 deletions

View File

@ -12,7 +12,7 @@ import { buildWorkspace } from "./build";
import { populateStepFilters, substituteFilterVariables } from "./classFilter"; import { populateStepFilters, substituteFilterVariables } from "./classFilter";
import * as commands from "./commands"; import * as commands from "./commands";
import * as lsPlugin from "./languageServerPlugin"; import * as lsPlugin from "./languageServerPlugin";
import { addMoreHelpfulVMArgs, detectLaunchCommandStyle, validateRuntime } from "./launchCommand"; import { addMoreHelpfulVMArgs, getJavaVersion, getShortenApproachForCLI, validateRuntimeCompatibility } from "./launchCommand";
import { logger, Type } from "./logger"; import { logger, Type } from "./logger";
import { mainClassPicker } from "./mainClassPicker"; import { mainClassPicker } from "./mainClassPicker";
import { resolveJavaProcess } from "./processPicker"; import { resolveJavaProcess } from "./processPicker";
@ -271,17 +271,18 @@ export class JavaDebugConfigurationProvider implements vscode.DebugConfiguration
// Populate the class filters to the debug configuration. // Populate the class filters to the debug configuration.
await populateStepFilters(config); await populateStepFilters(config);
const targetJavaVersion: number = await getJavaVersion(config.javaExec);
// Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag. // Auto add '--enable-preview' vmArgs if the java project enables COMPILER_PB_ENABLE_PREVIEW_FEATURES flag.
if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) { if (await lsPlugin.detectPreviewFlag(config.mainClass, config.projectName)) {
config.vmArgs = (config.vmArgs || "") + " --enable-preview"; config.vmArgs = (config.vmArgs || "") + " --enable-preview";
validateRuntime(config); validateRuntimeCompatibility(targetJavaVersion);
} }
// Add more helpful vmArgs. // Add more helpful vmArgs.
await addMoreHelpfulVMArgs(config); await addMoreHelpfulVMArgs(config, targetJavaVersion);
if (!config.shortenCommandLine || config.shortenCommandLine === "auto") { if (!config.shortenCommandLine || config.shortenCommandLine === "auto") {
config.shortenCommandLine = await detectLaunchCommandStyle(config); config.shortenCommandLine = await getShortenApproachForCLI(config, targetJavaVersion);
} }
if (process.platform === "win32" && config.console !== "internalConsole") { if (process.platform === "win32" && config.console !== "internalConsole") {

View File

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. // Licensed under the MIT license.
import * as cp from "child_process"; import * as cp from "child_process";
import * as fs from "fs";
import * as _ from "lodash"; import * as _ from "lodash";
import * as path from "path"; import * as path from "path";
import * as vscode from "vscode"; import * as vscode from "vscode";
@ -17,19 +18,25 @@ enum shortenApproach {
const HELPFUL_NPE_VMARGS = "-XX:+ShowCodeDetailsInExceptionMessages"; const HELPFUL_NPE_VMARGS = "-XX:+ShowCodeDetailsInExceptionMessages";
export async function detectLaunchCommandStyle(config: vscode.DebugConfiguration): Promise<shortenApproach> { /**
const javaExec: string = config.javaExec || path.join(await getJavaHome(), "bin", "java"); * Returns the recommended approach to shorten the command line length.
const javaVersion = await checkJavaVersion(javaExec); * @param config the launch configuration
const recommendedShortenApproach = javaVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile; * @param runtimeVersion the target runtime version
*/
export async function getShortenApproachForCLI(config: vscode.DebugConfiguration, runtimeVersion: number): Promise<shortenApproach> {
const recommendedShortenApproach = runtimeVersion <= 8 ? shortenApproach.jarmanifest : shortenApproach.argfile;
return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none; return (await shouldShortenIfNecessary(config)) ? recommendedShortenApproach : shortenApproach.none;
} }
export async function validateRuntime(config: vscode.DebugConfiguration) { /**
* Validates whether the specified runtime version could be supported by the Java tooling.
* @param runtimeVersion the target runtime version
*/
export async function validateRuntimeCompatibility(runtimeVersion: number) {
try { try {
const platformSettings = await fetchPlatformSettings(); const platformSettings = await fetchPlatformSettings();
if (platformSettings && platformSettings.latestSupportedJavaVersion) { if (platformSettings && platformSettings.latestSupportedJavaVersion) {
const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion); const latestSupportedVersion = flattenMajorVersion(platformSettings.latestSupportedJavaVersion);
const runtimeVersion = await checkJavaVersion(config.javaExec || path.join(await getJavaHome(), "bin", "java"));
if (latestSupportedVersion < runtimeVersion) { if (latestSupportedVersion < runtimeVersion) {
showWarningMessageWithTroubleshooting({ showWarningMessageWithTroubleshooting({
message: "The compiled classes are not compatible with the runtime JDK. To mitigate the issue, please refer to \"Learn More\".", 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) {
} }
} }
export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration) { /**
* Add some helpful VM arguments to the launch configuration based on the target runtime version.
* @param config the launch configuration
* @param runtimeVersion the target runtime version
*/
export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration, runtimeVersion: number) {
try { try {
const javaExec = config.javaExec || path.join(await getJavaHome(), "bin", "java"); if (runtimeVersion >= 14) {
const version = await checkJavaVersion(javaExec);
if (version >= 14) {
// JEP-358: https://openjdk.java.net/jeps/358 // JEP-358: https://openjdk.java.net/jeps/358
if (config.vmArgs && config.vmArgs.indexOf(HELPFUL_NPE_VMARGS) >= 0) { if (config.vmArgs && config.vmArgs.indexOf(HELPFUL_NPE_VMARGS) >= 0) {
return; return;
@ -59,23 +69,63 @@ export async function addMoreHelpfulVMArgs(config: vscode.DebugConfiguration) {
} }
} }
function checkJavaVersion(javaExec: string): Promise<number> { /**
return new Promise((resolve, _reject) => { * Returns the target runtime version. If the javaExec is not specified, then return the current Java version
cp.execFile(javaExec, ["-version"], {}, (_error, _stdout, stderr) => { * that the Java tooling used.
const javaVersion = parseMajorVersion(stderr); * @param javaExec the path of the Java executable
resolve(javaVersion); */
}); export async function getJavaVersion(javaExec: string): Promise<number> {
}); javaExec = javaExec || path.join(await getJavaHome(), "bin", "java");
let javaVersion = await checkVersionInReleaseFile(path.resolve(javaExec, "..", ".."));
if (!javaVersion) {
javaVersion = await checkVersionByCLI(javaExec);
}
return javaVersion;
} }
function parseMajorVersion(content: string): number { async function checkVersionInReleaseFile(javaHome: string): Promise<number> {
const regexp = /version "(.*)"/g; if (!javaHome) {
const match = regexp.exec(content); return 0;
if (!match) { }
const releaseFile = path.join(javaHome, "release");
if (!await fs.existsSync(releaseFile)) {
return 0; return 0;
} }
return flattenMajorVersion(match[1]); try {
const content = fs.readFileSync(releaseFile);
const regexp = /^JAVA_VERSION="(.*)"/gm;
const match = regexp.exec(content.toString());
if (!match) {
return 0;
}
const majorVersion = flattenMajorVersion(match[1]);
return majorVersion;
} catch (error) {
// ignore
}
return 0;
}
/**
* Get version by parsing `JAVA_HOME/bin/java -version`
*/
async function checkVersionByCLI(javaExec: string): Promise<number> {
if (!javaExec) {
return 0;
}
return new Promise((resolve) => {
cp.execFile(javaExec, ["-version"], {}, (_error, _stdout, stderr) => {
const regexp = /version "(.*)"/g;
const match = regexp.exec(stderr);
if (!match) {
return resolve(0);
}
const javaVersion = flattenMajorVersion(match[1]);
resolve(javaVersion);
});
});
} }
function flattenMajorVersion(version: string): number { function flattenMajorVersion(version: string): number {