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 0000000..98b8a3b --- /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 00ff30e..64056b7 100644 --- a/src/main/java/org/spdx/tools/Verify.java +++ b/src/main/java/org/spdx/tools/Verify.java @@ -48,27 +48,47 @@ /** * Verifies an SPDX document and lists any verification errors + *
+ * Exit codes: + * * @author Gary O'Neall */ public class Verify { static final int MIN_ARGS = 1; static final int MAX_ARGS = 2; - 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"; - + 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) { + 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, 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"); - System.exit(ERROR_STATUS); + return ExitCode.USAGE_ERROR; } if (args.length > MAX_ARGS) { System.out.println("Warning: Extra arguments will be ignored"); @@ -82,7 +102,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 ExitCode.USAGE_ERROR; } } else { fileType = SpdxToolsHelper.fileToFileType(new File(args[0])); @@ -90,10 +110,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 ExitCode.ERROR; } catch (InvalidFileNameException e) { System.err.println("Invalid file name: "+args[0]); - System.exit(ERROR_STATUS); + return ExitCode.USAGE_ERROR; } // separate out the warning from errors List warnings = new ArrayList<>(); @@ -120,8 +140,9 @@ public static void main(String[] args) { } if (errors.isEmpty()) { System.out.println("This SPDX Document is valid."); + return ExitCode.SUCCESS; } else { - System.exit(ERROR_STATUS); + return ExitCode.ERROR; } }