Skip to content

Commit b8a3050

Browse files
Verify JAVA_HOME is set correctly
Our system requirements point that JAVA_HOME must be set, but `tns doctor` is not strict about this. With version 1.7.0 of the runtime, `jarsigner` from $JAVA_HOME/bin/jarsigner will be called explicitly, so we must be sure JAVA_HOME is correct. `jarsigner` does not exist in JRE, so add logic to call it in order to verify that the currently set JAVA_HOME is correct. Validate the information in the following order: 1) Check if JAVA_HOME is set. In case it is not, you cannot build for Android (`tns build android` will fail before starting). 2) Check if JAVA_HOME is correct by executing JAVA_HOME/bin/jarsigner - in case it does not exist - fail 3) Check if the version of the JAVA is correct by calling JAVA_HOME/bin/javac -version and compare it with min required one. In case it's lower - fail. `tns doctor` will print warning in case any of the above check fails. `tns build android` and any other Android related build operations will fail.
1 parent 83cd22d commit b8a3050

File tree

4 files changed

+51
-16
lines changed

4 files changed

+51
-16
lines changed

lib/android-tools-info.ts

+46-11
Original file line numberDiff line numberDiff line change
@@ -156,30 +156,65 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
156156
}).future<boolean>()();
157157
}
158158

159-
public validateJavacVersion(installedJavaVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture<boolean> {
159+
public validateJava(javacVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture<boolean> {
160160
return ((): boolean => {
161-
let hasProblemWithJavaVersion = false;
162161
if(options) {
163162
this.showWarningsAsErrors = options.showWarningsAsErrors;
164163
}
165-
let additionalMessage = "You will not be able to build your projects for Android." + EOL
164+
165+
let helpfulMessage = "You will not be able to build your projects for Android." + EOL
166166
+ "To be able to build for Android, verify that you have installed The Java Development Kit (JDK) and configured it according to system requirements as" + EOL +
167167
" described in https://github.com/NativeScript/nativescript-cli#system-requirements.";
168-
let matchingVersion = (installedJavaVersion || "").match(AndroidToolsInfo.VERSION_REGEX);
169-
if(matchingVersion && matchingVersion[1]) {
170-
if(semver.lt(matchingVersion[1], AndroidToolsInfo.MIN_JAVA_VERSION)) {
171-
hasProblemWithJavaVersion = true;
172-
this.printMessage(`Javac version ${installedJavaVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, additionalMessage);
168+
169+
let hasProblemWithJavaHome = this.validateJavaHome(helpfulMessage).wait();
170+
let hasProblemWithJavaVersion: boolean;
171+
if(!hasProblemWithJavaHome) {
172+
hasProblemWithJavaVersion = this.validateJavacVersion(javacVersion, helpfulMessage);
173+
}
174+
175+
return hasProblemWithJavaHome || hasProblemWithJavaVersion;
176+
}).future<boolean>()();
177+
}
178+
179+
private validateJavaHome(helpfulMessage: string): IFuture<boolean> {
180+
return ((): boolean => {
181+
let hasProblemWithJavaHome = false;
182+
let javaHome = process.env.JAVA_HOME;
183+
184+
if(javaHome) {
185+
// validate jarsigner as it does not exist in JRE, but is mandatory for JDK and Android Runtime
186+
let jarSigner = path.join(javaHome, "bin", "jarsigner");
187+
let childProcessResult = this.$childProcess.spawnFromEvent(jarSigner, [], "close", {}, { throwError: false }).wait();
188+
this.$logger.trace(`Result of calling jarsigner from path: ${jarSigner}:`, childProcessResult);
189+
if(childProcessResult.stderr || childProcessResult.exitCode !== 0) {
190+
hasProblemWithJavaHome = true;
191+
this.printMessage("JAVA_HOME environment variable points to incorrect path. Make sure it points to the installation directory of JDK.", helpfulMessage);
173192
}
174193
} else {
175-
hasProblemWithJavaVersion = true;
176-
this.printMessage("Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable.", additionalMessage);
194+
hasProblemWithJavaHome = true;
195+
this.printMessage("JAVA_HOME environment variable is not set.", helpfulMessage);
177196
}
178197

179-
return hasProblemWithJavaVersion;
198+
return hasProblemWithJavaHome;
180199
}).future<boolean>()();
181200
}
182201

202+
private validateJavacVersion(installedJavaVersion: string, helpfulMessage: string): boolean {
203+
let hasProblemWithJavaVersion = false;
204+
let matchingVersion = (installedJavaVersion || "").match(AndroidToolsInfo.VERSION_REGEX);
205+
if(matchingVersion && matchingVersion[1]) {
206+
if(semver.lt(matchingVersion[1], AndroidToolsInfo.MIN_JAVA_VERSION)) {
207+
hasProblemWithJavaVersion = true;
208+
this.printMessage(`Javac version ${installedJavaVersion} is not supported. You have to install at least ${AndroidToolsInfo.MIN_JAVA_VERSION}.`, helpfulMessage);
209+
}
210+
} else {
211+
hasProblemWithJavaVersion = true;
212+
this.printMessage("Error executing command 'javac'. Make sure you have installed The Java Development Kit (JDK) and set JAVA_HOME environment variable.", helpfulMessage);
213+
}
214+
215+
return hasProblemWithJavaVersion;
216+
}
217+
183218
public getPathToAdbFromAndroidHome(): IFuture<string> {
184219
return (() => {
185220
if(this.androidHome) {

lib/declarations.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,12 @@ interface IAndroidToolsInfo {
160160
validateInfo(options?: {showWarningsAsErrors: boolean, validateTargetSdk: boolean}): IFuture<boolean>;
161161

162162
/**
163-
* Validates the information about required JAVA version.
164-
* @param {string} installedJavaVersion The JAVA version that will be checked.
163+
* Validates the information about required JAVA version and JAVA_HOME.
164+
* @param {string} javacVersion The JAVA version that will be checked.
165165
* @param {any} options Defines if the warning messages should treated as error.
166166
* @return {boolean} True if there are detected issues, false otherwise.
167167
*/
168-
validateJavacVersion(installedJavaVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture<boolean>;
168+
validateJava(javacVersion: string, options?: {showWarningsAsErrors: boolean}): IFuture<boolean>;
169169

170170
/**
171171
* Returns the path to `android` executable. It should be `$ANDROID_HOME/tools/android`.

lib/services/android-project-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
8888

8989
// this call will fail in case `android` is not set correctly.
9090
this.$androidToolsInfo.getPathToAndroidExecutable({showWarningsAsErrors: true}).wait();
91-
this.$androidToolsInfo.validateJavacVersion(this.$sysInfo.getSysInfo(path.join(__dirname, "..", "..", "package.json")).wait().javacVersion, {showWarningsAsErrors: true}).wait();
91+
this.$androidToolsInfo.validateJava(this.$sysInfo.getSysInfo(path.join(__dirname, "..", "..", "package.json")).wait().javacVersion, {showWarningsAsErrors: true}).wait();
9292
}).future<void>()();
9393
}
9494

lib/services/doctor-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class DoctorService implements IDoctorService {
8787
}
8888

8989
let androidToolsIssues = this.$androidToolsInfo.validateInfo().wait();
90-
let javaVersionIssue = this.$androidToolsInfo.validateJavacVersion(sysInfo.javacVersion).wait();
90+
let javaVersionIssue = this.$androidToolsInfo.validateJava(sysInfo.javacVersion).wait();
9191
return result || androidToolsIssues || javaVersionIssue;
9292
}
9393

0 commit comments

Comments
 (0)