diff --git a/README.md b/README.md index 21fe6e0..d69851d 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,17 @@ commons compression library for support of tarred Gzip archive format (".tgz"), [![Build Status](https://travis-ci.org/richardrodgers/bagit.svg?branch=master)] (https://travis-ci.org/richardrodgers/bagit) +[![Dependency Status](https://dependencyci.com/github/richardrodgers/bagit/badge)] +(https://dependencyci.com/github/richardrodgers/bagit) ## Use Cases ## The library attempts to simplify a few of the most common use cases/patterns involving bag packages. The first (the _producer_ pattern) is where content is assembled and placed into a bag, and the bag is then serialized for transport/hand-off to another component or system. The goal here is to ensure that the constructed bag is correct. -A helper class - bag _Filler_ - is used to orchestrate this assembly. Sequence: new Filler -> add content -> add more content -> serialize. +A helper class - _Filler_ - is used to orchestrate this assembly. Sequence: new Filler -> add content -> add more content -> serialize. The second (the _consumer_ pattern) is where a bag serialization (or a loose directory) is given and must -be interpreted and validated for use. Here another helper class _Loader_ is used to deserialize. +be interpreted and validated for use. Here another helper class - _Loader_ - is used to deserialize. Sequence: new Loader -> load serialization -> convert to Bag -> process contents. If you have more complex needs in java, (e.g. support for multiple spec versions), you may wish to consider the [Library of Congress Java Library](https://github.com/LibraryOfCongress/bagit-java). @@ -35,7 +37,7 @@ archive. To convert the same bag to use a compressed tar format: InputStream bagStream = filler.toStream("tgz"); -We don't always need bag I/O streams - suppose we wish obtain a reference to an archive file object instead: +We don't always want bag I/O streams - suppose we wish to obtain a bag archive file package instead: Path bagPackage = new Filler().payload(file1).metadata("External-Identifier", "mit.edu.0001").toPackage(); @@ -93,10 +95,10 @@ See the [Javadoc](http://richardrodgers.github.io/bagit/javadoc/index.html) for ## Archive formats ## Bags are commonly serialized to standard archive formats such as ZIP. The library supports two archive formats: -'zip' and 'tgz' and the variants 'zip.nt' and 'tgz.nt' (no time). If these variants are used, the library -suppresses the file creation/modification time attributes, in order that checksums of archives produced at different times -may accurately reflect only bag contents. That is, the checksum of a zip.nt bag (of the same name) is time-of-archiving- -and filesystem-time-invariant, but content-sensitive. +'zip' and 'tgz' and a variant in each of these. If the variant is used, the library suppresses the file +creation/modification time attributes, in order that checksums of archives produced at different times +may accurately reflect only bag contents. That is, the checksum of a zipped bag (with no timestamp variant) is +time-of-archiving and filesystem-time-invariant, but content-sensitive. The variant is requested with an API call. ## Extras ## @@ -131,14 +133,14 @@ Fat jars include all dependencies in a single executable jar (no classpath decla The distribution jars are kept at [Bintray](https://bintray.com), so make sure that repository is declared. Then (NB: using the most current version), for Gradle: - compile 'edu.mit.lib:bagit:0.7' + compile 'edu.mit.lib:bagit:0.8' or Maven: edu.mit.lib bagit - 0.7 + 0.8 in a standard pom.xml dependencies block. diff --git a/build.gradle b/build.gradle index 0062bf0..a5de0a8 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ sourceCompatibility = 1.8 group = 'edu.mit.lib' archivesBaseName = 'bagit' -version = '0.7' +version = '0.8' description = 'Compact Java BagIt library' ext { @@ -28,7 +28,7 @@ ext { } dependencies { - compile group: 'org.apache.commons', name: 'commons-compress', version: '1.9' + compile group: 'org.apache.commons', name: 'commons-compress', version: '1.13' testCompile group: 'junit', name: 'junit', version: '4.11' } diff --git a/src/main/java/edu/mit/lib/bagit/Bag.java b/src/main/java/edu/mit/lib/bagit/Bag.java index d072d65..084b623 100644 --- a/src/main/java/edu/mit/lib/bagit/Bag.java +++ b/src/main/java/edu/mit/lib/bagit/Bag.java @@ -14,7 +14,6 @@ import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.security.DigestInputStream; -import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; @@ -44,7 +43,7 @@ public class Bag { static final String ENCODING = "UTF-8"; static final String CS_ALGO = "MD5"; static final String BAGIT_VSN = "0.97"; - static final String LIB_VSN = "0.7"; + static final String LIB_VSN = "0.8"; static final String DFLT_FMT = "zip"; static final String TGZIP_FMT = "tgz"; static final String SPACER = " "; @@ -77,9 +76,9 @@ public enum MetadataName { INTERNAL_SENDER_DESC("Internal-Sender-Description"), BAG_SOFTWARE_AGENT("Bag-Software-Agent"); // not in IETF spec - private String mdName; + private final String mdName; - private MetadataName(String name) { + MetadataName(String name) { mdName = name; } @@ -168,11 +167,9 @@ public boolean isComplete() throws IOException { // # tag files and # manifest entries must agree // tag files consist of any top-level files except: // tagmanifest itself, and the payload directory. - DirectoryStream.Filter filter = new DirectoryStream.Filter() { - public boolean accept(Path file) throws IOException { - String name = file.getFileName().toString(); - return ! (name.startsWith(TAGMANIF_FILE) || name.startsWith(DATA_DIR)); - } + DirectoryStream.Filter filter = file -> { + String name = file.getFileName().toString(); + return ! (name.startsWith(TAGMANIF_FILE) || name.startsWith(DATA_DIR)); }; int tagCount = 0; try (DirectoryStream stream = Files.newDirectoryStream(baseDir, filter)) { @@ -277,10 +274,9 @@ public Map payloadRefs() throws IOException { * * @param relPath the relative path of the file from the bag root directory * @return tagfile the tag file path, or null if no file at the specified path - * @throws IOException if unable to access tag file * @throws IllegalAccessException if bag is sealed */ - public Path tagFile(String relPath) throws IOException, IllegalAccessException { + public Path tagFile(String relPath) throws IllegalAccessException { if (sealed) { throw new IllegalAccessException("Sealed Bag: no file access allowed"); } @@ -354,7 +350,7 @@ public List property(String relPath, String name) throws IOException { try (BufferedReader reader = Files.newBufferedReader(bagFile(relPath), StandardCharsets.UTF_8)) { String propName = null; StringBuilder valSb = new StringBuilder(); - String line = null; + String line; while ((line = reader.readLine()) != null) { // if line does not start with spacer, it is a new property if (! line.startsWith(SPACER)) { @@ -414,7 +410,7 @@ public Map tagManifest() throws IOException { public Map manifest(String relPath) throws IOException { Map mfMap = new HashMap<>(); try (BufferedReader reader = Files.newBufferedReader(bagFile(relPath), StandardCharsets.UTF_8)) { - String line = null; + String line; while((line = reader.readLine()) != null) { String[] parts = line.split(" "); mfMap.put(parts[1], parts[0]); @@ -439,11 +435,7 @@ private int fileCount(Path dir) throws IOException { } private void addProp(String name, String value, Map> mdSet) { - List vals = mdSet.get(name); - if (vals == null) { - vals = new ArrayList<>(); - mdSet.put(name, vals); - } + List vals = mdSet.computeIfAbsent(name, k -> new ArrayList<>()); vals.add(value.trim()); } @@ -484,7 +476,7 @@ static Map payloadRefs(Path refFile) throws IOException { Map refMap = new HashMap<>(); if (Files.exists(refFile)) { try (BufferedReader reader = Files.newBufferedReader(refFile, StandardCharsets.UTF_8)) { - String line = null; + String line; while((line = reader.readLine()) != null) { String[] parts = line.split(" "); refMap.put(parts[2], parts[0]); diff --git a/src/main/java/edu/mit/lib/bagit/Bagger.java b/src/main/java/edu/mit/lib/bagit/Bagger.java index 027612b..02aa118 100644 --- a/src/main/java/edu/mit/lib/bagit/Bagger.java +++ b/src/main/java/edu/mit/lib/bagit/Bagger.java @@ -26,13 +26,14 @@ public class Bagger { /* A bit clunky in the cmd-line arg handling, but deliberately so as to limit external dependencies for those who want to only use the library API directly. */ - private List payloads = new ArrayList<>(); - private List references = new ArrayList<>(); - private List tags = new ArrayList<>(); - private List statements = new ArrayList<>(); + private final List payloads = new ArrayList<>(); + private final List references = new ArrayList<>(); + private final List tags = new ArrayList<>(); + private final List statements = new ArrayList<>(); private String archFmt = "directory"; + private boolean noTime = false; private String csAlg = "MD5"; - private List optFlags = new ArrayList<>(); + private final List optFlags = new ArrayList<>(); private int verbosityLevel; public static void main(String[] args) throws IOException, IllegalAccessException { @@ -47,6 +48,7 @@ public static void main(String[] args) throws IOException, IllegalAccessExceptio case "-r": bagger.references.add(args[i+1]); break; case "-t": bagger.tags.add(args[i+1]); break; case "-m": bagger.statements.add(args[i+1]); break; + case "-n": bagger.noTime = Boolean.valueOf(args[i+1]); break; case "-a": bagger.archFmt = args[i+1]; break; case "-c": bagger.csAlg = args[i+1]; break; case "-o": bagger.optFlags.add(args[i+1]); break; @@ -80,7 +82,8 @@ public static void usage() { "-r = - payload reference\n" + "-t [=]\n" + "-m = - metadata statement\n" + - "-a - e.g. 'zip', 'zip.nt', 'tgz', 'tgz.nt' (default: loose directory)\n" + + "-a - e.g. 'zip', 'tgz', (default: loose directory)\n" + + "-n - 'true' or 'false'\n" + "-c - default: 'MD5'\n" + "-o \n" + "-v - output level to console (default: 0 = no output)"); @@ -121,11 +124,11 @@ private void fill(Path baseDir) throws IOException { String[] parts = statement.split("="); filler.metadata(parts[0], parts[1]); } - Path bagPath = null; + Path bagPath; if (archFmt.equals("directory")) { bagPath = filler.toDirectory(); } else { - bagPath = filler.toPackage(archFmt); + bagPath = filler.toPackage(archFmt, noTime); } if (verbosityLevel > 0) { message(bagPath.getFileName().toString(), true, "created"); diff --git a/src/main/java/edu/mit/lib/bagit/Filler.java b/src/main/java/edu/mit/lib/bagit/Filler.java index 449a70d..04498b7 100644 --- a/src/main/java/edu/mit/lib/bagit/Filler.java +++ b/src/main/java/edu/mit/lib/bagit/Filler.java @@ -6,10 +6,7 @@ package edu.mit.lib.bagit; import java.io.BufferedOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FilterInputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -27,7 +24,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -188,33 +184,31 @@ public Filler(Path base, String csAlgorithm, EolRule eolRule) throws IOException private void buildBag() throws IOException { if (built) return; // if auto-generating any metadata, do so - Iterator agIter = autogenNames.iterator(); - while (agIter.hasNext()) { - switch (agIter.next()) { - case BAGGING_DATE : - metadata(BAGGING_DATE, new SimpleDateFormat("yyyy-MM-dd").format(new Date())); - break; - case BAG_SIZE : - metadata(BAG_SIZE, scaledSize(payloadSize, 0)); - break; - case PAYLOAD_OXUM : - metadata(PAYLOAD_OXUM, String.valueOf(payloadSize) + "." + String.valueOf(payloadCount)); - break; - case BAG_SOFTWARE_AGENT : - metadata(BAG_SOFTWARE_AGENT, "MIT BagIt Lib v:" + LIB_VSN); + for (MetadataName autogenName : autogenNames) { + switch (autogenName) { + case BAGGING_DATE: + metadata(BAGGING_DATE, new SimpleDateFormat("yyyy-MM-dd").format(new Date())); + break; + case BAG_SIZE: + metadata(BAG_SIZE, scaledSize(payloadSize, 0)); + break; + case PAYLOAD_OXUM: + metadata(PAYLOAD_OXUM, String.valueOf(payloadSize) + "." + String.valueOf(payloadCount)); + break; + case BAG_SOFTWARE_AGENT: + metadata(BAG_SOFTWARE_AGENT, "MIT BagIt Lib v:" + LIB_VSN); + break; + default: break; - default : break; } } // close all optional writers' tag files - Iterator wIter = writers.keySet().iterator(); - while (wIter.hasNext()) { - getWriter(wIter.next()).close(); + for (String s : writers.keySet()) { + getWriter(s).close(); } // close all optional output streams - Iterator sIter = streams.keySet().iterator(); - while (sIter.hasNext()) { - getStream(null, sIter.next(), null, true).close(); + for (String s : streams.keySet()) { + getStream(null, s, null, true).close(); } // close the manifest file manWriter.close(); @@ -235,7 +229,7 @@ private void buildBag() throws IOException { * @return Filler this Filler */ public Filler noAutoGen() { - return autoGen(new HashSet()); + return autoGen(new HashSet<>()); } /** @@ -583,37 +577,38 @@ public Path toDirectory() throws IOException { } /** - * Returns bag serialized as an archive file using default packaging (zip archive). + * Returns bag serialized as an archive file using default packaging (zip archive) + * assigning zip timestamps * * @return path the bag archive package path * @throws IOException if error reading bag */ public Path toPackage() throws IOException { - return toPackage(DFLT_FMT); + return toPackage(DFLT_FMT, false); } /** * Returns bag serialized as an archive file using passed packaging format. * Supported formats: 'zip' - zip archive, 'tgz' - gzip compressed tar archive - * 'zip.nt' and 'tgz.nt' the same except file time attributes suppressed * * @param format the package format ('zip', or 'tgz') + * @param noTime if 'true', suppress regular timestamp assignment in archive * @return path the bag archive package path * @throws IOException if error reading bag */ - public Path toPackage(String format) throws IOException { - return deflate(format); + public Path toPackage(String format, boolean noTime) throws IOException { + return deflate(format, noTime); } /** * Returns bag serialized as an IO stream using default packaging (zip archive). * Bag is deleted when stream closed if temporary bag location used. * - * @return file the bag archive package + * @return InputStream of the bag archive package * @throws IOException if error reading bag */ public InputStream toStream() throws IOException { - return toStream(DFLT_FMT); + return toStream(DFLT_FMT, true); } /** @@ -622,11 +617,12 @@ public InputStream toStream() throws IOException { * Supported formats: 'zip' - zip archive, 'tgz' - gzip compressed tar archive * * @param format the package format ('zip', or 'tgz') - * @return file the bag archive package + * @param noTime if 'true', suppress regular timestamp assignment in archive + * @return InputStream of the bag archive package * @throws IOException if error reading bag */ - public InputStream toStream(String format) throws IOException { - Path pkgFile = deflate(format); + public InputStream toStream(String format, boolean noTime) throws IOException { + Path pkgFile = deflate(format, noTime); if (transientBag) { return new CleanupInputStream(Files.newInputStream(pkgFile), pkgFile); } else { @@ -636,7 +632,7 @@ public InputStream toStream(String format) throws IOException { class CleanupInputStream extends FilterInputStream { - private Path file; + private final Path file; public CleanupInputStream(InputStream in, Path file) { super(in); @@ -666,33 +662,29 @@ private void deleteDir(Path dirFile) { } catch (IOException ioE) {} } - private Path deflate(String format) throws IOException { + private Path deflate(String format, boolean noTime) throws IOException { // deflate this bag in situ (in current directory) using given packaging format buildBag(); - int ndIdx = format.indexOf(".nt"); - String sfx = (ndIdx > 0) ? format.substring(0, ndIdx) : format; - Path pkgFile = base.getParent().resolve(base.getFileName().toString() + "." + sfx); - deflate(Files.newOutputStream(pkgFile), format); + Path pkgFile = base.getParent().resolve(base.getFileName().toString() + "." + format); + deflate(Files.newOutputStream(pkgFile), format, noTime); // remove base empty(); return pkgFile; } - private void deflate(OutputStream out, String format) throws IOException { + private void deflate(OutputStream out, String format, boolean noTime) throws IOException { switch(format) { case "zip": - case "zip.nt": try (ZipOutputStream zout = new ZipOutputStream( new BufferedOutputStream(out))) { - fillZip(base, base.getFileName().toString(), zout, format.endsWith(".nt")); + fillZip(base, base.getFileName().toString(), zout, noTime); } break; case "tgz": - case "tgz.nt": try (TarArchiveOutputStream tout = new TarArchiveOutputStream( new BufferedOutputStream( new GzipCompressorOutputStream(out)))) { - fillArchive(base, base.getFileName().toString(), tout, format.endsWith(".nt")); + fillArchive(base, base.getFileName().toString(), tout, noTime); } break; default: @@ -700,16 +692,16 @@ private void deflate(OutputStream out, String format) throws IOException { } } - private void fillArchive(Path dirFile, String relBase, ArchiveOutputStream out, boolean skipTime) throws IOException { + private void fillArchive(Path dirFile, String relBase, ArchiveOutputStream out, boolean noTime) throws IOException { try (DirectoryStream stream = Files.newDirectoryStream(dirFile)) { for (Path file : stream) { String relPath = relBase + '/' + file.getFileName().toString(); if (Files.isDirectory(file)) { - fillArchive(file, relPath, out, skipTime); + fillArchive(file, relPath, out, noTime); } else { TarArchiveEntry entry = new TarArchiveEntry(relPath); entry.setSize(Files.size(file)); - entry.setModTime(skipTime ? 0L : Files.getLastModifiedTime(file).toMillis()); + entry.setModTime(noTime ? 0L : Files.getLastModifiedTime(file).toMillis()); out.putArchiveEntry(entry); Files.copy(file, out); out.closeArchiveEntry(); @@ -718,17 +710,17 @@ private void fillArchive(Path dirFile, String relBase, ArchiveOutputStream out, } } - private void fillZip(Path dirFile, String relBase, ZipOutputStream zout, boolean skipTime) throws IOException { + private void fillZip(Path dirFile, String relBase, ZipOutputStream zout, boolean noTime) throws IOException { try (DirectoryStream stream = Files.newDirectoryStream(dirFile)) { for (Path file : stream) { String relPath = relBase + '/' + file.getFileName().toString(); if (Files.isDirectory(file)) { - fillZip(file, relPath, zout, skipTime); + fillZip(file, relPath, zout, noTime); } else { ZipEntry entry = new ZipEntry(relPath); BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class); - entry.setCreationTime(skipTime ? FileTime.fromMillis(0L) : attrs.creationTime()); - entry.setLastModifiedTime(skipTime ? FileTime.fromMillis(0L) : attrs.lastModifiedTime()); + entry.setCreationTime(noTime ? FileTime.fromMillis(0L) : attrs.creationTime()); + entry.setLastModifiedTime(noTime ? FileTime.fromMillis(0L) : attrs.lastModifiedTime()); zout.putNextEntry(entry); Files.copy(file, zout); zout.closeEntry(); diff --git a/src/main/java/edu/mit/lib/bagit/Loader.java b/src/main/java/edu/mit/lib/bagit/Loader.java index 4f2f221..4565ea3 100644 --- a/src/main/java/edu/mit/lib/bagit/Loader.java +++ b/src/main/java/edu/mit/lib/bagit/Loader.java @@ -20,7 +20,6 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; @@ -190,7 +189,7 @@ private void finish() throws IOException { private List bufferFile(Path file) throws IOException { List lines = new ArrayList<>(); try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { - String line = null; + String line; while ((line = reader.readLine()) != null) { lines.add(line + lineSeparator); } @@ -245,17 +244,6 @@ private Path bagFile(String name) { return base.resolve(name); } - private Path dataFile(String name) throws IOException { - // all user-defined files live in payload area - ie. under 'data' - Path dataFile = bagFile(DATA_DIR).resolve(name); - // create needed dirs - Path parentFile = dataFile.getParent(); - if (! Files.isDirectory(parentFile)) { - Files.createDirectories(parentFile); - } - return dataFile; - } - // lazy initialization of manifest writer private synchronized LoaderWriter manifestWriter() throws IOException { if (manWriter == null) { @@ -264,15 +252,15 @@ private synchronized LoaderWriter manifestWriter() throws IOException { try (Scanner sc = new Scanner(manif)) { lineSeparator = (sc.findWithinHorizon("\r\n", 500) != null) ? "\r\n" : "\n"; } - manWriter = new LoaderWriter(manif, null, true, null); + manWriter = new LoaderWriter(manif); } return manWriter; } class LoaderWriter extends LoaderOutputStream { - private LoaderWriter(Path file, String brPath, boolean append, LoaderWriter tailWriter) throws IOException { - super(file, brPath, append, tailWriter); + private LoaderWriter(Path file) throws IOException { + super(file); } public void writeLine(String line) throws IOException { @@ -288,13 +276,13 @@ class LoaderOutputStream extends OutputStream { private final DigestOutputStream dout; private final LoaderWriter tailWriter; - private LoaderOutputStream(Path file, String relPath, boolean append, LoaderWriter tailWriter) throws IOException { - OpenOption opt = append ? StandardOpenOption.APPEND : StandardOpenOption.READ; + private LoaderOutputStream(Path file) throws IOException { + OpenOption opt = StandardOpenOption.APPEND; try { out = Files.newOutputStream(file, opt); dout = new DigestOutputStream(out, MessageDigest.getInstance(csAlg)); - this.relPath = (relPath != null) ? relPath : file.getFileName().toString(); - this.tailWriter = tailWriter; + this.relPath = file.getFileName().toString(); + this.tailWriter = null; } catch (NoSuchAlgorithmException nsae) { throw new IOException("no such algorithm: " + csAlg); } @@ -320,7 +308,7 @@ private void inflate(Path parent, InputStream in, String fmt) throws IOException switch (fmt) { case "zip" : try (ZipInputStream zin = new ZipInputStream(in)) { - ZipEntry entry = null; + ZipEntry entry; while((entry = zin.getNextEntry()) != null) { if (base == null) { base = parent.resolve(entry.getName().substring(0, entry.getName().indexOf("/"))); @@ -337,7 +325,7 @@ private void inflate(Path parent, InputStream in, String fmt) throws IOException case "tgz" : try (TarArchiveInputStream tin = new TarArchiveInputStream( new GzipCompressorInputStream(in))) { - TarArchiveEntry tentry = null; + TarArchiveEntry tentry; while((tentry = tin.getNextTarEntry()) != null) { if (base == null) { base = parent.resolve(tentry.getName().substring(0, tentry.getName().indexOf("/"))); diff --git a/src/test/java/edu/mit/lib/bagit/BagTest.java b/src/test/java/edu/mit/lib/bagit/BagTest.java index 677b626..65d3944 100644 --- a/src/test/java/edu/mit/lib/bagit/BagTest.java +++ b/src/test/java/edu/mit/lib/bagit/BagTest.java @@ -4,16 +4,12 @@ */ package edu.mit.lib.bagit; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; import java.util.Scanner; import java.util.HashSet; import java.util.Map; @@ -43,7 +39,7 @@ public class BagTest { public Path payload1, payload2, tag1, tag2; @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); + public final TemporaryFolder tempFolder = new TemporaryFolder(); @Before public void createTestData() throws IOException { @@ -227,8 +223,8 @@ public void bagFileAttributesPreservedInZip() throws IOException, IllegalAccessE Path bagFile = tempFolder.newFolder("bag11").toPath(); BasicFileAttributes beforeAttrs = Files.readAttributes(payload1, BasicFileAttributes.class); Filler filler = new Filler(bagFile).payload("first.pdf", payload1); - // 'zip' should preserve file time attrs - Path bagPackage = filler.toPackage("zip"); + // should preserve file time attrs if noTime false + Path bagPackage = filler.toPackage("zip", false); Bag bag = new Loader(bagPackage).load(); Path payload = bag.payloadFile("first.pdf"); BasicFileAttributes afterAttrs = Files.readAttributes(payload, BasicFileAttributes.class); @@ -241,8 +237,8 @@ public void bagFileAttributesClearedInZipNt() throws IOException, IllegalAccessE Path bagFile = tempFolder.newFolder("bag12").toPath(); BasicFileAttributes beforeAttrs = Files.readAttributes(payload1, BasicFileAttributes.class); Filler filler = new Filler(bagFile).payload("first.pdf", payload1); - // 'zip.nt' should strip file time attrs - Path bagPackage = filler.toPackage("zip.nt"); + // should strip file time attrs if noTime true + Path bagPackage = filler.toPackage("zip", true); Bag bag = new Loader(bagPackage).load(); Path payload = bag.payloadFile("first.pdf"); BasicFileAttributes afterAttrs = Files.readAttributes(payload, BasicFileAttributes.class);