java-caller 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/java-caller.js +51 -53
  2. package/package.json +4 -3
@@ -6,6 +6,7 @@ const path = require("path");
6
6
  const { spawn } = require("child_process");
7
7
  const util = require("util");
8
8
  const execPromise = util.promisify(require("child_process").exec);
9
+ const semver = require("semver");
9
10
 
10
11
  class JavaCaller {
11
12
  "use strict";
@@ -213,8 +214,10 @@ class JavaCaller {
213
214
  if (await this.getInstallInCache()) {
214
215
  return;
215
216
  }
217
+ const semverRule = `>=${this.minimumJavaVersion}.0.0` + (this.maximumJavaVersion ? ` <${this.maximumJavaVersion}.0.0` : '');
216
218
  const javaVersion = await this.getJavaVersion();
217
- if (javaVersion === false || javaVersion < this.minimumJavaVersion || (this.maximumJavaVersion && javaVersion > this.maximumJavaVersion)) {
219
+ const requiresInstall = javaVersion === false ? true : !semver.satisfies(javaVersion, semverRule)
220
+ if (requiresInstall) {
218
221
  // Check if the appropriate version has already been installed
219
222
  const { javaVersionHome = null, javaVersionBin = null } = await this.findJavaVersionHome();
220
223
  if (javaVersionHome) {
@@ -254,7 +257,7 @@ class JavaCaller {
254
257
  const njreOptions = { type: javaTypeToInstall };
255
258
  const prevRequireMainFilename = require.main.filename; // hack require.main.filename to njre installs java where we want
256
259
  require.main.filename = packageJson;
257
- const installDir = await njre.install(this.maximumJavaVersion || this.minimumJavaVersion, njreOptions);
260
+ const installDir = await njre.install(javaVersionToInstall, njreOptions);
258
261
  require.main.filename = prevRequireMainFilename; // unhack require.main.filename
259
262
  console.log(`Installed Java ${javaTypeToInstall} ${javaVersionToInstall} in ${installDir}...`);
260
263
 
@@ -283,24 +286,16 @@ class JavaCaller {
283
286
  try {
284
287
  const { stderr } = await execPromise("java -version");
285
288
  const match = /version "(.*?)"/.exec(stderr);
286
- const parts = match[1].split(".");
287
- let join = ".";
288
- let versionStr = "";
289
- for (const v of parts) {
290
- versionStr += v;
291
- if (join !== null) {
292
- versionStr += join;
293
- join = null;
294
- }
295
- }
296
- versionStr = versionStr.replace("_", "");
297
- let versionNb = parseFloat(versionStr);
298
- if (versionNb < 2) {
299
- versionStr = versionStr.substring(2);
300
- versionNb = parseFloat(versionStr[0] + "." + versionStr.substring(2));
289
+
290
+ // see https://openjdk.org/jeps/223
291
+ // semver.coerce does awfully good job of parsing anything Java throws our way
292
+ const version = semver.valid(semver.coerce(match[1]))
293
+ if (version === null) {
294
+ throw new Error(`unparsable java version: ${match[1]}`)
301
295
  }
302
- debug(`Found default java version ${versionNb}`);
303
- return versionNb;
296
+
297
+ debug(`Found default java version ${version}`);
298
+ return version;
304
299
  } catch (e) {
305
300
  debug(`Java not found: ${e.message}`);
306
301
  return false;
@@ -310,41 +305,44 @@ class JavaCaller {
310
305
  // Browse locally installed java versions
311
306
  // check if one matches with javaType , minimumJavaVersion and maximumJavaVersion
312
307
  async findJavaVersionHome() {
313
- let javaInstallsTopDir = this.javaCallerSupportDir + path.sep + "jre";
314
- if (fse.existsSync(javaInstallsTopDir)) {
315
- const dirContent = await fse.readdir(javaInstallsTopDir);
316
- let cacheFutureItem;
317
- let isFirst = true;
318
- const dirContentFiltered = dirContent.filter((file) => {
319
- if (!fse.statSync(path.join(javaInstallsTopDir, file)).isDirectory()) {
320
- return false;
321
- }
322
- const versionMatches = file.includes("u")
323
- ? file.substring(0, file.indexOf("u")).match(/(\d+)/)
324
- : file.substring(0, file.indexOf(".")).match(/(\d+)/);
325
- const versionFound = parseInt(versionMatches[0], 10);
326
- const isMatching = this.checkMatchingJavaVersion(versionFound, file);
327
- if (isMatching && isFirst) {
328
- cacheFutureItem = { versionFound, file };
329
- isFirst = false;
330
- }
331
- return isMatching;
332
- });
333
- if (dirContentFiltered[0]) {
334
- const javaVersionHome = javaInstallsTopDir + path.sep + dirContentFiltered[0];
335
- const javaVersionBin = javaVersionHome + path.sep + this.getPlatformBinPath();
336
- if (fse.existsSync(javaVersionBin)) {
337
- debug(
338
- `Found matching java bin: ${javaVersionBin} for ${this.javaType ? this.javaType : "jre or jdk"} ${this.minimumJavaVersion}${
339
- this.maximumJavaVersion && this.maximumJavaVersion !== this.minimumJavaVersion ? " -> " + this.maximumJavaVersion : "+"
340
- }`
341
- );
342
- this.addInCache(cacheFutureItem.versionFound, cacheFutureItem.file, javaVersionHome, javaVersionBin);
343
- return { javaVersionHome, javaVersionBin };
344
- }
345
- }
308
+ const javaInstallsTopDir = path.join(this.javaCallerSupportDir, "jre");
309
+ if (!fse.existsSync(javaInstallsTopDir)) {
310
+ return {};
346
311
  }
347
- return {};
312
+
313
+ return await fse.readdir(javaInstallsTopDir)
314
+ .then((items) =>
315
+ items
316
+ .filter((item) => fse.statSync(path.join(javaInstallsTopDir, item)).isDirectory())
317
+ .map((folder) => {
318
+ const version = semver.coerce(folder)
319
+ return { version, folder }
320
+ })
321
+ .filter(({ version, folder }) => this.checkMatchingJavaVersion(version.major, folder))
322
+ .map(({ version, folder }) => {
323
+ const home = path.join(javaInstallsTopDir, folder);
324
+ const bin = path.join(home, this.getPlatformBinPath());
325
+ return { version, folder, home, bin }
326
+ })
327
+ .find(({ bin }) => fse.existsSync(bin))
328
+ )
329
+ .then((match) => {
330
+ if (!match) return {};
331
+ const { version, folder, home, bin } = match
332
+
333
+ debug(
334
+ `Found matching java bin: ${bin} for ${this.javaType ? this.javaType : "jre or jdk"} ${this.minimumJavaVersion}${
335
+ this.maximumJavaVersion && this.maximumJavaVersion !== this.minimumJavaVersion ? " -> " + this.maximumJavaVersion : "+"
336
+ }`
337
+ );
338
+ this.addInCache(version.major, folder, home, bin);
339
+
340
+ return { javaVersionHome: home, javaVersionBin: bin };
341
+ })
342
+ .catch((e) => {
343
+ debug(`findJavaVersionHome failed: ${e}`)
344
+ return {}
345
+ })
348
346
  }
349
347
 
350
348
  checkMatchingJavaVersion(versionFound, file) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "java-caller",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Library to easily call java from node sources. Automatically installs java if not present",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -37,10 +37,11 @@
37
37
  "dependencies": {
38
38
  "debug": "^4.3.4",
39
39
  "fs-extra": "^11.1.1",
40
- "njre": "^1.0.0"
40
+ "njre": "^1.0.0",
41
+ "semver": "^7.5.4"
41
42
  },
42
43
  "devDependencies": {
43
- "@babel/eslint-parser": "^7.19.1",
44
+ "@babel/eslint-parser": "^7.22.15",
44
45
  "eslint": "^8.27.0",
45
46
  "mocha": "^10.1.0",
46
47
  "nyc": "^15.1.0",