diff --git a/src/main/java/org/dataone/hashstore/exceptions/NonMatchingChecksumException.java b/src/main/java/org/dataone/hashstore/exceptions/NonMatchingChecksumException.java index 3704144e..3bc23c4b 100644 --- a/src/main/java/org/dataone/hashstore/exceptions/NonMatchingChecksumException.java +++ b/src/main/java/org/dataone/hashstore/exceptions/NonMatchingChecksumException.java @@ -1,13 +1,21 @@ package org.dataone.hashstore.exceptions; +import java.util.Map; + /** * An exception thrown when a checksum does not match what is expected. */ public class NonMatchingChecksumException extends IllegalArgumentException { - public NonMatchingChecksumException(String message) { + private final Map hexDigests; + + public NonMatchingChecksumException(String message, Map checksumMap) { super(message); + this.hexDigests = checksumMap; } + public Map getHexDigests() { + return hexDigests; + } } diff --git a/src/main/java/org/dataone/hashstore/filehashstore/FileHashStore.java b/src/main/java/org/dataone/hashstore/filehashstore/FileHashStore.java index 4bcccf95..5ec02dec 100644 --- a/src/main/java/org/dataone/hashstore/filehashstore/FileHashStore.java +++ b/src/main/java/org/dataone/hashstore/filehashstore/FileHashStore.java @@ -859,7 +859,7 @@ public void deleteIfInvalidObject( + ". Actual checksum calculated: " + digestFromHexDigests + " (algorithm: " + checksumAlgorithm + ")"; logFileHashStore.error(errMsg); - throw new NonMatchingChecksumException(errMsg); + throw new NonMatchingChecksumException(errMsg, hexDigests); } // Validate size if (objInfoRetrievedSize != objSize) { @@ -1258,6 +1258,7 @@ protected void validateTmpObject( } if (compareChecksum) { + FileHashStoreUtility.ensureNotNull(hexDigests, "hexDigests"); logFileHashStore.info("Validating object, checksum arguments supplied and valid."); String digestFromHexDigests = hexDigests.get(checksumAlgorithm); if (digestFromHexDigests == null) { @@ -1269,7 +1270,7 @@ protected void validateTmpObject( String errMsg = baseErrMsg + ". Failed to delete tmpFile: " + tmpFile + ". " + ge.getMessage(); logFileHashStore.error(errMsg); - throw new NonMatchingChecksumException(errMsg); + throw new NonMatchingChecksumException(errMsg, hexDigests); } String errMsg = baseErrMsg + ". tmpFile has been deleted: " + tmpFile; logFileHashStore.error(errMsg); @@ -1285,12 +1286,12 @@ protected void validateTmpObject( String errMsg = baseErrMsg + ". Failed to delete tmpFile: " + tmpFile + ". " + ge.getMessage(); logFileHashStore.error(errMsg); - throw new NonMatchingChecksumException(errMsg); + throw new NonMatchingChecksumException(errMsg, hexDigests); } String errMsg = baseErrMsg + ". tmpFile has been deleted: " + tmpFile; logFileHashStore.error(errMsg); - throw new NonMatchingChecksumException(errMsg); + throw new NonMatchingChecksumException(errMsg, hexDigests); } } } diff --git a/src/main/java/org/dataone/hashstore/hashstoreconverter/FileHashStoreLinks.java b/src/main/java/org/dataone/hashstore/hashstoreconverter/FileHashStoreLinks.java index 8a959592..977245f0 100644 --- a/src/main/java/org/dataone/hashstore/hashstoreconverter/FileHashStoreLinks.java +++ b/src/main/java/org/dataone/hashstore/hashstoreconverter/FileHashStoreLinks.java @@ -94,13 +94,14 @@ public ObjectMetadata storeHardLink( try (InputStream fileStream = Files.newInputStream(filePath)) { Map hexDigests = generateChecksums(fileStream, checksumAlgorithm); + FileHashStoreUtility.ensureNotNull(hexDigests, "hexDigests"); String checksumToMatch = hexDigests.get(checksumAlgorithm); if (!checksum.equalsIgnoreCase(checksumToMatch)) { String errMsg = "Checksum supplied: " + checksum + " does not match what has been" + " calculated: " + checksumToMatch + " for pid: " + pid + " and checksum" + " algorithm: " + checksumAlgorithm; logFileHashStoreLinks.error(errMsg); - throw new NonMatchingChecksumException(errMsg); + throw new NonMatchingChecksumException(errMsg, hexDigests); } // Gather the elements to form the permanent address diff --git a/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreInterfaceTest.java b/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreInterfaceTest.java index 7bc157fb..32cc50d3 100644 --- a/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreInterfaceTest.java +++ b/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreInterfaceTest.java @@ -365,7 +365,7 @@ public void storeObject_correctChecksumValue() throws Exception { */ @Test public void storeObject_incorrectChecksumValue() { - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(NonMatchingChecksumException.class, () -> { // Get test file to "upload" String pid = "jtao.1700.1"; Path testDataFile = testData.getTestFile(pid); @@ -379,6 +379,39 @@ public void storeObject_incorrectChecksumValue() { }); } + /** + * Verify exception contains hexDigests when NonMatchingChecksumException is thrown + */ + @Test + public void storeObject_nonMatchingChecksumException_hexDigestsIncluded() throws Exception { + // Get test file to "upload" + String pid = "jtao.1700.1"; + Path testDataFile = testData.getTestFile(pid); + + String checksumIncorrect = + "aaf9b6c88f1f458e410c30c351c6384ea42ac1b5ee1f8430d3e365e43b78a38a"; + + try (InputStream dataStream = Files.newInputStream(testDataFile)) { + try { + fileHashStore.storeObject(dataStream, pid, null, checksumIncorrect, "SHA-256", -1); + + } catch (NonMatchingChecksumException nmce) { + Map hexDigestsRetrieved = nmce.getHexDigests(); + + String md5 = testData.pidData.get(pid).get("md5"); + String sha1 = testData.pidData.get(pid).get("sha1"); + String sha256 = testData.pidData.get(pid).get("sha256"); + String sha384 = testData.pidData.get(pid).get("sha384"); + String sha512 = testData.pidData.get(pid).get("sha512"); + assertEquals(md5, hexDigestsRetrieved.get("MD5")); + assertEquals(sha1, hexDigestsRetrieved.get("SHA-1")); + assertEquals(sha256, hexDigestsRetrieved.get("SHA-256")); + assertEquals(sha384, hexDigestsRetrieved.get("SHA-384")); + assertEquals(sha512, hexDigestsRetrieved.get("SHA-512")); + } + } + } + /** * Verify exception thrown when checksum is empty and algorithm supported */ diff --git a/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreProtectedTest.java b/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreProtectedTest.java index 0bd99379..742b37a7 100644 --- a/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreProtectedTest.java +++ b/src/test/java/org/dataone/hashstore/filehashstore/FileHashStoreProtectedTest.java @@ -643,8 +643,8 @@ public void validateTmpObject_validationRequested_matchingChecksum() throws Exce } /** - * Confirm validateTmpObject does not throw exception when requested to validate checksums with - * good values, and that the tmpFile passed is deleted. + * Confirm validateTmpObject throws exception when requested to validate a bad checksum, + * and that the tmpFile passed is deleted. */ @Test public void validateTmpObject_validationRequested_nonMatchingChecksum() throws Exception { @@ -676,6 +676,18 @@ public void validateTmpObject_validationRequested_algoNotFound() throws Exceptio assertFalse(Files.exists(tmpFile.toPath())); } + /** + * Confirm validateTmpObject throws exception when hexDigests provided is null + */ + @Test + public void validateTmpObject_validationRequested_hexDigestsNull() throws Exception { + File tmpFile = generateTemporaryFile(); + + assertThrows(IllegalArgumentException.class, + () -> fileHashStore.validateTmpObject(true, "md2Digest", "MD2", tmpFile, null, + -1)); + } + /** * Check algorithm support for supported algorithm */