Skip to content

Commit

Permalink
Merge pull request #37 from LibraryOfCongress/rewrite_extension
Browse files Browse the repository at this point in the history
merge Rewrite extension
  • Loading branch information
johnscancella committed Mar 11, 2016
2 parents a05c795 + 8070d4e commit 0174692
Show file tree
Hide file tree
Showing 23 changed files with 463 additions and 329 deletions.
44 changes: 37 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ The "new" bagit interface is very intuitive, but here are some easy to follow ex
File folder = new File("FolderYouWantToBag");
StandardSupportedAlgorithms algorithm = StandardSupportedAlgorithms.MD5;
boolean includeHiddenFiles = false;
Bag bag = BagCreator.bagInPlace(folder, algorithm, includeHiddenFiles);
BagCreator creator = new BagCreator();
Bag bag = creator.bagInPlace(folder, algorithm, includeHiddenFiles);
```
##### Read an existing bag (version 0.93 and higher)
```java
File rootDir = new File("RootDirectoryOfExistingBag");
Bag bag = BagReader.read(rootDir);
BagReader reader = new BagReader();
Bag bag = reader.read(rootDir);
```
##### Write a Bag object to disk
```java
Expand All @@ -46,21 +48,50 @@ BagWriter.write(bag, outputDir); //where bag is a Bag object
##### Verify Complete
```java
boolean ignoreHiddenFiles = true;
BagVerifier.isComplete(bag, ignoreHiddenFiles);
BagVerifier verifier = new BagVerifier();
verifier.isComplete(bag, ignoreHiddenFiles);
```
##### Verify Valid
```java
boolean ignoreHiddenFiles = true;
BagVerifier.isValid(bag, ignoreHiddenFiles);
BagVerifier verifier = new BagVerifier();
verifier.isValid(bag, ignoreHiddenFiles);
```
##### Quickly verify by payload-oxum
```java
boolean ignoreHiddenFiles = true;
BagVerifier verifier = new BagVerifier();

if(BagVerifier.canQuickVerify(bag)){
BagVerifier.quicklyVerify(bag, ignoreHiddenFiles);
if(verifier.canQuickVerify(bag)){
verifier.quicklyVerify(bag, ignoreHiddenFiles);
}
```
##### Add other checksum algorithms
You only need to implement 2 interfaces
```java
public class MyNewSupportedAlgorithm implements SupportedAlgorithm {
@Override
public String getMessageDigestName() {
return "SHA3-256";
}
@Override
public String getBagitName() {
return "sha3256";
}
}

public class MyNewNameMapping implements BagitAlgorithmNameToSupportedAlgorithmMapping {
@Override
public SupportedAlgorithm getMessageDigestName(String bagitAlgorithmName) {
if("sha3256".equals(bagitAlgorithmName)){
return new MyNewSupportedAlgorithm();
}

return StandardSupportedAlgorithms.valueOf(bagitAlgorithmName.toUpperCase());
}
}
```
and then add the implemented BagitAlgorithmNameToSupportedAlgorithmMapping class to your BagReader or bagVerifier object before using their methods

