Skip to content

Commit

Permalink
Add public API method 'getHexDigest()' plus new junit tests and clean…
Browse files Browse the repository at this point in the history
… up code
  • Loading branch information
doulikecookiedough committed Jun 29, 2023
1 parent 9ac1933 commit ff7135a
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 95 deletions.
10 changes: 5 additions & 5 deletions src/main/java/org/dataone/hashstore/HashAddress.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
* know the underlying file system details.
*/
public class HashAddress {
private String id;
private String relPath;
private Path absPath;
private boolean isDuplicate;
private Map<String, String> hexDigests;
private final String id;
private final String relPath;
private final Path absPath;
private final boolean isDuplicate;
private final Map<String, String> hexDigests;

/**
* Creates a new instance of HashAddress with the given properties.
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/org/dataone/hashstore/HashStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ String storeMetadata(InputStream metadata, String pid, String formatId)
* @throws FileNotFoundException When requested pid has no associated object
* @throws IOException I/O error when creating InputStream to
* object
* @throws NoSuchAlgorithmException When algorithm used to calcualte object
* @throws NoSuchAlgorithmException When algorithm used to calculate object
* address is not supported
*/
InputStream retrieveObject(String pid)
Expand All @@ -123,21 +123,21 @@ InputStream retrieveObject(String pid)
* associated object
* @throws IOException I/O error when creating InputStream to
* metadata
* @throws NoSuchAlgorithmException When algorithm used to calcualte metadata
* @throws NoSuchAlgorithmException When algorithm used to calculate metadata
* address is not supported
*/
InputStream retrieveMetadata(String pid, String formatId) throws Exception;

/**
* The 'deleteObject' method deletes an object permanently from disk using a
* given persistent identifier and any empty subdirecetories.
* given persistent identifier and any empty subdirectories.
*
* @param pid Authority-based identifier
* @return
* @return True if successful
* @throws IllegalArgumentException When pid is null or empty
* @throws FileNotFoundException When requested pid has no associated object
* @throws IOException I/O error when deleting empty directories
* @throws NoSuchAlgorithmException When algorithm used to calcualte object
* @throws NoSuchAlgorithmException When algorithm used to calculate object
* address is not supported
*/
boolean deleteObject(String pid) throws Exception;
Expand All @@ -149,11 +149,11 @@ InputStream retrieveObject(String pid)
*
* @param pid Authority-based identifier
* @param formatId Metadata namespace/format
* @return
* @return True if successfulÏ
* @throws IllegalArgumentException When pid or formatId is null or empty
* @throws FileNotFoundException When requested pid has no metadata
* @throws IOException I/O error when deleting empty directories
* @throws NoSuchAlgorithmException When algorithm used to calcualte object
* @throws NoSuchAlgorithmException When algorithm used to calculate object
* address is not supported
*/
boolean deleteMetadata(String pid, String formatId) throws Exception;
Expand All @@ -164,8 +164,12 @@ InputStream retrieveObject(String pid)
*
* @param pid Authority-based identifier
* @param algorithm Algorithm of desired hex digest
* @return
* @throws Exception TODO: Add specific exceptions
* @return String hex digest of requested pid
* @throws IllegalArgumentException When pid or formatId is null or empty
* @throws FileNotFoundException When requested pid object does not exist
* @throws IOException I/O error when calculating hex digests
* @throws NoSuchAlgorithmException When algorithm used to calculate object
* address is not supported
*/
String getHexDigest(String pid, String algorithm) throws Exception;
}
4 changes: 2 additions & 2 deletions src/main/java/org/dataone/hashstore/HashStoreFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public class HashStoreFactory {
* (int)
* storeAlgorithm
*
* @return
* @throws HashStoreFactoryException When HashStore fails to initialize due to
* @return HashStore instance ready to store objects and metadata
* @throws HashStoreFactoryException When HashStore failÏs to initialize due to
* permissions or class-related issues
* @throws IOException When there is an issue with properties
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ protected void checkConfigurationEquality(String propertyName, Object suppliedVa
* @param storeWidth Width of store
* @param storeAlgorithm Algorithm to use to calculate the hex digest
* for the
* permanent address of a data sobject
* permanent address of a data object
* @param storeMetadataNamespace default formatId of hashstore metadata
* @return String that representing the contents of 'hashstore.yaml'
*/
Expand Down Expand Up @@ -533,7 +533,7 @@ public InputStream retrieveObject(String pid)
}

// Get permanent address of the pid by calculating its sha-256 hex digest
String objectCid = this.getPidHexDigest(pid, OBJECT_STORE_ALGORITHM);
String objectCid = this.getPidHexDigest(pid, this.OBJECT_STORE_ALGORITHM);
String objShardString = this.getHierarchicalPathString(this.DIRECTORY_DEPTH, this.DIRECTORY_WIDTH,
objectCid);
Path objHashAddressPath = this.OBJECT_STORE_DIRECTORY.resolve(objShardString);
Expand Down Expand Up @@ -579,7 +579,7 @@ public InputStream retrieveMetadata(String pid, String formatId) throws Exceptio
}

