Skip to content

Commit 016e2fb

Browse files
FIX (CodeAnalyzer v3): @W-15991264@: Backport java version check bug fix (#1504)
1 parent cf68113 commit 016e2fb

File tree

2 files changed

+36
-26
lines changed

2 files changed

+36
-26
lines changed

messages/jreSetupManager.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
We couldn't find Java Home.
44
Please verify that Java 1.8 or later is installed on your machine and try again.
5-
If the problem persists, please manually add a 'javaHome' property to your Config.json file, referencing your Java home directory.
5+
If the problem persists, please manually add a 'javaHome' property to your `%s` file, referencing your Java home directory.
66

77
# InvalidJavaHome
88

99
The Java Home is invalid: %s. Error code: %s.
1010
Please verify that Java 1.8 or later is installed on your machine and try again.
11-
If the problem persists, please manually add a 'javaHome' property to your Config.json file, referencing your Java home directory.
11+
If the problem persists, please manually add a 'javaHome' property to your `%s` file, referencing your Java home directory.
1212

1313
# VersionNotFound
1414

1515
We couldn't find the Java version.
1616
Please verify that Java 1.8 or later is installed on your machine and try again.
17-
If the problem persists, please manually add a 'javaHome' property to your Config.json file, referencing your Java home directory.
17+
If the problem persists, please manually add a 'javaHome' property to your `%s` file, referencing your Java home directory.
1818

1919
# InvalidVersion
2020

src/lib/JreSetupManager.ts

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export class JreSetupManagerDependencies {
3030
class JreSetupManager extends AsyncCreatable {
3131
private logger!: Logger;
3232
private config!: Config;
33+
private configFile: string;
3334
private dependencies: JreSetupManagerDependencies;
3435
private initialized: boolean;
3536

@@ -40,6 +41,7 @@ class JreSetupManager extends AsyncCreatable {
4041
this.logger = await Logger.child('verifyJRE');
4142

4243
this.config = await Controller.getConfig();
44+
this.configFile = path.join(Controller.getSfdxScannerPath(), CONFIG_FILE)
4345
this.dependencies = new JreSetupManagerDependencies();
4446

4547
this.initialized = true;
@@ -80,7 +82,7 @@ class JreSetupManager extends AsyncCreatable {
8082
// So we'll just throw an error telling the user to set it themselves.
8183
if (!javaHome) {
8284
const errName = 'NoJavaHomeFound';
83-
throw new SfError(getMessage(BundleName.JreSetupManager, errName, []), errName);
85+
throw new SfError(getMessage(BundleName.JreSetupManager, errName, [this.configFile]), errName);
8486
}
8587

8688
return javaHome;
@@ -110,42 +112,50 @@ class JreSetupManager extends AsyncCreatable {
110112
} catch (e) {
111113
const error: NodeJS.ErrnoException = e as NodeJS.ErrnoException;
112114
const errName = 'InvalidJavaHome';
113-
throw new SfError(getMessage(BundleName.JreSetupManager, errName, [javaHome, error.code]), errName);
115+
throw new SfError(getMessage(BundleName.JreSetupManager, errName, [javaHome, error.code, this.configFile]), errName);
114116
}
115117
}
116118

117119
private async verifyJavaVersion(javaHome: string): Promise<void> {
118-
const versionOut = await this.fetchJavaVersion(javaHome);
119-
120-
// Version output looks like this:
121-
// MacOS: "openjdk version "11.0.6" 2020-01-14 LTS\nOpenJDK Runtime Environment Zulu11.37+17-CA (build 11.0.6+10-LTS)\nOpenJDK 64-Bit Server VM Zulu11.37+17-CA (build 11.0.6+10-LTS, mixed mode)\n"
122-
// Win10: "openjdk 14 2020-03-17\r\nOpenJDK Runtime Environment (build 14+36-1461)\r\nOpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)\r\n"
123-
// We want to get the "11.0" or "14" part
124-
// The version number could be of the format 11.0 or 1.8 or 14
125-
const regex = /(\d+)(\.(\d+))?/;
126-
const matchedParts = regex.exec(versionOut);
127-
this.logger.trace(`Version output match for pattern ${regex.toString()} is ${JSON.stringify(matchedParts)}`);
128-
129-
// matchedParts should have four groups: "11.0", "11", ".0", "0" or "14", "14", undefined, undefined
130-
if (!matchedParts || matchedParts.length < 4) {
131-
throw new SfError(getMessage(BundleName.JreSetupManager, 'VersionNotFound', []));
120+
const versionCommandOut = await this.fetchJavaVersion(javaHome);
121+
122+
// We are using "java -version" below which has output that typically looks like:
123+
// * (from MacOS): "openjdk version "11.0.6" 2020-01-14 LTS\nOpenJDK Runtime Environment Zulu11.37+17-CA (build 11.0.6+10-LTS)\nOpenJDK 64-Bit Server VM Zulu11.37+17-CA (build 11.0.6+10-LTS, mixed mode)\n"
124+
// From much research it should ideally say "version " and then either a number with or without quotes.
125+
// If instead we used java --version then the output would look something like:
126+
// * (from Win10): "openjdk 14 2020-03-17\r\nOpenJDK Runtime Environment (build 14+36-1461)\r\nOpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)\r\n"
127+
// Notice it doesn't have the word "version" but again, we don't call "--version". But for sanity sakes,
128+
// we will attempt to support this as well. Basically we want to get the "11.0.6" or "14" part.
129+
130+
// First we'll see if the word "version" exists with the version number and use that first.
131+
const matchedParts = versionCommandOut.match(/version\s+"?(\d+(\.\d+)*)"?/i);
132+
this.logger.trace(`Attempt 1: Java version output match results is ${JSON.stringify(matchedParts)}`);
133+
let version: string;
134+
if (matchedParts && matchedParts.length > 1) {
135+
version = matchedParts[1];
136+
} else {
137+
// Otherwise we'll try to get the version number the old way just be looking for the first number
138+
const matchedParts = versionCommandOut.match(/\s+(\d+(\.\d+)*)/);
139+
this.logger.trace(`Attempt 2: Java version output match results is ${JSON.stringify(matchedParts)}`);
140+
if (!matchedParts || matchedParts.length < 2) {
141+
throw new SfError(getMessage(BundleName.JreSetupManager, 'VersionNotFound', [this.configFile]));
142+
}
143+
version = matchedParts[1];
132144
}
133145

134-
const majorVersion = parseInt(matchedParts[1]);
135-
const minorVersion = matchedParts[3] ? parseInt(matchedParts[3]) : '';
136-
const version = `${majorVersion}${minorVersion ? `.${minorVersion}` : ''}`;
137-
138-
// We want to allow 1.8 and greater.
139146
// Up to JDK8, the version scheme is 1.blah
140147
// Starting JDK 9, the version scheme is 9.blah for 9, 10.blah for 10, etc.
141-
// If either version part clicks, we should be good.
148+
const versionParts: string[] = version.split('.');
149+
const majorVersion = parseInt(versionParts[0]);
150+
const minorVersion: number = versionParts.length > 1 ? parseInt(versionParts[1]) : 0;
151+
142152
if (majorVersion === 1 && minorVersion === 8) {
143153
// Accommodating 1.8
144154
uxEvents.emit(EVENTS.WARNING_ALWAYS_UNIQUE, getMessage(BundleName.JreSetupManager, 'warning.JavaV8Deprecated', [path.join(Controller.getSfdxScannerPath(), CONFIG_FILE)]));
145155
} else if (majorVersion < 9) {
146156
// Not matching what we are looking for
147157
const errName = 'InvalidVersion';
148-
throw new SfError(getMessage(BundleName.JreSetupManager, errName, [version]), errName);
158+
throw new SfError(getMessage(BundleName.JreSetupManager, errName, [version, this.configFile]), errName);
149159
}
150160

151161
this.logger.trace(`Java version found as ${version}`);

0 commit comments

Comments
 (0)