From 45bfed9ab41a25b937215883a56e2b211ace144c Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 11 Feb 2026 11:13:33 +0100 Subject: [PATCH 1/4] Improve veraPDF Java version error message --- src/tools/impl/verapdf.ts | 11 +++++++++-- src/tools/tools.ts | 5 ++++- src/tools/types.ts | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/tools/impl/verapdf.ts b/src/tools/impl/verapdf.ts index cdf64233839..b885f586f80 100644 --- a/src/tools/impl/verapdf.ts +++ b/src/tools/impl/verapdf.ts @@ -40,8 +40,15 @@ export const verapdfInstallable: InstallableTool = { kSupportedJavaVersions.includes(javaVersion); }, os: ["darwin", "linux", "windows"], - message: - `Java is not installed or version is not supported. veraPDF requires Java 8, 11, 17, or 21.`, + message: async () => { + const javaVersion = await getJavaVersion(); + const supportedVersions = kSupportedJavaVersions.join(", "); + if (javaVersion === undefined) { + return `Java is not installed. veraPDF requires Java ${supportedVersions}.`; + } else { + return `Java ${javaVersion} is installed but not supported. veraPDF requires Java ${supportedVersions}.`; + } + }, }], installed, installDir, diff --git a/src/tools/tools.ts b/src/tools/tools.ts index b8c59d6abed..b15f482ead8 100644 --- a/src/tools/tools.ts +++ b/src/tools/tools.ts @@ -136,7 +136,10 @@ export async function installTool(name: string, updatePath?: boolean) { for (const prereq of platformPrereqs) { const met = await prereq.check(context); if (!met) { - context.error(prereq.message); + const message = typeof prereq.message === "function" + ? await prereq.message(context) + : prereq.message; + context.error(message); Deno.exit(1); } } diff --git a/src/tools/types.ts b/src/tools/types.ts index f6e23c2d384..6a1d9fcddaf 100644 --- a/src/tools/types.ts +++ b/src/tools/types.ts @@ -30,7 +30,7 @@ export interface InstallableTool { export interface InstallPreReq { check: (context: InstallContext) => Promise; os: string[]; - message: string; + message: string | ((context: InstallContext) => Promise); } // Locally accessible Package information From b0f6d2ea0edf13330cbe1bcb092dbaf0f6611e09 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 11 Feb 2026 11:27:00 +0100 Subject: [PATCH 2/4] Cache Java version to avoid redundant subprocess call The check and message functions were both calling getJavaVersion(), spawning the subprocess twice. This created inefficiency and a TOCTOU risk where the Java environment could change between calls. Now check caches the detected version in context.props.javaVersion, and message reads from the cache. The message function is now synchronous since it only reads from context. The InstallPreReq.message type was updated to allow both sync and async functions for flexibility. Co-Authored-By: Claude Opus 4.6 --- src/tools/impl/verapdf.ts | 7 ++++--- src/tools/types.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/impl/verapdf.ts b/src/tools/impl/verapdf.ts index b885f586f80..d45f1b95e84 100644 --- a/src/tools/impl/verapdf.ts +++ b/src/tools/impl/verapdf.ts @@ -34,14 +34,15 @@ const kVersionFileName = "version"; export const verapdfInstallable: InstallableTool = { name: "VeraPDF", prereqs: [{ - check: async () => { + check: async (context) => { const javaVersion = await getJavaVersion(); + context.props.javaVersion = javaVersion; return javaVersion !== undefined && kSupportedJavaVersions.includes(javaVersion); }, os: ["darwin", "linux", "windows"], - message: async () => { - const javaVersion = await getJavaVersion(); + message: (context) => { + const javaVersion = context.props.javaVersion as number | undefined; const supportedVersions = kSupportedJavaVersions.join(", "); if (javaVersion === undefined) { return `Java is not installed. veraPDF requires Java ${supportedVersions}.`; diff --git a/src/tools/types.ts b/src/tools/types.ts index 6a1d9fcddaf..265d47465d3 100644 --- a/src/tools/types.ts +++ b/src/tools/types.ts @@ -30,7 +30,7 @@ export interface InstallableTool { export interface InstallPreReq { check: (context: InstallContext) => Promise; os: string[]; - message: string | ((context: InstallContext) => Promise); + message: string | ((context: InstallContext) => string | Promise); } // Locally accessible Package information From 546dd9736b4483389265a9755dec18c46596941b Mon Sep 17 00:00:00 2001 From: Gordon Woodhull Date: Thu, 12 Feb 2026 17:06:47 -0500 Subject: [PATCH 3/4] claude: Warn instead of error for non-LTS Java versions in veraPDF Allow veraPDF installation with any Java 8+, but warn if using a non-LTS version. LTS versions (8, 11, 17, 21, 25, ...) proceed silently. Co-Authored-By: Claude Opus 4.5 --- src/tools/impl/verapdf.ts | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/tools/impl/verapdf.ts b/src/tools/impl/verapdf.ts index d45f1b95e84..d687aa9dd01 100644 --- a/src/tools/impl/verapdf.ts +++ b/src/tools/impl/verapdf.ts @@ -6,6 +6,7 @@ import { existsSync, safeRemoveSync } from "../../deno_ral/fs.ts"; import { basename, join } from "../../deno_ral/path.ts"; +import { warning } from "../../deno_ral/log.ts"; import { unzip } from "../../core/zip.ts"; import { execProcess } from "../../core/process.ts"; @@ -25,29 +26,50 @@ import { isWindows } from "../../deno_ral/platform.ts"; const kDownloadBaseUrl = "https://quarto.org/download"; const kDefaultVersion = "1.28.2"; -// Supported Java versions for veraPDF -const kSupportedJavaVersions = [8, 11, 17, 21]; +// Minimum Java version required +const kMinJavaVersion = 8; // The name of the file that we use to store the installed version const kVersionFileName = "version"; +// Check if a Java version is a Long-Term Support (LTS) release. +// LTS versions: 8, 11, then every 2 years starting from 17 (17, 21, 25, 29, ...) +function isLtsJavaVersion(version: number): boolean { + if (version === 8 || version === 11) return true; + if (version >= 17 && (version - 17) % 4 === 0) return true; + return false; +} + export const verapdfInstallable: InstallableTool = { name: "VeraPDF", prereqs: [{ check: async (context) => { const javaVersion = await getJavaVersion(); context.props.javaVersion = javaVersion; - return javaVersion !== undefined && - kSupportedJavaVersions.includes(javaVersion); + + // Block installation if Java is not installed or version is too old + if (javaVersion === undefined || javaVersion < kMinJavaVersion) { + return false; + } + + // Warn but allow installation for non-LTS Java versions + if (!isLtsJavaVersion(javaVersion)) { + warning( + `Java ${javaVersion} is not a Long-Term Support (LTS) version. ` + + `veraPDF officially supports LTS versions (8, 11, 17, 21, 25, ...). ` + + `Installation will proceed, but you may encounter issues.`, + ); + } + + return true; }, os: ["darwin", "linux", "windows"], message: (context) => { const javaVersion = context.props.javaVersion as number | undefined; - const supportedVersions = kSupportedJavaVersions.join(", "); if (javaVersion === undefined) { - return `Java is not installed. veraPDF requires Java ${supportedVersions}.`; + return `Java is not installed. veraPDF requires Java ${kMinJavaVersion} or later.`; } else { - return `Java ${javaVersion} is installed but not supported. veraPDF requires Java ${supportedVersions}.`; + return `Java ${javaVersion} is too old. veraPDF requires Java ${kMinJavaVersion} or later.`; } }, }], From c3965e1a9026a5c6114ebc688ac3959365114db8 Mon Sep 17 00:00:00 2001 From: Gordon Woodhull Date: Thu, 12 Feb 2026 17:47:53 -0500 Subject: [PATCH 4/4] claude: Warn instead of error for unsupported Java versions in veraPDF Allow installation with any Java 8+. Warn (but proceed) for non-LTS versions or LTS versions newer than this veraPDF release supports. Co-Authored-By: Claude Opus 4.5 --- src/tools/impl/verapdf.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/tools/impl/verapdf.ts b/src/tools/impl/verapdf.ts index d687aa9dd01..0f3303257c5 100644 --- a/src/tools/impl/verapdf.ts +++ b/src/tools/impl/verapdf.ts @@ -29,6 +29,10 @@ const kDefaultVersion = "1.28.2"; // Minimum Java version required const kMinJavaVersion = 8; +// Highest Java LTS version officially supported by this veraPDF version. +// Update this when bumping kDefaultVersion to a release that supports a newer LTS. +const kMaxSupportedLtsVersion = 21; + // The name of the file that we use to store the installed version const kVersionFileName = "version"; @@ -52,11 +56,20 @@ export const verapdfInstallable: InstallableTool = { return false; } - // Warn but allow installation for non-LTS Java versions + // Warn but allow installation for non-LTS or too-new LTS Java versions if (!isLtsJavaVersion(javaVersion)) { + const supportedVersions = Array.from( + { length: kMaxSupportedLtsVersion - 8 + 1 }, + (_, i) => i + 8, + ).filter(isLtsJavaVersion).join(", "); warning( `Java ${javaVersion} is not a Long-Term Support (LTS) version. ` + - `veraPDF officially supports LTS versions (8, 11, 17, 21, 25, ...). ` + + `veraPDF ${kDefaultVersion} officially supports Java ${supportedVersions}. ` + + `Installation will proceed, but you may encounter issues.`, + ); + } else if (javaVersion > kMaxSupportedLtsVersion) { + warning( + `Java ${javaVersion} is newer than veraPDF ${kDefaultVersion} officially supports. ` + `Installation will proceed, but you may encounter issues.`, ); }