From 476c5503f3432ac4f1021705b8fc0f242c2708c3 Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Thu, 3 Sep 2020 00:55:49 -0700 Subject: [PATCH 1/6] Add JdkInstaller If JDK 8 is not already installed, JdkInstaller will download the binary and source code at given path. --- packages/cli/src/lib/config.ts | 20 ++++- packages/core/src/index.ts | 2 + packages/core/src/lib/jdk/JdkInstaller.ts | 96 +++++++++++++++++++++++ 3 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 packages/core/src/lib/jdk/JdkInstaller.ts diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index d4a2a9d5..4d711bab 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -17,7 +17,7 @@ import {join} from 'path'; import {homedir} from 'os'; -import {Config, Log, ConsoleLog} from '@bubblewrap/core'; +import {Config, Log, ConsoleLog, JdkInstaller} from '@bubblewrap/core'; import * as inquirer from 'inquirer'; import {existsSync} from 'fs'; import {promises as fsPromises} from 'fs'; @@ -31,9 +31,15 @@ const LEGACY_CONFIG_FILE_PATH = join(LEGACY_CONFIG_FOLDER, LEGACY_CONFIG_NAME); async function createConfig(): Promise { const result = await inquirer.prompt([ + { + type: 'confirm', + name: 'jdkExists', + message: 'Do you have JDK 8 installed?', + default: false, + }, { name: 'jdkPath', - message: 'Path to the JDK:', + message: 'Path to the JDK. If not installed, enter the path you want JDK 8 to be installed at:', validate: existsSync, }, { name: 'androidSdkPath', @@ -41,7 +47,15 @@ async function createConfig(): Promise { validate: existsSync, }, ]); - return new Config(result.jdkPath, result.androidSdkPath); + + let jdkPath = result.jdkPath; + if (!result.jdkExists) { + console.log('Downloading JDK 8'); + const jdkInstaller = new JdkInstaller(process); + jdkPath = await jdkInstaller.install(result.jdkPath); + } + + return new Config(jdkPath, result.androidSdkPath); } async function renameConfigIfNeeded(log: Log): Promise { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7fcc4133..cd04df38 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -21,6 +21,7 @@ import {Log, ConsoleLog} from './lib/Log'; import {MockLog} from './spec/mock/MockLog'; import {JarSigner} from './lib/jdk/JarSigner'; import {JdkHelper} from './lib/jdk/JdkHelper'; +import {JdkInstaller} from './lib/jdk/JdkInstaller'; import {KeyTool} from './lib/jdk/KeyTool'; import {TwaManifest, DisplayModes, DisplayMode, asDisplayMode, SigningKeyInfo} from './lib/TwaManifest'; @@ -35,6 +36,7 @@ export {AndroidSdkTools, GradleWrapper, JarSigner, JdkHelper, + JdkInstaller, KeyTool, Log, ConsoleLog, diff --git a/packages/core/src/lib/jdk/JdkInstaller.ts b/packages/core/src/lib/jdk/JdkInstaller.ts new file mode 100644 index 00000000..497de50e --- /dev/null +++ b/packages/core/src/lib/jdk/JdkInstaller.ts @@ -0,0 +1,96 @@ +/* + * Copyright 2019 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +import * as path from 'path' +import util = require('../util'); + +const JDK_VERSION = '8u265-b01'; +const JDK_DIR = `jdk${JDK_VERSION}`; +const DOWNLOAD_JDK_BIN_ROOT = `https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk${JDK_VERSION}/`; +const DOWNLOAD_JDK_SRC_ROOT = 'https://github.com/AdoptOpenJDK/openjdk-jdk8u/archive/'; +const JDK_BIN_VERSION = JDK_VERSION.replace('-', ''); +const JDK_FILE_NAME_MAC = `OpenJDK8U-jdk_x64_mac_hotspot_${JDK_BIN_VERSION}.tar.gz`; +const JDK_FILE_NAME_WIN32 = `OpenJDK8U-jdk_x86-32_windows_hotspot_${JDK_BIN_VERSION}.zip`; +const JDK_FILE_NAME_LINUX64 = `OpenJDK8U-jdk_x64_linux_hotspot_${JDK_BIN_VERSION}.tar.gz`; +const JDK_SRC_ZIP = `jdk${JDK_VERSION}.zip`; + +/** + * Checks whether JDK 8 is installed. If not installed, + * download the binary and source code and decompress at + * path given by user. + */ +export class JdkInstaller { + private process: NodeJS.Process; + private downloadFile: string; + private unzipFunction: (srcPath: string, dstPath: string, deleteWhenDone: boolean) => Promise; + private joinPath: (...paths: string[]) => string; + /** + * Constructs a new instance of JdkInstaller + * + * @param process {NodeJS.Process} process information from the OS process + */ + constructor(process: NodeJS.Process) { + this.process = process; + this.unzipFunction = util.untar; + this.joinPath = path.posix.join; + switch (process.platform) { + case 'win32': { + this.downloadFile = JDK_FILE_NAME_WIN32; + this.unzipFunction = util.unzipFile; + this.joinPath = path.win32.join; + break; + } + case 'darwin': { + this.downloadFile = JDK_FILE_NAME_MAC; + break; + } + case 'linux': { + this.downloadFile = JDK_FILE_NAME_LINUX64; + break; + } + default: + this.downloadFile = ''; + console.log('Platform not found. Cannot download appropriate JDK.') + } + } + + /** + * Downloads the platform-appropriate version of JDK 8, including + * binary and source code. + * + * @param installPath {string} path to install JDK at + */ + async install(installPath: string): Promise { + if (this.downloadFile === '') { + throw new Error(`Platform not found or unsupported: ${this.process.platform}. Cannot download appropriate JDK.`); + } + let dstPath = path.resolve(installPath); + const downloadSrcUrl = DOWNLOAD_JDK_SRC_ROOT + JDK_SRC_ZIP; + const localSrcZipPath = this.joinPath(dstPath, JDK_SRC_ZIP); + await util.downloadFile(downloadSrcUrl, localSrcZipPath); + await util.unzipFile(localSrcZipPath, dstPath, true); + + const downloadBinUrl = DOWNLOAD_JDK_BIN_ROOT + this.downloadFile; + const localBinPath = this.joinPath(dstPath, this.downloadFile); + await util.downloadFile(downloadBinUrl, localBinPath); + await this.unzipFunction(localBinPath, dstPath, true); + + return this.joinPath(dstPath, JDK_DIR); + } +} + \ No newline at end of file From f3255922711294269c193d81b9d9888f9b2cb2a4 Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Thu, 3 Sep 2020 01:06:58 -0700 Subject: [PATCH 2/6] Fix lint errors --- packages/cli/src/lib/config.ts | 4 ++-- packages/core/src/lib/jdk/JdkInstaller.ts | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index 4d711bab..b6598a31 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -39,7 +39,7 @@ async function createConfig(): Promise { }, { name: 'jdkPath', - message: 'Path to the JDK. If not installed, enter the path you want JDK 8 to be installed at:', + message: 'Path to the JDK. If not installed, enter the desired install location:', validate: existsSync, }, { name: 'androidSdkPath', @@ -54,7 +54,7 @@ async function createConfig(): Promise { const jdkInstaller = new JdkInstaller(process); jdkPath = await jdkInstaller.install(result.jdkPath); } - + return new Config(jdkPath, result.androidSdkPath); } diff --git a/packages/core/src/lib/jdk/JdkInstaller.ts b/packages/core/src/lib/jdk/JdkInstaller.ts index 497de50e..99fb276d 100644 --- a/packages/core/src/lib/jdk/JdkInstaller.ts +++ b/packages/core/src/lib/jdk/JdkInstaller.ts @@ -16,7 +16,7 @@ 'use strict'; -import * as path from 'path' +import * as path from 'path'; import util = require('../util'); const JDK_VERSION = '8u265-b01'; @@ -37,11 +37,12 @@ const JDK_SRC_ZIP = `jdk${JDK_VERSION}.zip`; export class JdkInstaller { private process: NodeJS.Process; private downloadFile: string; - private unzipFunction: (srcPath: string, dstPath: string, deleteWhenDone: boolean) => Promise; + private unzipFunction: (srcPath: string, dstPath: string, deleteWhenDone: boolean) + => Promise; private joinPath: (...paths: string[]) => string; /** * Constructs a new instance of JdkInstaller - * + * * @param process {NodeJS.Process} process information from the OS process */ constructor(process: NodeJS.Process) { @@ -64,22 +65,22 @@ export class JdkInstaller { break; } default: - this.downloadFile = ''; - console.log('Platform not found. Cannot download appropriate JDK.') + this.downloadFile = ''; + console.log('Platform not found. Cannot download appropriate JDK.'); } } /** * Downloads the platform-appropriate version of JDK 8, including * binary and source code. - * + * * @param installPath {string} path to install JDK at */ async install(installPath: string): Promise { if (this.downloadFile === '') { - throw new Error(`Platform not found or unsupported: ${this.process.platform}. Cannot download appropriate JDK.`); + throw new Error(`Platform not found or unsupported: ${this.process.platform}.`); } - let dstPath = path.resolve(installPath); + const dstPath = path.resolve(installPath); const downloadSrcUrl = DOWNLOAD_JDK_SRC_ROOT + JDK_SRC_ZIP; const localSrcZipPath = this.joinPath(dstPath, JDK_SRC_ZIP); await util.downloadFile(downloadSrcUrl, localSrcZipPath); @@ -93,4 +94,3 @@ export class JdkInstaller { return this.joinPath(dstPath, JDK_DIR); } } - \ No newline at end of file From d7513f5040688fe6974aa8520869a4ce87637651 Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Tue, 8 Sep 2020 09:48:08 -0700 Subject: [PATCH 3/6] Update comments and move error to constructor --- packages/core/src/lib/jdk/JdkInstaller.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/core/src/lib/jdk/JdkInstaller.ts b/packages/core/src/lib/jdk/JdkInstaller.ts index 99fb276d..3811b570 100644 --- a/packages/core/src/lib/jdk/JdkInstaller.ts +++ b/packages/core/src/lib/jdk/JdkInstaller.ts @@ -30,9 +30,10 @@ const JDK_FILE_NAME_LINUX64 = `OpenJDK8U-jdk_x64_linux_hotspot_${JDK_BIN_VERSION const JDK_SRC_ZIP = `jdk${JDK_VERSION}.zip`; /** - * Checks whether JDK 8 is installed. If not installed, - * download the binary and source code and decompress at - * path given by user. + * Install JDK 8 by downloading the binary and source code and + * decompressing it at path given by user. Source code is required + * based on discussions with legal team about licensing. + * */ export class JdkInstaller { private process: NodeJS.Process; @@ -40,10 +41,11 @@ export class JdkInstaller { private unzipFunction: (srcPath: string, dstPath: string, deleteWhenDone: boolean) => Promise; private joinPath: (...paths: string[]) => string; + /** - * Constructs a new instance of JdkInstaller + * Constructs a new instance of JdkInstaller. * - * @param process {NodeJS.Process} process information from the OS process + * @param process {NodeJS.Process} process information from the OS process. */ constructor(process: NodeJS.Process) { this.process = process; @@ -66,7 +68,7 @@ export class JdkInstaller { } default: this.downloadFile = ''; - console.log('Platform not found. Cannot download appropriate JDK.'); + throw new Error(`Platform not found or unsupported: ${this.process.platform}.`); } } @@ -74,12 +76,9 @@ export class JdkInstaller { * Downloads the platform-appropriate version of JDK 8, including * binary and source code. * - * @param installPath {string} path to install JDK at + * @param installPath {string} path to install JDK at. */ async install(installPath: string): Promise { - if (this.downloadFile === '') { - throw new Error(`Platform not found or unsupported: ${this.process.platform}.`); - } const dstPath = path.resolve(installPath); const downloadSrcUrl = DOWNLOAD_JDK_SRC_ROOT + JDK_SRC_ZIP; const localSrcZipPath = this.joinPath(dstPath, JDK_SRC_ZIP); From b2bd919c0770951402a2f5991bafd805d3327a8e Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Tue, 8 Sep 2020 09:48:08 -0700 Subject: [PATCH 4/6] Update comments and move error to constructor --- packages/core/src/lib/jdk/JdkInstaller.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/core/src/lib/jdk/JdkInstaller.ts b/packages/core/src/lib/jdk/JdkInstaller.ts index 99fb276d..2b0d1377 100644 --- a/packages/core/src/lib/jdk/JdkInstaller.ts +++ b/packages/core/src/lib/jdk/JdkInstaller.ts @@ -30,9 +30,9 @@ const JDK_FILE_NAME_LINUX64 = `OpenJDK8U-jdk_x64_linux_hotspot_${JDK_BIN_VERSION const JDK_SRC_ZIP = `jdk${JDK_VERSION}.zip`; /** - * Checks whether JDK 8 is installed. If not installed, - * download the binary and source code and decompress at - * path given by user. + * Install JDK 8 by downloading the binary and source code and + * decompressing it at path given by user. Source code is required + * based on discussions with legal team about licensing. */ export class JdkInstaller { private process: NodeJS.Process; @@ -40,10 +40,11 @@ export class JdkInstaller { private unzipFunction: (srcPath: string, dstPath: string, deleteWhenDone: boolean) => Promise; private joinPath: (...paths: string[]) => string; + /** - * Constructs a new instance of JdkInstaller + * Constructs a new instance of JdkInstaller. * - * @param process {NodeJS.Process} process information from the OS process + * @param process {NodeJS.Process} process information from the OS process. */ constructor(process: NodeJS.Process) { this.process = process; @@ -66,7 +67,7 @@ export class JdkInstaller { } default: this.downloadFile = ''; - console.log('Platform not found. Cannot download appropriate JDK.'); + throw new Error(`Platform not found or unsupported: ${this.process.platform}.`); } } @@ -74,12 +75,9 @@ export class JdkInstaller { * Downloads the platform-appropriate version of JDK 8, including * binary and source code. * - * @param installPath {string} path to install JDK at + * @param installPath {string} path to install JDK at. */ async install(installPath: string): Promise { - if (this.downloadFile === '') { - throw new Error(`Platform not found or unsupported: ${this.process.platform}.`); - } const dstPath = path.resolve(installPath); const downloadSrcUrl = DOWNLOAD_JDK_SRC_ROOT + JDK_SRC_ZIP; const localSrcZipPath = this.joinPath(dstPath, JDK_SRC_ZIP); From af8d130a88de76499c17b091b164161500dc5e9b Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Tue, 8 Sep 2020 09:54:00 -0700 Subject: [PATCH 5/6] Fix lint errors --- packages/core/src/lib/jdk/JdkInstaller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/src/lib/jdk/JdkInstaller.ts b/packages/core/src/lib/jdk/JdkInstaller.ts index 3811b570..2b0d1377 100644 --- a/packages/core/src/lib/jdk/JdkInstaller.ts +++ b/packages/core/src/lib/jdk/JdkInstaller.ts @@ -30,10 +30,9 @@ const JDK_FILE_NAME_LINUX64 = `OpenJDK8U-jdk_x64_linux_hotspot_${JDK_BIN_VERSION const JDK_SRC_ZIP = `jdk${JDK_VERSION}.zip`; /** - * Install JDK 8 by downloading the binary and source code and + * Install JDK 8 by downloading the binary and source code and * decompressing it at path given by user. Source code is required * based on discussions with legal team about licensing. - * */ export class JdkInstaller { private process: NodeJS.Process; From c795e0e967e82dbe6711ad81bbdb3136f9138a96 Mon Sep 17 00:00:00 2001 From: Joyce Toh Date: Tue, 8 Sep 2020 13:52:51 -0700 Subject: [PATCH 6/6] Modify flow to install JDK to default path --- packages/cli/src/lib/config.ts | 44 +++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/cli/src/lib/config.ts b/packages/cli/src/lib/config.ts index b6598a31..089fbca0 100644 --- a/packages/cli/src/lib/config.ts +++ b/packages/cli/src/lib/config.ts @@ -28,34 +28,44 @@ export const DEFAULT_CONFIG_FILE_PATH = join(DEFAULT_CONFIG_FOLDER, DEFAULT_CONF const LEGACY_CONFIG_FOLDER = join(homedir(), '.llama-pack'); const LEGACY_CONFIG_NAME = 'llama-pack-config.json'; const LEGACY_CONFIG_FILE_PATH = join(LEGACY_CONFIG_FOLDER, LEGACY_CONFIG_NAME); +const DEFAULT_JDK_FOLDER = join(DEFAULT_CONFIG_FOLDER, 'jdk'); async function createConfig(): Promise { - const result = await inquirer.prompt([ + const installRequest = await inquirer.prompt([ { type: 'confirm', - name: 'jdkExists', - message: 'Do you have JDK 8 installed?', - default: false, + name: 'jdk', + message: 'Do you want Bubblewrap to install JDK? (Enter "No" to use your JDK installation)', + default: true, }, + ]); + + let jdkPath; + if (!installRequest.jdk) { + const jdk = await inquirer.prompt([ + { + name: 'path', + message: 'Path to your existing JDK:', + validate: existsSync, + }, + ]); + jdkPath = jdk.path; + } else { + await fsPromises.mkdir(DEFAULT_JDK_FOLDER); + console.log(`Downloading JDK 8 to ${DEFAULT_JDK_FOLDER}`); + const jdkInstaller = new JdkInstaller(process); + jdkPath = await jdkInstaller.install(DEFAULT_JDK_FOLDER); + } + + const androidSdk = await inquirer.prompt([ { - name: 'jdkPath', - message: 'Path to the JDK. If not installed, enter the desired install location:', - validate: existsSync, - }, { - name: 'androidSdkPath', + name: 'path', message: 'Path to the Android SDK:', validate: existsSync, }, ]); - let jdkPath = result.jdkPath; - if (!result.jdkExists) { - console.log('Downloading JDK 8'); - const jdkInstaller = new JdkInstaller(process); - jdkPath = await jdkInstaller.install(result.jdkPath); - } - - return new Config(jdkPath, result.androidSdkPath); + return new Config(jdkPath, androidSdk.path); } async function renameConfigIfNeeded(log: Log): Promise {