From d94365f53575314379b6ebded79f03a4115ec112 Mon Sep 17 00:00:00 2001 From: Daniel Scalzi Date: Sun, 2 Jun 2019 18:11:39 -0400 Subject: [PATCH] Use OpenJDK downloads instead of Oracle (no longer possible). Makes use of https://adoptopenjdk.net/, star them on GitHub, great product. --- app/assets/js/assetexec.js | 38 ++-- app/assets/js/assetguard.js | 318 ++++++++++++++++++++----------- app/assets/js/scripts/landing.js | 9 +- 3 files changed, 244 insertions(+), 121 deletions(-) diff --git a/app/assets/js/assetexec.js b/app/assets/js/assetexec.js index b234efe..28c3af7 100644 --- a/app/assets/js/assetexec.js +++ b/app/assets/js/assetexec.js @@ -14,18 +14,22 @@ console.log('AssetExec Started') // Temporary for debug purposes. process.on('unhandledRejection', r => console.log(r)) -tracker.on('validate', (data) => { - process.send({context: 'validate', data}) -}) -tracker.on('progress', (data, acc, total) => { - process.send({context: 'progress', data, value: acc, total, percent: parseInt((acc/total)*100)}) -}) -tracker.on('complete', (data, ...args) => { - process.send({context: 'complete', data, args}) -}) -tracker.on('error', (data, error) => { - process.send({context: 'error', data, error}) -}) +function assignListeners(){ + tracker.on('validate', (data) => { + process.send({context: 'validate', data}) + }) + tracker.on('progress', (data, acc, total) => { + process.send({context: 'progress', data, value: acc, total, percent: parseInt((acc/total)*100)}) + }) + tracker.on('complete', (data, ...args) => { + process.send({context: 'complete', data, args}) + }) + tracker.on('error', (data, error) => { + process.send({context: 'error', data, error}) + }) +} + +assignListeners() process.on('message', (msg) => { if(msg.task === 'execute'){ @@ -44,6 +48,16 @@ process.on('message', (msg) => { } else { process.send({result: res, context: func}) } + } else { + process.send({context: 'error', data: null, error: `Function ${func} not found on ${process.argv[2]}`}) + } + } else if(msg.task === 'changeContext'){ + target = require('./assetguard')[msg.class] + if(target == null){ + process.send({context: 'error', data: null, error: `Invalid class ${msg.class}`}) + } else { + tracker = new target(...(msg.args)) + assignListeners() } } }) diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js index c0de4ae..3e065ff 100644 --- a/app/assets/js/assetguard.js +++ b/app/assets/js/assetguard.js @@ -16,11 +16,11 @@ const DistroManager = require('./distromanager') const isDev = require('./isdev') // Constants -const PLATFORM_MAP = { - win32: '-windows-x64.tar.gz', - darwin: '-macosx-x64.tar.gz', - linux: '-linux-x64.tar.gz' -} +// const PLATFORM_MAP = { +// win32: '-windows-x64.tar.gz', +// darwin: '-macosx-x64.tar.gz', +// linux: '-linux-x64.tar.gz' +// } // Classes @@ -176,34 +176,69 @@ class JavaGuard extends EventEmitter { this.mcVersion = mcVersion } - /** - * @typedef OracleJREData - * @property {string} uri The base uri of the JRE. - * @property {{major: string, update: string, build: string}} version Object containing version information. - */ + // /** + // * @typedef OracleJREData + // * @property {string} uri The base uri of the JRE. + // * @property {{major: string, update: string, build: string}} version Object containing version information. + // */ - /** - * Resolves the latest version of Oracle's JRE and parses its download link. - * - * @returns {Promise.} Promise which resolved to an object containing the JRE download data. - */ - static _latestJREOracle(){ + // /** + // * Resolves the latest version of Oracle's JRE and parses its download link. + // * + // * @returns {Promise.} Promise which resolved to an object containing the JRE download data. + // */ + // static _latestJREOracle(){ - const url = 'https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html' - const regex = /https:\/\/.+?(?=\/java)\/java\/jdk\/([0-9]+u[0-9]+)-(b[0-9]+)\/([a-f0-9]{32})?\/jre-\1/ + // const url = 'https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html' + // const regex = /https:\/\/.+?(?=\/java)\/java\/jdk\/([0-9]+u[0-9]+)-(b[0-9]+)\/([a-f0-9]{32})?\/jre-\1/ + // return new Promise((resolve, reject) => { + // request(url, (err, resp, body) => { + // if(!err){ + // const arr = body.match(regex) + // const verSplit = arr[1].split('u') + // resolve({ + // uri: arr[0], + // version: { + // major: verSplit[0], + // update: verSplit[1], + // build: arr[2] + // } + // }) + // } else { + // resolve(null) + // } + // }) + // }) + // } + + /** + * @typedef OpenJDKData + * @property {string} uri The base uri of the JRE. + * @property {number} size The size of the download. + * @property {string} name The name of the artifact. + */ + + /** + * Fetch the last open JDK binary. Uses https://api.adoptopenjdk.net/ + * + * @param {string} major The major version of Java to fetch. + * + * @returns {Promise.} Promise which resolved to an object containing the JRE download data. + */ + static _latestOpenJDK(major = '8'){ + + const sanitizedOS = process.platform === 'win32' ? 'windows' : (process.platform === 'darwin' ? 'mac' : process.platform) + + const url = `https://api.adoptopenjdk.net/v2/latestAssets/nightly/openjdk${major}?os=${sanitizedOS}&arch=x64&heap_size=normal&openjdk_impl=hotspot&type=jre` + return new Promise((resolve, reject) => { - request(url, (err, resp, body) => { - if(!err){ - const arr = body.match(regex) - const verSplit = arr[1].split('u') + request({url, json: true}, (err, resp, body) => { + if(!err && body.length > 0){ resolve({ - uri: arr[0], - version: { - major: verSplit[0], - update: verSplit[1], - build: arr[2] - } + uri: body[0].binary_link, + size: body[0].binary_size, + name: body[0].binary_name }) } else { resolve(null) @@ -401,6 +436,11 @@ class JavaGuard extends EventEmitter { if(!JavaGuard.isJavaExecPath(binaryExecPath)){ resolve({valid: false}) } else if(fs.existsSync(binaryExecPath)){ + // Workaround (javaw.exe no longer outputs this information.) + console.log(typeof binaryExecPath) + if(binaryExecPath.indexOf('javaw.exe') > -1) { + binaryExecPath.replace('javaw.exe', 'java.exe') + } child_process.exec('"' + binaryExecPath + '" -XshowSettings:properties', (err, stdout, stderr) => { try { // Output is stored in stderr? @@ -1447,59 +1487,63 @@ class AssetGuard extends EventEmitter { // Java (Category=''') Validation (download) Functions // #region - _enqueueOracleJRE(dataDir){ + _enqueueOpenJDK(dataDir){ return new Promise((resolve, reject) => { - AssetGuard._latestJREOracle().then(verData => { + JavaGuard._latestOpenJDK('8').then(verData => { if(verData != null){ - const combined = verData.uri + PLATFORM_MAP[process.platform] - - const opts = { - url: combined, - headers: { - 'Cookie': 'oraclelicense=accept-securebackup-cookie' - } - } - - request.head(opts, (err, resp, body) => { - if(err){ - resolve(false) - } else { - dataDir = path.join(dataDir, 'runtime', 'x64') - const name = combined.substring(combined.lastIndexOf('/')+1) - const fDir = path.join(dataDir, name) - const jre = new Asset(name, null, parseInt(resp.headers['content-length']), opts, fDir) - this.java = new DLTracker([jre], jre.size, (a, self) => { - let h = null - fs.createReadStream(a.to) - .on('error', err => console.log(err)) - .pipe(zlib.createGunzip()) - .on('error', err => console.log(err)) - .pipe(tar.extract(dataDir, { - map: (header) => { - if(h == null){ - h = header.name - } + dataDir = path.join(dataDir, 'runtime', 'x64') + const fDir = path.join(dataDir, verData.name) + const jre = new Asset(verData.name, null, verData.size, verData.uri, fDir) + this.java = new DLTracker([jre], jre.size, (a, self) => { + if(verData.name.endsWith('zip')){ + + const zip = new AdmZip(a.to) + const pos = path.join(dataDir, zip.getEntries()[0].entryName) + zip.extractAllToAsync(dataDir, true, (err) => { + if(err){ + console.log(err) + self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos)) + } else { + fs.unlink(a.to, err => { + if(err){ + console.log(err) } - })) - .on('error', err => console.log(err)) - .on('finish', () => { - fs.unlink(a.to, err => { - if(err){ - console.log(err) - } - if(h.indexOf('/') > -1){ - h = h.substring(0, h.indexOf('/')) - } - const pos = path.join(dataDir, h) - self.emit('complete', 'java', AssetGuard.javaExecFromRoot(pos)) - }) + self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos)) }) - + } }) - resolve(true) + + } else { + // Tar.gz + let h = null + fs.createReadStream(a.to) + .on('error', err => console.log(err)) + .pipe(zlib.createGunzip()) + .on('error', err => console.log(err)) + .pipe(tar.extract(dataDir, { + map: (header) => { + if(h == null){ + h = header.name + } + } + })) + .on('error', err => console.log(err)) + .on('finish', () => { + fs.unlink(a.to, err => { + if(err){ + console.log(err) + } + if(h.indexOf('/') > -1){ + h = h.substring(0, h.indexOf('/')) + } + const pos = path.join(dataDir, h) + self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos)) + }) + }) } }) + resolve(true) } else { resolve(false) @@ -1509,42 +1553,104 @@ class AssetGuard extends EventEmitter { } - /*_enqueueMojangJRE(dir){ - return new Promise((resolve, reject) => { - // Mojang does not host the JRE for linux. - if(process.platform === 'linux'){ - resolve(false) - } - AssetGuard.loadMojangLauncherData().then(data => { - if(data != null) { + // _enqueueOracleJRE(dataDir){ + // return new Promise((resolve, reject) => { + // JavaGuard._latestJREOracle().then(verData => { + // if(verData != null){ - try { - const mJRE = data[Library.mojangFriendlyOS()]['64'].jre - const url = mJRE.url + // const combined = verData.uri + PLATFORM_MAP[process.platform] + + // const opts = { + // url: combined, + // headers: { + // 'Cookie': 'oraclelicense=accept-securebackup-cookie' + // } + // } + + // request.head(opts, (err, resp, body) => { + // if(err){ + // resolve(false) + // } else { + // dataDir = path.join(dataDir, 'runtime', 'x64') + // const name = combined.substring(combined.lastIndexOf('/')+1) + // const fDir = path.join(dataDir, name) + // const jre = new Asset(name, null, parseInt(resp.headers['content-length']), opts, fDir) + // this.java = new DLTracker([jre], jre.size, (a, self) => { + // let h = null + // fs.createReadStream(a.to) + // .on('error', err => console.log(err)) + // .pipe(zlib.createGunzip()) + // .on('error', err => console.log(err)) + // .pipe(tar.extract(dataDir, { + // map: (header) => { + // if(h == null){ + // h = header.name + // } + // } + // })) + // .on('error', err => console.log(err)) + // .on('finish', () => { + // fs.unlink(a.to, err => { + // if(err){ + // console.log(err) + // } + // if(h.indexOf('/') > -1){ + // h = h.substring(0, h.indexOf('/')) + // } + // const pos = path.join(dataDir, h) + // self.emit('complete', 'java', JavaGuard.javaExecFromRoot(pos)) + // }) + // }) + + // }) + // resolve(true) + // } + // }) - request.head(url, (err, resp, body) => { - if(err){ - resolve(false) - } else { - const name = url.substring(url.lastIndexOf('/')+1) - const fDir = path.join(dir, name) - const jre = new Asset('jre' + mJRE.version, mJRE.sha1, resp.headers['content-length'], url, fDir) - this.java = new DLTracker([jre], jre.size, a => { - fs.readFile(a.to, (err, data) => { - // Data buffer needs to be decompressed from lzma, - // not really possible using node.js - }) - }) - } - }) - } catch (err){ - resolve(false) - } + // } else { + // resolve(false) + // } + // }) + // }) - } - }) - }) - }*/ + // } + + // _enqueueMojangJRE(dir){ + // return new Promise((resolve, reject) => { + // // Mojang does not host the JRE for linux. + // if(process.platform === 'linux'){ + // resolve(false) + // } + // AssetGuard.loadMojangLauncherData().then(data => { + // if(data != null) { + + // try { + // const mJRE = data[Library.mojangFriendlyOS()]['64'].jre + // const url = mJRE.url + + // request.head(url, (err, resp, body) => { + // if(err){ + // resolve(false) + // } else { + // const name = url.substring(url.lastIndexOf('/')+1) + // const fDir = path.join(dir, name) + // const jre = new Asset('jre' + mJRE.version, mJRE.sha1, resp.headers['content-length'], url, fDir) + // this.java = new DLTracker([jre], jre.size, a => { + // fs.readFile(a.to, (err, data) => { + // // Data buffer needs to be decompressed from lzma, + // // not really possible using node.js + // }) + // }) + // } + // }) + // } catch (err){ + // resolve(false) + // } + + // } + // }) + // }) + // } // #endregion diff --git a/app/assets/js/scripts/landing.js b/app/assets/js/scripts/landing.js index 247f635..57e2e73 100644 --- a/app/assets/js/scripts/landing.js +++ b/app/assets/js/scripts/landing.js @@ -329,7 +329,8 @@ function asyncSystemScan(mcVersion, launchAfter = true){ ) setOverlayHandler(() => { setLaunchDetails('Preparing Java Download..') - sysAEx.send({task: 'execute', function: '_enqueueOracleJRE', argsArr: [ConfigManager.getDataDirectory()]}) + sysAEx.send({task: 'changeContext', class: 'AssetGuard', args: [ConfigManager.getCommonDirectory(),ConfigManager.getJavaExecutable()]}) + sysAEx.send({task: 'execute', function: '_enqueueOpenJDK', argsArr: [ConfigManager.getDataDirectory()]}) toggleOverlay(false) }) setDismissHandler(() => { @@ -369,7 +370,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){ } sysAEx.disconnect() } - } else if(m.context === '_enqueueOracleJRE'){ + } else if(m.context === '_enqueueOpenJDK'){ if(m.result === true){ @@ -399,7 +400,7 @@ function asyncSystemScan(mcVersion, launchAfter = true){ switch(m.data){ case 'download': - // Downloading.. + // Downloading.. setDownloadPercentage(m.value, m.total, m.percent) break } @@ -448,6 +449,8 @@ function asyncSystemScan(mcVersion, launchAfter = true){ break } + } else if(m.context === 'error'){ + console.log(m.error) } })