From 83fabbe3f9423ca605134c7eecfeb26585f5a5e9 Mon Sep 17 00:00:00 2001 From: Arthit Suriyawongkul Date: Thu, 16 Jul 2026 13:57:23 +0100 Subject: [PATCH 1/5] Extract Verify main() logic into testable run() method run() returns an exit-status int instead of calling System.exit() directly. No behavior change. Signed-off-by: Arthit Suriyawongkul --- src/main/java/org/spdx/tools/Verify.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/spdx/tools/Verify.java b/src/main/java/org/spdx/tools/Verify.java index 00ff30e3..6c1fec57 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -65,10 +65,20 @@ public class Verify { * @param args args[0] SPDX file path; args[1] [RDFXML|JSON|XLS|XLSX|YAML|TAG] an optional file type - if not present, file type of the to file will be used */ public static void main(String[] args) { + System.exit(run(args)); + } + + /** + * Runs the Verify command logic and reports results to standard out/error, + * without terminating the JVM - allows the logic to be unit tested. + * @param args args[0] SPDX file path; args[1] [RDFXML|JSON|XLS|XLSX|YAML|TAG] an optional file type - if not present, file type of the to file will be used + * @return process exit status + */ + static int run(String[] args) { if (args.length < MIN_ARGS) { System.err .println("Usage:\n Verify file\nwhere file is the file path to an SPDX file"); - System.exit(ERROR_STATUS); + return ERROR_STATUS; } if (args.length > MAX_ARGS) { System.out.println("Warning: Extra arguments will be ignored"); @@ -82,7 +92,7 @@ public static void main(String[] args) { fileType = SpdxToolsHelper.strToFileType(args[1]); } catch (Exception ex) { System.err.println("Invalid file type: "+args[1]); - System.exit(ERROR_STATUS); + return ERROR_STATUS; } } else { fileType = SpdxToolsHelper.fileToFileType(new File(args[0])); @@ -90,10 +100,10 @@ public static void main(String[] args) { verify = verify(args[0], fileType); } catch (SpdxVerificationException e) { System.out.println(e.getMessage()); - System.exit(ERROR_STATUS); + return ERROR_STATUS; } catch (InvalidFileNameException e) { System.err.println("Invalid file name: "+args[0]); - System.exit(ERROR_STATUS); + return ERROR_STATUS; } // separate out the warning from errors List warnings = new ArrayList<>(); @@ -120,8 +130,9 @@ public static void main(String[] args) { } if (errors.isEmpty()) { System.out.println("This SPDX Document is valid."); + return 0; } else { - System.exit(ERROR_STATUS); + return ERROR_STATUS; } } From cf4b163d71e2b94dcef18094e280789718683501 Mon Sep 17 00:00:00 2001 From: Arthit Suriyawongkul Date: Thu, 16 Jul 2026 13:58:06 +0100 Subject: [PATCH 2/5] Add distinct exit code for Verify CLI usage errors USAGE_ERROR_STATUS=2 for bad invocation (missing args, invalid file type, invalid file name); ERROR_STATUS=1 stays for invalid or unreadable SPDX documents. Signed-off-by: Arthit Suriyawongkul --- src/main/java/org/spdx/tools/Verify.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/spdx/tools/Verify.java b/src/main/java/org/spdx/tools/Verify.java index 6c1fec57..2a6fdec1 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -48,6 +48,13 @@ /** * Verifies an SPDX document and lists any verification errors + *
+ * Exit codes: + *
    + *
  • 0 - the SPDX document is valid
  • + *
  • 1 - the SPDX document is invalid, or could not be read/parsed
  • + *
  • 2 - the command was invoked incorrectly (missing/invalid arguments)
  • + *
* @author Gary O'Neall */ public class Verify { @@ -55,6 +62,7 @@ public class Verify { static final int MIN_ARGS = 1; static final int MAX_ARGS = 2; static final int ERROR_STATUS = 1; + static final int USAGE_ERROR_STATUS = 2; public static final String JSON_SCHEMA_RESOURCE_V2_3 = "resources/spdx-schema-v2.3.json"; public static final String JSON_SCHEMA_RESOURCE_V2_2 = "resources/spdx-schema-v2.2.json"; public static final String JSON_SCHEMA_RESOURCE_V3 = "resources/spdx-schema-v3.0.1.json"; @@ -72,13 +80,13 @@ public static void main(String[] args) { * Runs the Verify command logic and reports results to standard out/error, * without terminating the JVM - allows the logic to be unit tested. * @param args args[0] SPDX file path; args[1] [RDFXML|JSON|XLS|XLSX|YAML|TAG] an optional file type - if not present, file type of the to file will be used - * @return process exit status + * @return process exit status - 0 valid, {@link #ERROR_STATUS} invalid document, {@link #USAGE_ERROR_STATUS} invalid usage */ static int run(String[] args) { if (args.length < MIN_ARGS) { System.err .println("Usage:\n Verify file\nwhere file is the file path to an SPDX file"); - return ERROR_STATUS; + return USAGE_ERROR_STATUS; } if (args.length > MAX_ARGS) { System.out.println("Warning: Extra arguments will be ignored"); @@ -92,7 +100,7 @@ static int run(String[] args) { fileType = SpdxToolsHelper.strToFileType(args[1]); } catch (Exception ex) { System.err.println("Invalid file type: "+args[1]); - return ERROR_STATUS; + return USAGE_ERROR_STATUS; } } else { fileType = SpdxToolsHelper.fileToFileType(new File(args[0])); @@ -103,7 +111,7 @@ static int run(String[] args) { return ERROR_STATUS; } catch (InvalidFileNameException e) { System.err.println("Invalid file name: "+args[0]); - return ERROR_STATUS; + return USAGE_ERROR_STATUS; } // separate out the warning from errors List warnings = new ArrayList<>(); From f2ca04ac5b78803c94f066fa39b19c06b92d0717 Mon Sep 17 00:00:00 2001 From: Arthit Suriyawongkul Date: Thu, 16 Jul 2026 14:43:47 +0100 Subject: [PATCH 3/5] Add shared ExitCode class, adopt in Verify Signed-off-by: Arthit Suriyawongkul --- src/main/java/org/spdx/tools/ExitCode.java | 43 ++++++++++++++++++++++ src/main/java/org/spdx/tools/Verify.java | 22 +++++++---- 2 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/spdx/tools/ExitCode.java diff --git a/src/main/java/org/spdx/tools/ExitCode.java b/src/main/java/org/spdx/tools/ExitCode.java new file mode 100644 index 00000000..98b8a3b3 --- /dev/null +++ b/src/main/java/org/spdx/tools/ExitCode.java @@ -0,0 +1,43 @@ +/** + * SPDX-FileCopyrightText: 2026 SPDX Contributors + * SPDX-FileType: SOURCE + * SPDX-License-Identifier: Apache-2.0 + */ +package org.spdx.tools; + +/** + * Shared process exit status codes for the command line tools. + *
+ * Individual tools are free to only use a subset of these - e.g. a tool + * with no document-level validity concept may only ever return + * {@link #SUCCESS} or {@link #ERROR}. + *
+ * Values match the {@code CommandLine.ExitCode} constants used by + * picocli, a common Java CLI framework + * ({@code OK=0}, {@code SOFTWARE=1}, {@code USAGE=2}). + * + * @author Arthit Suriyawongkul + */ +public class ExitCode { + + private ExitCode() { + // Static constants only, no instances + } + + /** + * The command completed successfully. + */ + public static final int SUCCESS = 0; + + /** + * The command failed - e.g. the SPDX document is invalid, or could + * not be read/parsed. + */ + public static final int ERROR = 1; + + /** + * The command was invoked incorrectly - e.g. missing or invalid + * arguments. + */ + public static final int USAGE_ERROR = 2; +} diff --git a/src/main/java/org/spdx/tools/Verify.java b/src/main/java/org/spdx/tools/Verify.java index 2a6fdec1..c6273404 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -61,8 +61,11 @@ public class Verify { static final int MIN_ARGS = 1; static final int MAX_ARGS = 2; + /** + * @deprecated unused - retained for compatibility, use {@link ExitCode} instead + */ + @Deprecated static final int ERROR_STATUS = 1; - static final int USAGE_ERROR_STATUS = 2; public static final String JSON_SCHEMA_RESOURCE_V2_3 = "resources/spdx-schema-v2.3.json"; public static final String JSON_SCHEMA_RESOURCE_V2_2 = "resources/spdx-schema-v2.2.json"; public static final String JSON_SCHEMA_RESOURCE_V3 = "resources/spdx-schema-v3.0.1.json"; @@ -70,6 +73,8 @@ public class Verify { static final ObjectMapper JSON_MAPPER = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); /** + * Main entry point for the Verify tool + * * @param args args[0] SPDX file path; args[1] [RDFXML|JSON|XLS|XLSX|YAML|TAG] an optional file type - if not present, file type of the to file will be used */ public static void main(String[] args) { @@ -79,14 +84,15 @@ public static void main(String[] args) { /** * Runs the Verify command logic and reports results to standard out/error, * without terminating the JVM - allows the logic to be unit tested. + * * @param args args[0] SPDX file path; args[1] [RDFXML|JSON|XLS|XLSX|YAML|TAG] an optional file type - if not present, file type of the to file will be used - * @return process exit status - 0 valid, {@link #ERROR_STATUS} invalid document, {@link #USAGE_ERROR_STATUS} invalid usage + * @return process exit status, see {@link ExitCode} */ static int run(String[] args) { if (args.length < MIN_ARGS) { System.err .println("Usage:\n Verify file\nwhere file is the file path to an SPDX file"); - return USAGE_ERROR_STATUS; + return ExitCode.USAGE_ERROR; } if (args.length > MAX_ARGS) { System.out.println("Warning: Extra arguments will be ignored"); @@ -100,7 +106,7 @@ static int run(String[] args) { fileType = SpdxToolsHelper.strToFileType(args[1]); } catch (Exception ex) { System.err.println("Invalid file type: "+args[1]); - return USAGE_ERROR_STATUS; + return ExitCode.USAGE_ERROR; } } else { fileType = SpdxToolsHelper.fileToFileType(new File(args[0])); @@ -108,10 +114,10 @@ static int run(String[] args) { verify = verify(args[0], fileType); } catch (SpdxVerificationException e) { System.out.println(e.getMessage()); - return ERROR_STATUS; + return ExitCode.ERROR; } catch (InvalidFileNameException e) { System.err.println("Invalid file name: "+args[0]); - return USAGE_ERROR_STATUS; + return ExitCode.USAGE_ERROR; } // separate out the warning from errors List warnings = new ArrayList<>(); @@ -138,9 +144,9 @@ static int run(String[] args) { } if (errors.isEmpty()) { System.out.println("This SPDX Document is valid."); - return 0; + return ExitCode.SUCCESS; } else { - return ERROR_STATUS; + return ExitCode.ERROR; } } From a719d2523f8c2a6d6a7419beb8ae0d328ca6e9ef Mon Sep 17 00:00:00 2001 From: Arthit Suriyawongkul Date: Sun, 19 Jul 2026 09:34:26 +0100 Subject: [PATCH 4/5] Remove ERROR_STATUS Signed-off-by: Arthit Suriyawongkul --- src/main/java/org/spdx/tools/Verify.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/spdx/tools/Verify.java b/src/main/java/org/spdx/tools/Verify.java index c6273404..54d9930e 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -61,11 +61,6 @@ public class Verify { static final int MIN_ARGS = 1; static final int MAX_ARGS = 2; - /** - * @deprecated unused - retained for compatibility, use {@link ExitCode} instead - */ - @Deprecated - static final int ERROR_STATUS = 1; public static final String JSON_SCHEMA_RESOURCE_V2_3 = "resources/spdx-schema-v2.3.json"; public static final String JSON_SCHEMA_RESOURCE_V2_2 = "resources/spdx-schema-v2.2.json"; public static final String JSON_SCHEMA_RESOURCE_V3 = "resources/spdx-schema-v3.0.1.json"; From a55c9b322a9e16d7a67dc5156091e440e53285ce Mon Sep 17 00:00:00 2001 From: Arthit Suriyawongkul Date: Sun, 19 Jul 2026 09:53:03 +0100 Subject: [PATCH 5/5] Update Verify.java Signed-off-by: Arthit Suriyawongkul --- src/main/java/org/spdx/tools/Verify.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/spdx/tools/Verify.java b/src/main/java/org/spdx/tools/Verify.java index 54d9930e..64056b7a 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -61,12 +61,13 @@ public class Verify { static final int MIN_ARGS = 1; static final int MAX_ARGS = 2; + public static final String JSON_SCHEMA_RESOURCE_V2_3 = "resources/spdx-schema-v2.3.json"; public static final String JSON_SCHEMA_RESOURCE_V2_2 = "resources/spdx-schema-v2.2.json"; public static final String JSON_SCHEMA_RESOURCE_V3 = "resources/spdx-schema-v3.0.1.json"; - + static final ObjectMapper JSON_MAPPER = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); - + /** * Main entry point for the Verify tool *