## Developing Bagit-Java
Bagit-Java uses [Gradle](https://gradle.org/) for its build system. Check out the great [documentation](https://docs.gradle.org/current/userguide/userguide_single.html) to learn more.
Expand All @@ -80,7 +111,6 @@ Simply run `gradle eclipse` and it will automatically create a eclipse project f
* Further refine reading and writing of bags version 0.93-0.97
* Integrate new proposed specification we are calling "dot bagit"
* Fix bugs/issues reported with new library (on going)
* Add extensions for more than standard supported algorithms

### Support
1. The Digital Curation Google Group (https://groups.google.com/d/forum/digital-curation) is an open discussion list that reaches many of the contributors to and users of this open-source project
Expand Down
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ repositories {
dependencies {
compile 'org.slf4j:slf4j-api:latest.integration'

testCompile 'junit:junit:4.12', 'org.springframework.boot:spring-boot-starter-logging:1.3.2.RELEASE'
testCompile 'junit:junit:latest.integration',
'org.springframework.boot:spring-boot-starter-logging:latest.integration',
'org.bouncycastle:bcprov-jdk15on:latest.integration'
}

test { //show test output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)throws IOE
InputStream inputStream = Files.newInputStream(path, StandardOpenOption.READ);
String hash = Hasher.hash(inputStream, messageDigest);
logger.debug("Adding [{}] to manifest with hash [{}]", path, hash);
manifest.getFileToChecksumMap().put(path.toFile(), hash);
manifest.getFileToChecksumMap().put(path, hash);
}

return FileVisitResult.CONTINUE;
Expand Down
42 changes: 15 additions & 27 deletions src/main/java/gov/loc/repository/bagit/creator/BagCreator.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package gov.loc.repository.bagit.creator;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

Expand Down Expand Up @@ -37,24 +36,26 @@ public class BagCreator {
* @throws IOException if there is a problem writing or moving file(s)
* @return a {@link Bag} object representing the newly created bagit bag
*/
public static Bag bagInPlace(File root, SupportedAlgorithm algorithm, boolean includeHidden) throws NoSuchAlgorithmException, IOException{
public static Bag bagInPlace(Path root, SupportedAlgorithm algorithm, boolean includeHidden) throws NoSuchAlgorithmException, IOException{
Bag bag = new Bag(new Version(0, 97));
bag.setRootDir(root);
logger.info("Creating a bag with version: [{}] in directory: [{}]", bag.getVersion(), root);

File[] files = root.listFiles();
File dataDir = new File(root, "data");
if(!dataDir.exists() && !dataDir.mkdir()){
throw new IOException("Unable to make " + dataDir);
}

moveFilesToDataDir(files, dataDir);
Path dataDir = root.resolve("data");
Files.createDirectory(dataDir);
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(root);
for(Path path : directoryStream){
if(!path.equals(dataDir) && !Files.isHidden(path) || includeHidden){
Files.move(path, dataDir.resolve(path.getFileName()));
}
}

logger.info("Creating payload manifest");
Manifest manifest = new Manifest(algorithm);
MessageDigest messageDigest = MessageDigest.getInstance(algorithm.getMessageDigestName());
AddPayloadToBagManifestVistor visitor = new AddPayloadToBagManifestVistor(manifest, messageDigest, includeHidden);
Files.walkFileTree(Paths.get(dataDir.toURI()), visitor);
Files.walkFileTree(dataDir, visitor);

bag.getPayLoadManifests().add(manifest);
BagWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), root);
Expand All @@ -64,17 +65,6 @@ public static Bag bagInPlace(File root, SupportedAlgorithm algorithm, boolean in
return bag;
}

protected static void moveFilesToDataDir(File[] files, File dataDir) throws IOException{
if(files != null){
logger.info("Moving files to [{}]", dataDir);
for(File file : files){
Path dest = Paths.get(dataDir.getPath(), file.getName());
logger.debug("Moving [{}] to [{}]", file, dest);
Files.move(Paths.get(file.toURI()), dest);
}
}
}

/**
* Creates a basic(only required elements) .bagit bag in place.
* This creates files and directories, thus if an error is thrown during operation it may leave the filesystem
Expand All @@ -87,21 +77,19 @@ protected static void moveFilesToDataDir(File[] files, File dataDir) throws IOEx
* @throws IOException if there is a problem writing files or .bagit directory
*/
@Incubating
public static Bag createDotBagit(File root, SupportedAlgorithm algorithm, boolean includeHidden) throws NoSuchAlgorithmException, IOException{
public static Bag createDotBagit(Path root, SupportedAlgorithm algorithm, boolean includeHidden) throws NoSuchAlgorithmException, IOException{
Bag bag = new Bag(new Version(0, 98));
bag.setRootDir(root);
logger.info("Creating a bag with version: [{}] in directory: [{}]", bag.getVersion(), root);

File dotbagitDir = new File(root, ".bagit");
if(!dotbagitDir.mkdir()){
throw new IOException("Was unable to create " + dotbagitDir);
}
Path dotbagitDir = root.resolve(".bagit");
Files.createDirectories(dotbagitDir);

logger.info("Creating payload manifest");
Manifest manifest = new Manifest(algorithm);
MessageDigest messageDigest = MessageDigest.getInstance(algorithm.getMessageDigestName());
AddPayloadToBagManifestVistor visitor = new AddPayloadToBagManifestVistor(manifest, messageDigest, includeHidden);
Files.walkFileTree(Paths.get(root.toURI()), visitor);
Files.walkFileTree(root, visitor);

bag.getPayLoadManifests().add(manifest);
BagWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), dotbagitDir);
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/gov/loc/repository/bagit/domain/Bag.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package gov.loc.repository.bagit.domain;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -33,7 +33,7 @@ public class Bag {
private List<Pair<String, String>> metadata = new ArrayList<>();

//the current location of the bag on the filesystem
private File rootDir;
private Path rootDir;

public Bag(){
}
Expand Down Expand Up @@ -142,11 +142,11 @@ public boolean equals(Object obj) {
Objects.equals(this.metadata, other.getMetadata());
}

public File getRootDir() {
public Path getRootDir() {
return rootDir;
}

public void setRootDir(File rootDir) {
public void setRootDir(Path rootDir) {
this.rootDir = rootDir;
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/gov/loc/repository/bagit/domain/Manifest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

package gov.loc.repository.bagit.domain;

import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;

import gov.loc.repository.bagit.hash.SupportedAlgorithm;
Expand All @@ -11,17 +11,17 @@
*/
public class Manifest {
private final SupportedAlgorithm algorithm;
private HashMap<File, String> fileToChecksumMap = new HashMap<>();
private HashMap<Path, String> fileToChecksumMap = new HashMap<>();

public Manifest(SupportedAlgorithm algorithm){
this.algorithm = algorithm;
}

public HashMap<File, String> getFileToChecksumMap() {
public HashMap<Path, String> getFileToChecksumMap() {
return fileToChecksumMap;
}

public void setFileToChecksumMap(HashMap<File, String> fileToChecksumMap) {
public void setFileToChecksumMap(HashMap<Path, String> fileToChecksumMap) {
this.fileToChecksumMap = fileToChecksumMap;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gov.loc.repository.bagit.hash;

/**
* Implement this interface if you need to be able to use other algorithms than the {@link StandardSupportedAlgorithms}
*/
public interface BagitAlgorithmNameToSupportedAlgorithmMapping {
public SupportedAlgorithm getMessageDigestName(String bagitAlgorithmName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gov.loc.repository.bagit.hash;

/**
* Provides a mapping between bagit algorithm names and {@link SupportedAlgorithm}
*/
public class StandardBagitAlgorithmNameToSupportedAlgorithmMapping
implements BagitAlgorithmNameToSupportedAlgorithmMapping {

@Override
public SupportedAlgorithm getMessageDigestName(String bagitAlgorithmName) {
return StandardSupportedAlgorithms.valueOf(bagitAlgorithmName.toUpperCase());
}

}
Loading

0 comments on commit 0174692

Please # to comment.