// Get permanent address of the pid by calculating its sha-256 hex digest
String metadataCid = this.getPidHexDigest(pid + formatId, OBJECT_STORE_ALGORITHM);
String metadataCid = this.getPidHexDigest(pid + formatId, this.OBJECT_STORE_ALGORITHM);
String metadataShardString = this.getHierarchicalPathString(this.DIRECTORY_DEPTH, this.DIRECTORY_WIDTH,
metadataCid);
Path metadataHashAddressPath = this.METADATA_STORE_DIRECTORY.resolve(metadataShardString);
Expand Down Expand Up @@ -620,7 +620,7 @@ public boolean deleteObject(String pid)
}

// Get permanent address of the pid by calculating its sha-256 hex digest
String objectCid = this.getPidHexDigest(pid, OBJECT_STORE_ALGORITHM);
String objectCid = this.getPidHexDigest(pid, this.OBJECT_STORE_ALGORITHM);
String objShardString = this.getHierarchicalPathString(this.DIRECTORY_DEPTH, this.DIRECTORY_WIDTH,
objectCid);
Path objHashAddressPath = this.OBJECT_STORE_DIRECTORY.resolve(objShardString);
Expand Down Expand Up @@ -673,7 +673,7 @@ public boolean deleteMetadata(String pid, String formatId)
}

// Get permanent address of the pid by calculating its sha-256 hex digest
String metadataCid = this.getPidHexDigest(pid + formatId, OBJECT_STORE_ALGORITHM);
String metadataCid = this.getPidHexDigest(pid + formatId, this.OBJECT_STORE_ALGORITHM);
String metadataCidShardString = this.getHierarchicalPathString(this.DIRECTORY_DEPTH, this.DIRECTORY_WIDTH,
metadataCid);
Path metadataCidPath = this.METADATA_STORE_DIRECTORY.resolve(metadataCidShardString);
Expand Down Expand Up @@ -710,9 +710,57 @@ public boolean deleteMetadata(String pid, String formatId)
}

@Override
public String getHexDigest(String pid, String algorithm) throws Exception {
// TODO: Implement method
return null;
public String getHexDigest(String pid, String algorithm)
throws NoSuchAlgorithmException, FileNotFoundException, IOException {
logFileHashStore.debug("FileHashStore.getHexDigest - Called to calculate hex digest for pid: " + pid);

if (pid == null || pid.trim().isEmpty()) {
String errMsg = "FileHashStore.getHexDigest - pid cannot be null or empty, pid: " + pid;
logFileHashStore.error(errMsg);
throw new IllegalArgumentException(errMsg);
}
this.validateAlgorithm(algorithm);

// Get permanent address of the pid by calculating its sha-256 hex digest
String objectCid = this.getPidHexDigest(pid, this.OBJECT_STORE_ALGORITHM);
String objShardString = this.getHierarchicalPathString(this.DIRECTORY_DEPTH, this.DIRECTORY_WIDTH,
objectCid);
Path objHashAddressPath = this.OBJECT_STORE_DIRECTORY.resolve(objShardString);

// Check to see if object exists
if (!Files.exists(objHashAddressPath)) {
String errMsg = "FileHashStore.getHexDigest - File does not exist for pid: " + pid
+ " with object address: " + objHashAddressPath;
logFileHashStore.warn(errMsg);
throw new FileNotFoundException(errMsg);
}

// If so, calculate hex digest/checksum
MessageDigest mdObject = MessageDigest.getInstance(algorithm);
try {
InputStream dataStream = Files.newInputStream(objHashAddressPath);
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = dataStream.read(buffer)) != -1) {
mdObject.update(buffer, 0, bytesRead);

}
// Close datastream
dataStream.close();

} catch (IOException ioe) {
String errMsg = "FileHashStore.getHexDigest - Unexpected IOException encountered: "
+ ioe.getMessage();
logFileHashStore.error(errMsg);
throw ioe;

}

String mdObjectHexDigest = DatatypeConverter.printHexBinary(mdObject.digest()).toLowerCase();
logFileHashStore
.info("FileHashStore.getHexDigest - Hex digest calculated for pid: " + pid + ", with hex digest value: "
+ mdObjectHexDigest);
return mdObjectHexDigest;
}

/**
Expand Down
Loading

0 comments on commit ff7135a

Please sign in to comment.