diff --git a/src/main/java/gov/nasa/pds/tools/label/LocationValidator.java b/src/main/java/gov/nasa/pds/tools/label/LocationValidator.java index 9afb0c08c..31a87e3a9 100644 --- a/src/main/java/gov/nasa/pds/tools/label/LocationValidator.java +++ b/src/main/java/gov/nasa/pds/tools/label/LocationValidator.java @@ -72,6 +72,7 @@ public class LocationValidator { private RuleContext ruleContext; private String validationRule; private String labelExtension; + private String pdfErrorDir; /* * Sets the report object in BundleManager static class. @@ -430,10 +431,13 @@ public void setRule(String ruleName) { } public void setEveryN(int value) { - ruleContext.setEveryN(value); + ruleContext.setEveryN(value); } public void setSpotCheckData(int value) { - ruleContext.setSpotCheckData(value); + ruleContext.setSpotCheckData(value); + } + public void setPDFErrorDir(String dir) { + ruleContext.setPDFErrorDir(dir); } public void setAllowUnlabeledFiles(boolean flag) { diff --git a/src/main/java/gov/nasa/pds/tools/util/PDFUtil.java b/src/main/java/gov/nasa/pds/tools/util/PDFUtil.java index fcd6efe7f..a9daf906e 100644 --- a/src/main/java/gov/nasa/pds/tools/util/PDFUtil.java +++ b/src/main/java/gov/nasa/pds/tools/util/PDFUtil.java @@ -49,12 +49,15 @@ public URL getTarget() { return (this.target); } - private synchronized void writeErrorToFile(URI uri, ValidationResult result, String flavor) { + private synchronized void writeErrorToFile(String baseDir, URI uri, ValidationResult result, String flavor) { + // Ignore the write if baseDir has not been given + if (baseDir.isEmpty()) return; + // Write to an external file with ".error" appended to file name in user's // default directory the content of result. // Build the external filename and save it for other to access. - this.externalErrorFilename = System.getProperty("user.dir") + File.separator + this.externalErrorFilename = baseDir + File.separator + FilenameUtils.getName(uri.getPath()) + "." + flavor + ".error.csv"; LOG.debug("writeErrorToFile:uri,this.externalErrorFilename {},{}", uri, @@ -99,7 +102,7 @@ private synchronized void writeErrorToFile(URI uri, ValidationResult result, Str } } - private boolean validatePDF(URI uri, String pdfRef) throws IOException { + private boolean validatePDF(String baseDir, URI uri, String pdfRef) throws IOException { boolean pdfValidateFlag = false; try { @@ -130,7 +133,7 @@ private boolean validatePDF(URI uri, String pdfRef) throws IOException { // Write the result to external file so the user can look over in the validate // report. - this.writeErrorToFile(uri, result, parser.getFlavour().getId()); + this.writeErrorToFile(baseDir, uri, result, parser.getFlavour().getId()); this.errorMessage = "Validation failed for flavour PDF/A-" + detectedFlavour.getId() + ". Detailed error output can be found at " + this.getExternalErrorFilename(); @@ -151,7 +154,7 @@ private boolean validatePDF(URI uri, String pdfRef) throws IOException { * @return true if the PDF is PDF/A compliant, and false otherwise * */ - public synchronized boolean validateFileStandardConformity(String pdfBase, URL parentURL) + public synchronized boolean validateFileStandardConformity(String baseDir, String pdfBase, URL parentURL) throws Exception { // Do the validation of the PDF document. // https://verapdf.org/category/software/ @@ -188,7 +191,7 @@ public synchronized boolean validateFileStandardConformity(String pdfBase, URL p // First, validate the PDF against PDFAFlavour.PDFA_1_A, if it does not // validate, do it again with PDFAFlavour.PDFA_1_B - pdfValidateFlag = this.validatePDF(uri, pdfRef); + pdfValidateFlag = this.validatePDF(baseDir, uri, pdfRef); LOG.debug("validateFileStandardConformity:pdfRef,pdfValidateFlag [{}],{}", parent, pdfValidateFlag); diff --git a/src/main/java/gov/nasa/pds/tools/validate/rule/RuleContext.java b/src/main/java/gov/nasa/pds/tools/validate/rule/RuleContext.java index d0ab99ebf..e2b4037ab 100644 --- a/src/main/java/gov/nasa/pds/tools/validate/rule/RuleContext.java +++ b/src/main/java/gov/nasa/pds/tools/validate/rule/RuleContext.java @@ -122,6 +122,10 @@ public class RuleContext extends ContextBase { * The key used to indicate how many lines or records to skip during content validation. */ public static final String EVERY_N_KEY = "validate.every-n"; + /** + * Property to specify directory for PDF error directory. + */ + public static final String PDF_ERROR_DIR = "validate.pdfErrorDir"; /** * The key used to indicate how many lines or records to skip during content validation. */ @@ -404,6 +408,13 @@ public int getEveryN() { public void setEveryN(int value) { putContextValue(EVERY_N_KEY, value); } + public String getPDFErrorDir() { + return getContextValue(PDF_ERROR_DIR, String.class) == null ? "" : getContextValue(PDF_ERROR_DIR, String.class); + } + + public void setPDFErrorDir(String dir) { + putContextValue(PDF_ERROR_DIR, dir); + } public int getSpotCheckData() { return getContextValue(SPOT_CHECK_DATA_KEY, Integer.class); diff --git a/src/main/java/gov/nasa/pds/tools/validate/rule/pds4/FileReferenceValidationRule.java b/src/main/java/gov/nasa/pds/tools/validate/rule/pds4/FileReferenceValidationRule.java index fa280a1a1..6c5ea3b63 100644 --- a/src/main/java/gov/nasa/pds/tools/validate/rule/pds4/FileReferenceValidationRule.java +++ b/src/main/java/gov/nasa/pds/tools/validate/rule/pds4/FileReferenceValidationRule.java @@ -727,7 +727,7 @@ private void handlePDF(ValidationTarget target, URL fileRef, TinyNodeImpl fileOb DocumentsChecker check = new DocumentsChecker(); if (check.isMimeTypeCorrect(fileRef.toString(), "PDF/A")) { // The parent is also needed for validateFileStandardConformity function. - pdfValidateFlag = this.pdfUtil.validateFileStandardConformity(pdfName, new URL(parent, directory)); + pdfValidateFlag = this.pdfUtil.validateFileStandardConformity(this.getContext().getPDFErrorDir(), pdfName, new URL(parent, directory)); // Report an error if the PDF file is not PDF/A compliant. if (!pdfValidateFlag) { diff --git a/src/main/java/gov/nasa/pds/validate/ValidateLauncher.java b/src/main/java/gov/nasa/pds/validate/ValidateLauncher.java index d6499f797..9cd2fcd01 100644 --- a/src/main/java/gov/nasa/pds/validate/ValidateLauncher.java +++ b/src/main/java/gov/nasa/pds/validate/ValidateLauncher.java @@ -222,6 +222,8 @@ public class ValidateLauncher { private int everyN; + private String pdfErrorDir; + private int spotCheckData; private boolean allowUnlabeledFiles; @@ -282,7 +284,7 @@ public ValidateLauncher() throws TransformerConfigurationException { deprecatedFlagWarning = false; validateContext = true; checkInbetweenFields = false; - + pdfErrorDir = ""; setLabelExtension(Constants.DEFAULT_LABEL_EXTENSION); this.flushValidators(); @@ -331,6 +333,12 @@ public void query(CommandLine line) throws Exception { throw new InvalidOptionException( "Could not parse value '" + line.getOptionValue("everyN", "1") + "': " + a.getMessage()); } + setPDFErrorDir(line.getOptionValue("pdf-errors", "")); + File dir = new File(pdfErrorDir); + if (!this.pdfErrorDir.isEmpty() && !dir.isDirectory()) { + throw new InvalidOptionException( + "Could not parse dir '" + this.pdfErrorDir + "' as a directory"); + } for (Option o : processedOptions) { LOG.debug("query:o.getOpt() {}", o.getOpt()); @@ -759,6 +767,9 @@ public void query(File configuration) throws ConfigurationException { if (config.containsKey(ConfigKey.EVERY_N)) { setEveryN(config.getInt(ConfigKey.EVERY_N)); } + if (config.containsKey(ConfigKey.PDF_ERROR_DIR)) { + setPDFErrorDir(config.getString(ConfigKey.PDF_ERROR_DIR)); + } if (config.containsKey(ConfigKey.SPOT_CHECK_DATA)) { setSpotCheckData(config.getInt(ConfigKey.SPOT_CHECK_DATA)); } @@ -1069,8 +1080,12 @@ public void setMaxErrors(long value) { } public void setEveryN(int value) { - this.everyN = value; - } + this.everyN = value; + } + + public void setPDFErrorDir(String dir) { + this.pdfErrorDir = dir; + } public void setSpotCheckData(int value) { this.spotCheckData = value; @@ -1306,6 +1321,9 @@ public void setupReport() throws IOException { if (everyN != 1) { report.addParameter(" Data Every N " + everyN); } + if (!pdfErrorDir.isEmpty()) { + report.addParameter(" PDF Error Directory " + pdfErrorDir); + } if (spotCheckData != -1) { report.addParameter(" Data Spot Check " + spotCheckData); } @@ -1383,6 +1401,7 @@ public boolean doValidation(Map checksumManifest) throws Exception validator.setCheckData(contentValidationFlag); validator.setSpotCheckData(spotCheckData); validator.setEveryN(everyN); + validator.setPDFErrorDir(pdfErrorDir); validator.setAllowUnlabeledFiles(allowUnlabeledFiles); validator.setValidateContext(validateContext); validator.setSkipProductValidation(skipProductValidation); diff --git a/src/main/java/gov/nasa/pds/validate/commandline/options/ConfigKey.java b/src/main/java/gov/nasa/pds/validate/commandline/options/ConfigKey.java index f1f1cf99a..466853f13 100644 --- a/src/main/java/gov/nasa/pds/validate/commandline/options/ConfigKey.java +++ b/src/main/java/gov/nasa/pds/validate/commandline/options/ConfigKey.java @@ -116,6 +116,11 @@ public class ConfigKey { */ public static final String EVERY_N = "validate.everyN"; + /** + * Property to specify directory for PDF error directory. + */ + public static final String PDF_ERROR_DIR = "validate.pdfErrorDir"; + /** * Property to specify how many lines or records to skip during content validation. */ diff --git a/src/main/java/gov/nasa/pds/validate/commandline/options/Flag.java b/src/main/java/gov/nasa/pds/validate/commandline/options/Flag.java index cc3721091..2cb2337f3 100644 --- a/src/main/java/gov/nasa/pds/validate/commandline/options/Flag.java +++ b/src/main/java/gov/nasa/pds/validate/commandline/options/Flag.java @@ -104,6 +104,10 @@ public enum Flag { NO_DATA(null, "no-data-check", "DEPRECATED: This option has been renamed to --skip-content-validation to be more consistent with other argument naming."), + PDF_ERROR_DIR(null, "pdf-error-dir", "directory", String.class, + "the directory to put PDF error reports that detail why a PDF file is not compliant that is not included in the standard report " + + "with undefined or empty string meaning the detailed reports are lost"), + /** Flag to disable data content validation. */ SKIP_CONTENT_VALIDATION("D", "skip-content-validation", "Disable product content validation. The tool will skip check the bytes within the content of the data file."), diff --git a/src/main/java/gov/nasa/pds/validate/commandline/options/FlagOptions.java b/src/main/java/gov/nasa/pds/validate/commandline/options/FlagOptions.java index c30a3441c..a04db17dd 100644 --- a/src/main/java/gov/nasa/pds/validate/commandline/options/FlagOptions.java +++ b/src/main/java/gov/nasa/pds/validate/commandline/options/FlagOptions.java @@ -54,6 +54,7 @@ public class FlagOptions { options.addOption(new ToolsOption(Flag.EXTENSION)); options.addOption(new ToolsOption(Flag.EVERY_N)); options.addOption(new ToolsOption(Flag.HELP)); + options.addOption(new ToolsOption(Flag.PDF_ERROR_DIR)); options.addOption(new ToolsOption(Flag.REPORT)); options.addOption(new ToolsOption(Flag.TARGET)); options.addOption(new ToolsOption(Flag.VERBOSE)); diff --git a/src/main/java/gov/nasa/pds/validate/report/JSONReport.java b/src/main/java/gov/nasa/pds/validate/report/JSONReport.java index bb9caee36..bbb6f4f5f 100644 --- a/src/main/java/gov/nasa/pds/validate/report/JSONReport.java +++ b/src/main/java/gov/nasa/pds/validate/report/JSONReport.java @@ -136,6 +136,7 @@ public void printHeader() { for (String parameter : parameters) { String[] tokens = parameter.trim().split("\\s{2,}+", 2); String key = tokens[0].replaceAll("\\s", ""); + System.out.println ("param: " + parameter); this.jsonWriter.name(WordUtils.uncapitalize(key)).value(tokens[1]); } this.jsonWriter.endObject();