[Git][java-team/plexus-archiver][upstream] New upstream version 4.3.0

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Thu Sep 29 13:33:07 BST 2022



Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / plexus-archiver


Commits:
fab62d24 by Emmanuel Bourg at 2022-09-29T13:46:13+02:00
New upstream version 4.3.0
- - - - -


27 changed files:

- − .github/workflows/codeql-analysis.yml
- .github/workflows/maven.yml
- .github/workflows/release-drafter.yml
- README.md
- pom.xml
- src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java
- src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java
- src/main/java/org/codehaus/plexus/archiver/Archiver.java
- src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java
- src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java
- src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java
- src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java
- src/main/java/org/codehaus/plexus/archiver/jar/JarArchiver.java
- src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java
- src/main/java/org/codehaus/plexus/archiver/jar/Manifest.java
- src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java
- src/main/java/org/codehaus/plexus/archiver/util/Streams.java
- src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java
- src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java
- src/main/java/org/codehaus/plexus/archiver/zip/ZipResource.java
- src/test/java/org/codehaus/plexus/archiver/DuplicateFilesTest.java
- src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java
- src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java
- src/test/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiverTest.java
- src/test/java/org/codehaus/plexus/archiver/zip/ArchiveFileComparator.java
- src/test/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreatorTest.java
- src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java


Changes:

=====================================
.github/workflows/codeql-analysis.yml deleted
=====================================
@@ -1,67 +0,0 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
-name: "CodeQL"
-
-on:
-  push:
-    branches: [ master ]
-  pull_request:
-    # The branches below must be a subset of the branches above
-    branches: [ master ]
-  schedule:
-    - cron: '29 9 * * 5'
-
-jobs:
-  analyze:
-    name: Analyze
-    runs-on: ubuntu-latest
-
-    strategy:
-      fail-fast: false
-      matrix:
-        language: [ 'java' ]
-        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
-        # Learn more:
-        # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
-
-    steps:
-    - name: Checkout repository
-      uses: actions/checkout at v2.4.0
-
-    # Initializes the CodeQL tools for scanning.
-    - name: Initialize CodeQL
-      uses: github/codeql-action/init at v1
-      with:
-        languages: ${{ matrix.language }}
-        # If you wish to specify custom queries, you can do so here or in a config file.
-        # By default, queries listed here will override any specified in a config file.
-        # Prefix the list here with "+" to use these queries and those in the config file.
-        # queries: ./path/to/local/query, your-org/your-repo/queries at main
-
-    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
-    # If this step fails, then you should remove it and run the build manually (see below)
-    - name: Autobuild
-      uses: github/codeql-action/autobuild at v1
-
-    # ℹ️ Command-line programs to run using the OS shell..
-    # 📚 https://git.io/JvXDl
-
-    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
-    #    and modify them (or add more) to build your code if your project
-    #    uses a compiled language
-
-    #- run: |
-    #   make bootstrap
-    #   make release
-
-    - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze at v1


=====================================
.github/workflows/maven.yml
=====================================
@@ -35,9 +35,9 @@ jobs:
             os: 'ubuntu-latest'
     steps:
       - name: Checkout
-        uses: actions/checkout at v2.4.0
+        uses: actions/checkout at v3
       - name: Set up JDK ${{ matrix.Java }} (${{ matrix.distribution }})
-        uses: actions/setup-java at v2
+        uses: actions/setup-java at v3
         with:
           distribution: ${{ matrix.distribution }}
           java-version: ${{ matrix.java }}


=====================================
.github/workflows/release-drafter.yml
=====================================
@@ -7,6 +7,6 @@ jobs:
   update_release_draft:
     runs-on: ubuntu-latest
     steps:
-      - uses: release-drafter/release-drafter at v5.15.0
+      - uses: release-drafter/release-drafter at v5.20.0
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


=====================================
README.md
=====================================
@@ -3,7 +3,7 @@ Plexus-archiver
 
 [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/codehaus-plexus/plexus-archiver.svg?label=License)](http://www.apache.org/licenses/)
 [![Maven Central](https://img.shields.io/maven-central/v/org.codehaus.plexus/plexus-archiver.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.codehaus.plexus/plexus-archiver)
-[![Build Status](https://travis-ci.org/codehaus-plexus/plexus-archiver.svg?branch=master)](https://travis-ci.org/codehaus-plexus/plexus-archiver)
+[![GitHub CI](https://github.com/codehaus-plexus/plexus-archiver/actions/workflows/maven.yml/badge.svg)](https://github.com/codehaus-plexus/plexus-archiver/actions/workflows/maven.yml)
 [![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green?labelColor=blue)](https://github.com/jvm-repo-rebuild/reproducible-central#org.codehaus.plexus:plexus-archiver)
 
 The current master is now at https://github.com/codehaus-plexus/plexus-archiver


=====================================
pom.xml
=====================================
@@ -6,18 +6,18 @@
   <parent>
     <groupId>org.codehaus.plexus</groupId>
     <artifactId>plexus</artifactId>
-    <version>8</version>
+    <version>10</version>
   </parent>
 
   <artifactId>plexus-archiver</artifactId>
-  <version>4.2.7</version>
+  <version>4.3.0</version>
   <name>Plexus Archiver Component</name>
 
   <scm>
     <connection>scm:git:git at github.com:codehaus-plexus/plexus-archiver.git</connection>
     <developerConnection>scm:git:git at github.com:codehaus-plexus/plexus-archiver.git</developerConnection>
     <url>http://github.com/codehaus-plexus/plexus-archiver/tree/${project.scm.tag}/</url>
-    <tag>plexus-archiver-4.2.7</tag>
+    <tag>plexus-archiver-4.3.0</tag>
   </scm>
   <issueManagement>
     <system>jira</system>
@@ -31,8 +31,8 @@
   </distributionManagement>
 
   <properties>
-    <javaVersion>7</javaVersion>
-    <project.build.outputTimestamp>2022-01-02T11:11:33Z</project.build.outputTimestamp>
+    <javaVersion>8</javaVersion>
+    <project.build.outputTimestamp>2022-06-10T17:04:44Z</project.build.outputTimestamp>
   </properties>
 
   <contributors>
@@ -49,37 +49,45 @@
   </contributors>
 
   <dependencies>
+    <!-- Plexus dependencies -->
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-container-default</artifactId>
-      <version>1.0-alpha-30</version>
+      <version>2.1.1</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
-      <version>3.4.1</version>
+      <version>3.4.2</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-io</artifactId>
-      <version>3.2.0</version>
+      <version>3.3.1</version>
+    </dependency>
+    <!-- Apache Commons dependencies -->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.11.0</version>
     </dependency>
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-compress</artifactId>
       <version>1.21</version>
     </dependency>
+    <!-- Other dependencies -->
     <dependency>
       <groupId>org.iq80.snappy</groupId>
       <artifactId>snappy</artifactId>
       <version>0.4</version>
     </dependency>
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.13.2</version>
-      <scope>test</scope>
+      <groupId>org.tukaani</groupId>
+      <artifactId>xz</artifactId>
+      <version>1.9</version>
+      <scope>runtime</scope>
     </dependency>
     <dependency>
       <groupId>com.google.code.findbugs</groupId>
@@ -87,15 +95,15 @@
       <version>3.0.2</version>
       <scope>provided</scope>
     </dependency>
+    <!-- Test dependencies -->
     <dependency>
-      <groupId>org.tukaani</groupId>
-      <artifactId>xz</artifactId>
-      <version>1.9</version>
-      <scope>runtime</scope>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.2</version>
+      <scope>test</scope>
     </dependency>
   </dependencies>
 
-
   <build>
     <plugins>
       <plugin>


=====================================
src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java
=====================================
@@ -22,6 +22,7 @@
 import java.lang.reflect.UndeclaredThrowableException;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
+import java.nio.file.attribute.FileTime;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
@@ -107,10 +108,7 @@
      */
     private boolean useJvmChmod = true;
 
-    /**
-     * @since 4.2.0
-     */
-    private Date lastModifiedDate;
+    private FileTime lastModifiedTime;
 
     /**
      * @since 4.2.0
@@ -1208,16 +1206,36 @@ public void setIgnorePermissions( final boolean ignorePermissions )
         this.ignorePermissions = ignorePermissions;
     }
 
+    /**
+     * @deprecated Use {@link #setLastModifiedTime(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void setLastModifiedDate( Date lastModifiedDate )
     {
-        this.lastModifiedDate = lastModifiedDate;
+        this.lastModifiedTime = lastModifiedDate != null ? FileTime.fromMillis( lastModifiedDate.getTime() ) : null;
     }
 
+    /**
+     * @deprecated Use {@link #getLastModifiedTime()} instead.
+     */
     @Override
+    @Deprecated
     public Date getLastModifiedDate()
     {
-        return lastModifiedDate;
+        return lastModifiedTime != null ? new Date( lastModifiedTime.toMillis() ) : null;
+    }
+
+    @Override
+    public void setLastModifiedTime( FileTime lastModifiedTime )
+    {
+        this.lastModifiedTime = lastModifiedTime;
+    }
+
+    @Override
+    public FileTime getLastModifiedTime()
+    {
+        return lastModifiedTime;
     }
 
     @Override
@@ -1279,11 +1297,21 @@ public String getOverrideGroupName()
         return overrideGroupName;
     }
 
+    /**
+     * @deprecated Use {@link #configureReproducibleBuild(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void configureReproducible( Date lastModifiedDate )
+    {
+        configureReproducibleBuild( FileTime.fromMillis( lastModifiedDate.getTime() ) );
+    }
+
+    @Override
+    public void configureReproducibleBuild( FileTime lastModifiedTime )
     {
         // 1. force last modified date
-        setLastModifiedDate( normalizeLastModifiedDate( lastModifiedDate ) );
+        setLastModifiedTime( normalizeLastModifiedTime ( lastModifiedTime ) );
 
         // 2. sort filenames in each directory when scanning filesystem
         setFilenameComparator( new Comparator<String>()
@@ -1309,14 +1337,18 @@ public int compare( String s1, String s2 )
 
     /**
      * Normalize last modified time value to get reproducible archive entries, based on
-     * archive binary format (tar uses UTC timestamp but zip uses local time then requires
-     * tweaks to make the value reproducible whatever the current timezone is).
+     * archive binary format.
+     *
+     * <p>tar uses UTC timestamp, but zip uses local time then requires
+     * tweaks to make the value reproducible whatever the current timezone is.
+     *
+     * @param lastModifiedTime The last modification time
+     * @return The normalized last modification time
      *
-     * @param lastModifiedDate 
-     * @return
+     * @see #configureReproducibleBuild(FileTime)
      */
-    protected Date normalizeLastModifiedDate( Date lastModifiedDate )
+    protected FileTime normalizeLastModifiedTime( FileTime lastModifiedTime )
     {
-        return lastModifiedDate;
+        return lastModifiedTime;
     }
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/AbstractUnArchiver.java
=====================================
@@ -25,6 +25,7 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Locale;
 
 import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
 import org.codehaus.plexus.components.io.attributes.SymlinkUtils;
@@ -412,7 +413,7 @@ protected boolean shouldExtractEntry( File targetDirectory, File targetFileName,
         boolean fileOnDiskIsNewerThanEntry = targetFileName.lastModified() >= entryDate.getTime();
         boolean differentCasing = !entryName.equals( relativeCanonicalDestPath );
 
-        String casingMessage = String.format( "Archive entry '%s' and existing file '%s' names differ only by case."
+        String casingMessage = String.format( Locale.ENGLISH, "Archive entry '%s' and existing file '%s' names differ only by case."
                 + " This may lead to an unexpected outcome on case-insensitive filesystems.", entryName, canonicalDestPath );
 
         // (1)


=====================================
src/main/java/org/codehaus/plexus/archiver/Archiver.java
=====================================
@@ -19,11 +19,13 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.file.attribute.FileTime;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
 import javax.annotation.Nonnull;
 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
 import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection;
@@ -390,14 +392,38 @@ ResourceIterator getResources()
      *
      * @param lastModifiedDate
      * @since 4.2.0
+     * @deprecated Use {@link #setLastModifiedTime(FileTime)} instead
      */
+    @Deprecated
     void setLastModifiedDate( final Date lastModifiedDate );
 
     /**
      * @since 4.2.0
+     * @deprecated Use {@link #getLastModifiedTime()} instead
      */
+    @Deprecated
     Date getLastModifiedDate();
 
+    /**
+     * Sets the last modification time of the entries (if non null).
+     *
+     * @param lastModifiedTime to set in the archive entries
+     *
+     * @see #getLastModifiedTime()
+     * @since 4.3.0
+     */
+    void setLastModifiedTime( final FileTime lastModifiedTime );
+
+    /**
+     * Returns the last modification time of the archiver.
+     *
+     * @return The last modification time of the archiver, null if not specified
+     *
+     * @see #setLastModifiedTime(FileTime)
+     * @since 4.3.0
+     */
+    FileTime getLastModifiedTime();
+
     /**
      * Set filename comparator, used to sort file entries when scanning directories since File.list() does not
      * guarantee any order.
@@ -446,6 +472,17 @@ ResourceIterator getResources()
      */
     String getOverrideGroupName();
 
+    /**
+     * This method is obsolete and will just call {@link #configureReproducibleBuild(FileTime)}
+     * with the Date transformed into FileTime.
+     *
+     * @param lastModifiedDate the date to use for archive entries last modified time
+     * @since 4.2.0
+     * @deprecated Use {@link #configureReproducibleBuild(FileTime)} instead.
+     */
+    @Deprecated
+    void configureReproducible( Date lastModifiedDate );
+
     /**
      * Configure the archiver to create archives in a reproducible way (see
      * <a href="https://reproducible-builds.org/">Reproducible Builds</a>).
@@ -455,9 +492,11 @@ ResourceIterator getResources()
      * <li>defined entries timestamp</li>
      * <li>and reproducible entries Unix mode.</li>
      * </ul>
-     * 
-     * @param lastModifiedDate the date to use for archive entries last modified time
-     * @since 4.2.0
+     *
+     * @param lastModifiedTime The last modification time of the entries
+     *
+     * @see <a href="https://reproducible-builds.org/">Reproducible Builds</a>
+     * @since 4.3.0
      */
-    void configureReproducible( Date lastModifiedDate );
+    void configureReproducibleBuild( FileTime lastModifiedTime );
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java
=====================================
@@ -18,6 +18,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.file.attribute.FileTime;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.Map;
@@ -333,18 +334,38 @@ public void setIgnorePermissions( boolean ignorePermissions )
         target.setIgnorePermissions( ignorePermissions );
     }
 
+    /**
+     * @deprecated Use {@link #setLastModifiedTime(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void setLastModifiedDate( final Date lastModifiedDate )
     {
         target.setLastModifiedDate( lastModifiedDate );
     }
 
+    /**
+     * @deprecated Use {@link #getLastModifiedTime()} instead.
+     */
     @Override
+    @Deprecated
     public Date getLastModifiedDate()
     {
         return target.getLastModifiedDate();
     }
 
+    @Override
+    public void setLastModifiedTime( final FileTime lastModifiedTime )
+    {
+        target.setLastModifiedTime( lastModifiedTime );
+    }
+
+    @Override
+    public FileTime getLastModifiedTime()
+    {
+        return target.getLastModifiedTime();
+    }
+
     @Override
     public void setFilenameComparator( final Comparator<String> filenameComparator )
     {
@@ -399,10 +420,20 @@ public String getOverrideGroupName()
         return target.getOverrideGroupName();
     }
 
+    /**
+     * @deprecated Use {@link #configureReproducibleBuild(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void configureReproducible( Date lastModifiedDate )
     {
         target.configureReproducible( lastModifiedDate );
     }
 
+    @Override
+    public void configureReproducibleBuild( FileTime lastModifiedTime )
+    {
+        target.configureReproducibleBuild( lastModifiedTime );
+    }
+
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java
=====================================
@@ -18,6 +18,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.file.attribute.FileTime;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
@@ -348,18 +349,38 @@ public void setIgnorePermissions( boolean ignorePermissions )
         this.ignorePermissions = ignorePermissions;
     }
 
+    /**
+     * @deprecated Use {@link #setLastModifiedTime(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void setLastModifiedDate( final Date lastModifiedDate )
     {
 
     }
 
+    /**
+     * @deprecated Use {@link #getLastModifiedTime()} instead.
+     */
     @Override
+    @Deprecated
     public Date getLastModifiedDate()
     {
         return null;
     }
 
+    @Override
+    public void setLastModifiedTime( final FileTime lastModifiedTime )
+    {
+
+    }
+
+    @Override
+    public FileTime getLastModifiedTime()
+    {
+        return null;
+    }
+
     @Override
     public void setFilenameComparator( final Comparator<String> filenameComparator )
     {
@@ -414,10 +435,20 @@ public String getOverrideGroupName()
         return null;
     }
 
+    /**
+     * @deprecated Use {@link #configureReproducibleBuild(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void configureReproducible( Date lastModifiedDate )
     {
 
     }
 
+    @Override
+    public void configureReproducibleBuild( FileTime lastModifiedTime )
+    {
+
+    }
+
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java
=====================================
@@ -18,16 +18,19 @@
  */
 package org.codehaus.plexus.archiver.diags;
 
+import javax.annotation.Nonnull;
+
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.file.attribute.FileTime;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import javax.annotation.Nonnull;
+
 import org.codehaus.plexus.archiver.ArchiveEntry;
 import org.codehaus.plexus.archiver.ArchivedFileSet;
 import org.codehaus.plexus.archiver.Archiver;
@@ -54,7 +57,7 @@
 
     private boolean ignorePermissions;
 
-    private Date lastModified;
+    private FileTime lastModifiedTime;
 
     private Comparator<String> filenameComparator;
 
@@ -406,18 +409,37 @@ public void setIgnorePermissions( final boolean ignorePermissions )
         this.ignorePermissions = ignorePermissions;
     }
 
+    /**
+     * @deprecated Use {@link #setLastModifiedTime(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void setLastModifiedDate( final Date lastModifiedDate )
     {
-        this.lastModified = lastModifiedDate;
+        this.lastModifiedTime = lastModifiedDate != null ? FileTime.fromMillis( lastModifiedDate.getTime() ) : null;
     }
 
+    /**
+     * @deprecated Use {@link #getLastModifiedTime()} instead.
+     */
     @Override
+    @Deprecated
     public Date getLastModifiedDate()
     {
-        return lastModified;
+        return lastModifiedTime != null ? new Date( lastModifiedTime.toMillis() ) : null;
     }
 
+    @Override
+    public void setLastModifiedTime( final FileTime lastModifiedTime )
+    {
+        this.lastModifiedTime = lastModifiedTime;
+    }
+
+    @Override
+    public FileTime getLastModifiedTime()
+    {
+        return lastModifiedTime;
+    }
 
     @Override
     public void setFilenameComparator( final Comparator<String> filenameComparator )
@@ -425,6 +447,11 @@ public void setFilenameComparator( final Comparator<String> filenameComparator )
         this.filenameComparator = filenameComparator;
     }
 
+    public Comparator<String> getFilenameComparator()
+    {
+        return filenameComparator;
+    }
+
     @Override
     public void setOverrideUid( int uid )
     {
@@ -469,8 +496,17 @@ public String getOverrideGroupName()
         return null;
     }
 
+    /**
+     * @deprecated Use {@link #configureReproducibleBuild(FileTime)} instead.
+     */
     @Override
+    @Deprecated
     public void configureReproducible( Date lastModifiedDate )
     {
     }
+
+    @Override
+    public void configureReproducibleBuild( FileTime lastModifiedTime )
+    {
+    }
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java
=====================================
@@ -17,6 +17,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.attribute.FileTime;
 import java.util.ArrayList;
 import java.util.List;
 import org.codehaus.plexus.archiver.AbstractArchiver;
@@ -37,7 +39,7 @@
     extends AbstractArchiver
 {
 
-    private final List<Runnable> directoryChmods = new ArrayList<Runnable>();
+    private final List<Runnable> directoryChmods = new ArrayList<>();
 
     public void resetArchiver()
         throws IOException
@@ -101,10 +103,7 @@ public void execute()
                 }
             }
 
-            for ( Runnable directoryChmod : directoryChmods )
-            {
-                directoryChmod.run();
-            }
+            directoryChmods.forEach( Runnable::run );
             directoryChmods.clear();
         }
         catch ( final IOException ioe )
@@ -167,15 +166,15 @@ else if ( !outFile.mkdirs() )
                 throw new ArchiverException( "Unable to create directory or parent directory of " + outFile );
             }
 
-            directoryChmods.add( new Runnable()
-            {
-
-                @Override
-                public void run()
+            directoryChmods.add( () -> {
+                try
                 {
                     setFileModes( entry, outFile, inLastModified );
                 }
-
+                catch ( IOException e )
+                {
+                    throw new ArchiverException( "Failed setting file attributes", e );
+                }
             } );
         }
 
@@ -194,21 +193,23 @@ private static void makeParentDirectories( File file ) {
     }
 
     private void setFileModes( ArchiveEntry entry, File outFile, long inLastModified )
+        throws IOException
     {
         if ( !isIgnorePermissions() )
         {
             ArchiveEntryUtils.chmod( outFile, entry.getMode() );
         }
 
-        if ( getLastModifiedDate() == null )
+        if ( getLastModifiedTime() == null )
         {
-            outFile.setLastModified( inLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE
-                                         ? System.currentTimeMillis()
-                                         : inLastModified );
+            FileTime fromMillis = FileTime.fromMillis( inLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE
+                            ? System.currentTimeMillis()
+                            : inLastModified );
+            Files.setLastModifiedTime( outFile.toPath(), fromMillis );
         }
         else
         {
-            outFile.setLastModified( getLastModifiedDate().getTime() );
+            Files.setLastModifiedTime( outFile.toPath(), getLastModifiedTime() );
         }
     }
 


=====================================
src/main/java/org/codehaus/plexus/archiver/jar/JarArchiver.java
=====================================
@@ -27,6 +27,7 @@
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -37,7 +38,6 @@
 import java.util.SortedMap;
 import java.util.StringTokenizer;
 import java.util.TreeMap;
-import java.util.Vector;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
@@ -139,12 +139,12 @@
      * <p/>
      * Will not be filled unless the user has asked for an index.
      */
-    private Vector<String> rootEntries;
+    private List<String> rootEntries;
 
     /**
      * Path containing jars that shall be indexed in addition to this archive.
      */
-    private ArrayList<String> indexJars;
+    private List<String> indexJars;
 
     /**
      * Creates a minimal default manifest with {@code Manifest-Version: 1.0} only.
@@ -159,7 +159,7 @@ public JarArchiver()
         super();
         archiveType = "jar";
         setEncoding( "UTF8" );
-        rootEntries = new Vector<String>();
+        rootEntries = new ArrayList<>();
     }
 
     /**
@@ -299,7 +299,7 @@ public void addConfiguredIndexJars( File indexJar )
     {
         if ( indexJars == null )
         {
-            indexJars = new ArrayList<String>();
+            indexJars = new ArrayList<>();
         }
         indexJars.add( indexJar.getAbsolutePath() );
     }
@@ -373,13 +373,14 @@ private void writeManifest( ConcurrentJarCreator zOut, Manifest manifest )
         }
 
         zipDir( null, zOut, "META-INF/", DEFAULT_DIR_MODE, getEncoding() );
+
         // time to write the manifest
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream( 128 );
         manifest.write( baos );
+        InputStreamSupplier in = () -> new ByteArrayInputStream( baos.toByteArray() );
 
-        ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
-        super.zipFile( createInputStreamSupplier( bais ), zOut, MANIFEST_NAME, System.currentTimeMillis(), null,
-                       DEFAULT_FILE_MODE, null, false );
+        super.zipFile( in, zOut, MANIFEST_NAME, System.currentTimeMillis(), null, DEFAULT_FILE_MODE, null,
+                       false );
         super.initZipOutputStream( zOut );
     }
 
@@ -408,9 +409,9 @@ protected void finalizeZipOutputStream( ConcurrentJarCreator zOut )
     private void createIndexList( ConcurrentJarCreator zOut )
         throws IOException, ArchiverException
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream( 128 );
         // encoding must be UTF8 as specified in the specs.
-        PrintWriter writer = new PrintWriter( new OutputStreamWriter( baos, "UTF8" ) );
+        PrintWriter writer = new PrintWriter( new OutputStreamWriter( baos, StandardCharsets.UTF_8 ) );
 
         // version-info blankline
         writer.println( "JarIndex-Version: 1.0" );
@@ -440,7 +441,7 @@ private void createIndexList( ConcurrentJarCreator zOut )
                 filteredDirs.remove( META_INF_NAME + '/' );
             }
         }
-        writeIndexLikeList( new ArrayList<String>( filteredDirs ), rootEntries, writer );
+        writeIndexLikeList( new ArrayList<>( filteredDirs ), rootEntries, writer );
         writer.println();
 
         if ( indexJars != null )
@@ -464,8 +465,8 @@ private void createIndexList( ConcurrentJarCreator zOut )
                 String name = findJarName( indexJar, cpEntries );
                 if ( name != null )
                 {
-                    ArrayList<String> dirs = new ArrayList<String>();
-                    ArrayList<String> files = new ArrayList<String>();
+                    List<String> dirs = new ArrayList<>();
+                    List<String> files = new ArrayList<>();
                     grabFilesAndDirs( indexJar, dirs, files );
                     if ( dirs.size() + files.size() > 0 )
                     {
@@ -479,9 +480,9 @@ private void createIndexList( ConcurrentJarCreator zOut )
 
         writer.flush();
 
-        ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
+        InputStreamSupplier in = () -> new ByteArrayInputStream( baos.toByteArray() );
 
-        super.zipFile( createInputStreamSupplier( bais ), zOut, INDEX_NAME, System.currentTimeMillis(), null,
+        super.zipFile( in, zOut, INDEX_NAME, System.currentTimeMillis(), null,
                        DEFAULT_FILE_MODE, null, true );
     }
 
@@ -511,9 +512,9 @@ else if ( INDEX_NAME.equalsIgnoreCase( vPath ) && index )
         }
         else
         {
-            if ( index && ( !vPath.contains( "/" ) ) )
+            if ( index && !vPath.contains( "/" ) )
             {
-                rootEntries.addElement( vPath );
+                rootEntries.add( vPath );
             }
             super.zipFile( is, zOut, vPath, lastModified, fromArchive, mode, symlinkDestination, addInParallel );
         }
@@ -624,7 +625,7 @@ protected void cleanUp()
             filesetManifest = null;
             originalManifest = null;
         }
-        rootEntries.removeAllElements();
+        rootEntries.clear();
     }
 
     /**
@@ -722,21 +723,9 @@ protected static String findJarName( String fileName, String[] classpath )
             return new File( fileName ).getName();
         }
         fileName = fileName.replace( File.separatorChar, '/' );
-        SortedMap<String, String> matches = new TreeMap<String, String>( new Comparator<String>()
-        {
 
-            // longest match comes first
-            @Override
-            public int compare( String o1, String o2 )
-            {
-                if ( ( o1 != null ) && ( o2 != null ) )
-                {
-                    return o2.length() - o1.length();
-                }
-                return 0;
-            }
-
-        } );
+        // longest match comes first
+        SortedMap<String, String> matches = new TreeMap<>( Comparator.comparingInt( String::length ).reversed() );
 
         for ( String aClasspath : classpath )
         {
@@ -825,4 +814,22 @@ else if ( !name.contains( "/" ) )
         }
     }
 
+    /**
+     * Override the behavior of the Zip Archiver to match the output of the JAR tool.
+     *
+     * @param zipEntry to set the last modified time
+     * @param lastModifiedTime to set in the zip entry only if {@link #getLastModifiedTime()} returns null
+     */
+    @Override
+    protected void setZipEntryTime( ZipArchiveEntry zipEntry, long lastModifiedTime )
+    {
+        if ( getLastModifiedTime() != null )
+        {
+            lastModifiedTime = getLastModifiedTime().toMillis();
+        }
+
+        // The JAR tool does not round up, so we keep that behavior here (JDK-8277755).
+        zipEntry.setTime( lastModifiedTime );
+    }
+
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java
=====================================
@@ -16,17 +16,30 @@
  */
 package org.codehaus.plexus.archiver.jar;
 
-import org.apache.commons.compress.parallel.InputStreamSupplier;
-import org.codehaus.plexus.archiver.ArchiverException;
-import org.codehaus.plexus.archiver.zip.ConcurrentJarCreator;
-
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.lang.reflect.Method;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.FileTime;
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Enumeration;
 import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
 import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.compress.parallel.InputStreamSupplier;
+import org.apache.commons.io.output.NullPrintStream;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.zip.ConcurrentJarCreator;
+import org.codehaus.plexus.util.IOUtil;
 
 /**
  * A {@link ModularJarArchiver} implementation that uses
@@ -58,6 +71,8 @@
 
     private boolean moduleDescriptorFound;
 
+    private boolean hasJarDateOption;
+
     public JarToolModularJarArchiver()
     {
         try
@@ -111,18 +126,30 @@ protected void postCreateArchive()
             getLogger().debug( "Using the jar tool to " +
                 "update the archive to modular JAR." );
 
-			Integer result = (Integer) jarTool.getClass()
-                .getMethod( "run",
-                    PrintStream.class, PrintStream.class, String[].class )
-                .invoke( jarTool,
-                    System.out, System.err,
-                    getJarToolArguments() );
+            final Method jarRun = jarTool.getClass()
+                .getMethod( "run", PrintStream.class, PrintStream.class, String[].class );
+
+            if ( getLastModifiedTime() != null )
+            {
+                hasJarDateOption = isJarDateOptionSupported( jarRun );
+                getLogger().debug( "jar tool --date option is supported: " + hasJarDateOption );
+            }
+
+            Integer result = (Integer) jarRun.invoke( jarTool, System.out, System.err, getJarToolArguments() );
 
             if ( result != null && result != 0 )
             {
                 throw new ArchiverException( "Could not create modular JAR file. " +
                     "The JDK jar tool exited with " + result );
             }
+
+            if ( !hasJarDateOption && getLastModifiedTime() != null )
+            {
+                getLogger().debug( "Fix last modified time zip entries." );
+                // --date option not supported, fallback to rewrite the JAR file
+                // https://github.com/codehaus-plexus/plexus-archiver/issues/164
+                fixLastModifiedTimeZipEntries();
+            }
         }
         catch ( IOException | ReflectiveOperationException | SecurityException e )
         {
@@ -131,6 +158,36 @@ protected void postCreateArchive()
         }
     }
 
+    /**
+     * Fallback to rewrite the JAR file with the correct timestamp if the {@code --date} option is not available.
+     */
+    private void fixLastModifiedTimeZipEntries()
+        throws IOException
+    {
+        long timeMillis = getLastModifiedTime().toMillis();
+        Path destFile = getDestFile().toPath();
+        Path tmpZip = Files.createTempFile( destFile.getParent(), null, null );
+        try ( ZipFile zipFile = new ZipFile( getDestFile() );
+              ZipOutputStream out = new ZipOutputStream( Files.newOutputStream( tmpZip ) ) )
+        {
+            Enumeration<? extends ZipEntry> entries = zipFile.entries();
+            while ( entries.hasMoreElements() )
+            {
+                ZipEntry entry = entries.nextElement();
+                // Not using setLastModifiedTime(FileTime) as it sets the extended timestamp
+                // which is not compatible with the jar tool output.
+                entry.setTime( timeMillis );
+                out.putNextEntry( entry );
+                if ( !entry.isDirectory() )
+                {
+                    IOUtil.copy( zipFile.getInputStream( entry ), out );
+                }
+                out.closeEntry();
+            }
+        }
+        Files.move( tmpZip, destFile, StandardCopyOption.REPLACE_EXISTING );
+    }
+
     /**
      * Returns {@code true} if {@code path}
      * is a module descriptor.
@@ -201,6 +258,14 @@ private String[] getJarToolArguments()
             args.add( "--no-compress" );
         }
 
+        if ( hasJarDateOption )
+        {
+            // The --date option already normalize the time, so revert to the local time
+            FileTime localTime = revertToLocalTime( getLastModifiedTime() );
+            args.add( "--date" );
+            args.add( localTime.toString() );
+        }
+
         args.add( "-C" );
         args.add( tempEmptyDir.getAbsolutePath() );
         args.add( "." );
@@ -208,4 +273,36 @@ private String[] getJarToolArguments()
         return args.toArray( new String[0] );
     }
 
+    private static FileTime revertToLocalTime( FileTime time )
+    {
+        long restoreToLocalTime = time.toMillis();
+        Calendar cal = Calendar.getInstance( TimeZone.getDefault(), Locale.ROOT );
+        cal.setTimeInMillis( restoreToLocalTime );
+        restoreToLocalTime = restoreToLocalTime + ( cal.get( Calendar.ZONE_OFFSET ) + cal.get( Calendar.DST_OFFSET ) );
+        return FileTime.fromMillis( restoreToLocalTime );
+    }
+
+    /**
+     * Check support for {@code --date} option introduced since Java 17.0.3 (JDK-8279925).
+     *
+     * @return true if the JAR tool supports the {@code --date} option
+     */
+    private boolean isJarDateOptionSupported( Method runMethod )
+    {
+        try
+        {
+            // Test the output code validating the --date option.
+            String[] args = { "--date", "2099-12-31T23:59:59Z", "--version" };
+
+            PrintStream nullPrintStream = NullPrintStream.NULL_PRINT_STREAM;
+            Integer result = (Integer) runMethod.invoke( jarTool, nullPrintStream, nullPrintStream, args );
+
+            return result != null && result.intValue() == 0;
+        }
+        catch ( ReflectiveOperationException | SecurityException e )
+        {
+            return false;
+        }
+    }
+
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/jar/Manifest.java
=====================================
@@ -510,7 +510,7 @@ public Iterator<String> iterator()
          */
         public Attribute getAttribute( String attributeName )
         {
-            return attributes.get( attributeName.toLowerCase() );
+            return attributes.get( attributeName.toLowerCase( Locale.ENGLISH ) );
         }
 
         /**


=====================================
src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java
=====================================
@@ -283,7 +283,7 @@ else if ( longFileMode.isFailMode() )
                 te = new TarArchiveEntry( vPath );
             }
 
-            if ( getLastModifiedDate() == null )
+            if ( getLastModifiedTime() == null )
             {
                 long teLastModified = entry.getResource().getLastModified();
                 te.setModTime( teLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE
@@ -292,7 +292,7 @@ else if ( longFileMode.isFailMode() )
             }
             else
             {
-                te.setModTime( getLastModifiedDate() );
+                te.setModTime( getLastModifiedTime().toMillis() );
             }
 
             if ( entry.getType() == ArchiveEntry.SYMLINK )


=====================================
src/main/java/org/codehaus/plexus/archiver/util/Streams.java
=====================================
@@ -17,6 +17,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -32,6 +33,8 @@
 public class Streams
 {
 
+    public static final InputStream EMPTY_INPUTSTREAM = new ByteArrayInputStream( new byte[0] );
+
     public static BufferedInputStream bufferedInputStream( InputStream is )
     {
         return is instanceof BufferedInputStream


=====================================
src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java
=====================================
@@ -22,15 +22,18 @@
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.UncheckedIOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.attribute.FileTime;
 import java.util.Calendar;
-import java.util.Date;
 import java.util.Deque;
 import java.util.Hashtable;
+import java.util.Locale;
+import java.util.TimeZone;
 import java.util.concurrent.ExecutionException;
 import java.util.zip.CRC32;
 
@@ -39,7 +42,6 @@
 import org.apache.commons.compress.archivers.zip.ZipEncoding;
 import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
 import org.apache.commons.compress.parallel.InputStreamSupplier;
-import org.apache.commons.compress.utils.Charsets;
 import org.codehaus.plexus.archiver.AbstractArchiver;
 import org.codehaus.plexus.archiver.ArchiveEntry;
 import org.codehaus.plexus.archiver.Archiver;
@@ -48,6 +50,7 @@
 import org.codehaus.plexus.archiver.UnixStat;
 import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
 import org.codehaus.plexus.archiver.util.ResourceUtils;
+import org.codehaus.plexus.archiver.util.Streams;
 import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier;
 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
 import org.codehaus.plexus.util.FileUtils;
@@ -94,6 +97,7 @@
     /**
      * @deprecated Use {@link Archiver#setDuplicateBehavior(String)} instead.
      */
+    @Deprecated
     protected final String duplicate = Archiver.DUPLICATES_SKIP;
 
     /**
@@ -328,11 +332,11 @@ private ZipArchiveOutputStream.UnicodeExtraFieldPolicy getUnicodeExtraFieldPolic
             effectiveEncoding = Charset.defaultCharset().name();
         }
 
-        boolean utf8 = Charsets.UTF_8.name().equalsIgnoreCase( effectiveEncoding );
+        boolean utf8 = StandardCharsets.UTF_8.name().equalsIgnoreCase( effectiveEncoding );
 
         if ( !utf8 )
         {
-            for ( String alias : Charsets.UTF_8.aliases() )
+            for ( String alias : StandardCharsets.UTF_8.aliases() )
             {
                 if ( alias.equalsIgnoreCase( effectiveEncoding ) )
                 {
@@ -461,17 +465,16 @@ protected void zipFile( InputStreamSupplier in, ConcurrentJarCreator zOut, Strin
         if ( !skipWriting )
         {
             ZipArchiveEntry ze = new ZipArchiveEntry( vPath );
-            setTime( ze, lastModified );
+            setZipEntryTime( ze, lastModified );
 
             ze.setMethod( doCompress ? ZipArchiveEntry.DEFLATED : ZipArchiveEntry.STORED );
             ze.setUnixMode( UnixStat.FILE_FLAG | mode );
 
-            InputStream payload;
             if ( ze.isUnixSymlink() )
             {
                 final byte[] bytes = encodeArchiveEntry( symlinkDestination, getEncoding() );
-                payload = new ByteArrayInputStream( bytes );
-                zOut.addArchiveEntry( ze, createInputStreamSupplier( payload ), true );
+                InputStreamSupplier payload = () -> new ByteArrayInputStream( bytes );
+                zOut.addArchiveEntry( ze, payload, true );
             }
             else
             {
@@ -504,22 +507,15 @@ protected void zipFile( final ArchiveEntry entry, ConcurrentJarCreator zOut, Str
 
         final boolean b = entry.getResource() instanceof SymlinkDestinationSupplier;
         String symlinkTarget = b ? ( (SymlinkDestinationSupplier) entry.getResource() ).getSymlinkDestination() : null;
-        InputStreamSupplier in = new InputStreamSupplier()
-        {
-
-            @Override
-            public InputStream get()
+        InputStreamSupplier in = () -> {
+            try
             {
-                try
-                {
-                    return entry.getInputStream();
-                }
-                catch ( IOException e )
-                {
-                    throw new RuntimeException( e );
-                }
+                return entry.getInputStream();
+            }
+            catch ( IOException e )
+            {
+                throw new UncheckedIOException( e );
             }
-
         };
         try
         {
@@ -532,35 +528,26 @@ public InputStream get()
         }
     }
 
-    private void setTime( java.util.zip.ZipEntry zipEntry, long lastModified )
+    /**
+     * Set the ZipEntry dostime using the date if specified otherwise the original time.
+     *
+     * <p>Zip archives store file modification times with a granularity of two seconds, so the times will either be
+     * rounded up or down. If you round down, the archive will always seem out-of-date when you rerun the task, so the
+     * default is to round up. Rounding up may lead to a different type of problems like JSPs inside a web archive that
+     * seem to be slightly more recent than precompiled pages, rendering precompilation useless.
+     * plexus-archiver chooses to round up.
+     *
+     * @param zipEntry to set the last modified time
+     * @param lastModifiedTime to set in the zip entry only if {@link #getLastModifiedTime()} returns null
+     */
+    protected void setZipEntryTime( ZipArchiveEntry zipEntry, long lastModifiedTime )
     {
-        if ( getLastModifiedDate() != null )
+        if ( getLastModifiedTime() != null )
         {
-            lastModified = getLastModifiedDate().getTime();
+            lastModifiedTime = getLastModifiedTime().toMillis();
         }
 
-        // Zip archives store file modification times with a
-        // granularity of two seconds, so the times will either be rounded
-        // up or down. If you round down, the archive will always seem
-        // out-of-date when you rerun the task, so the default is to round
-        // up. Rounding up may lead to a different type of problems like
-        // JSPs inside a web archive that seem to be slightly more recent
-        // than precompiled pages, rendering precompilation useless.
-        // plexus-archiver chooses to round up.
-        zipEntry.setTime( lastModified + 1999 );
-
-        /*   Consider adding extended file stamp support.....
-
-         X5455_ExtendedTimestamp ts =  new X5455_ExtendedTimestamp();
-         ts.setModifyJavaTime(new Date(lastModified));
-         if (zipEntry.getExtra() != null){
-         // Uh-oh. What do we do now.
-         throw new IllegalStateException("DIdnt expect to see xtradata here ?");
-
-         }  else {
-         zipEntry.setExtra(ts.getLocalFileDataData());
-         }
-         */
+        zipEntry.setTime( lastModifiedTime + 1999 );
     }
 
     protected void zipDir( PlexusIoResource dir, ConcurrentJarCreator zOut, String vPath, int mode,
@@ -599,12 +586,12 @@ protected void zipDir( PlexusIoResource dir, ConcurrentJarCreator zOut, String v
 
             if ( dir != null && dir.isExisting() )
             {
-                setTime( ze, dir.getLastModified() );
+                setZipEntryTime( ze, dir.getLastModified() );
             }
             else
             {
                 // ZIPs store time with a granularity of 2 seconds, round up
-                setTime( ze, System.currentTimeMillis() );
+                setZipEntryTime( ze, System.currentTimeMillis() );
             }
             if ( !isSymlink )
             {
@@ -617,14 +604,14 @@ protected void zipDir( PlexusIoResource dir, ConcurrentJarCreator zOut, String v
 
             if ( !isSymlink )
             {
-                zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( "".getBytes() ) ), true );
+                zOut.addArchiveEntry( ze, () -> Streams.EMPTY_INPUTSTREAM, true );
             }
             else
             {
                 String symlinkDestination = ( (SymlinkDestinationSupplier) dir ).getSymlinkDestination();
                 final byte[] bytes = encodeArchiveEntry( symlinkDestination, encodingToUse );
                 ze.setMethod( ZipArchiveEntry.DEFLATED );
-                zOut.addArchiveEntry( ze, createInputStreamSupplier( new ByteArrayInputStream( bytes ) ), true );
+                zOut.addArchiveEntry( ze, () -> new ByteArrayInputStream( bytes ), true );
             }
         }
     }
@@ -640,20 +627,6 @@ private byte[] encodeArchiveEntry( String payload, String encoding )
         return encodedPayloadBytes;
     }
 
-    protected InputStreamSupplier createInputStreamSupplier( final InputStream inputStream )
-    {
-        return new InputStreamSupplier()
-        {
-
-            @Override
-            public InputStream get()
-            {
-                return inputStream;
-            }
-
-        };
-    }
-
     /**
      * Create an empty zip file
      *
@@ -838,12 +811,12 @@ protected String getArchiveType()
     }
 
     @Override
-    protected Date normalizeLastModifiedDate( Date lastModifiedDate )
+    protected FileTime normalizeLastModifiedTime( FileTime lastModifiedTime )
     {
         // timestamp of zip entries at zip storage level ignores timezone: managed in ZipEntry.setTime,
         // that turns javaToDosTime: need to revert the operation here to get reproducible
         // zip entry time
-        return new Date( dosToJavaTime( lastModifiedDate.getTime() ) );
+        return FileTime.fromMillis( dosToJavaTime( lastModifiedTime.toMillis() ) );
     }
 
     /**
@@ -854,7 +827,7 @@ protected Date normalizeLastModifiedDate( Date lastModifiedDate )
      */
     private static long dosToJavaTime( long dosTime )
     {
-        Calendar cal = Calendar.getInstance();
+        Calendar cal = Calendar.getInstance( TimeZone.getDefault(), Locale.ROOT );
         cal.setTimeInMillis( dosTime );
         return dosTime - ( cal.get( Calendar.ZONE_OFFSET ) + cal.get( Calendar.DST_OFFSET ) );
     }


=====================================
src/main/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreator.java
=====================================
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.SequenceInputStream;
+import java.io.UncheckedIOException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
 import java.util.zip.Deflater;
@@ -30,12 +31,12 @@
 import org.apache.commons.compress.archivers.zip.StreamCompressor;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntryRequest;
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntryRequestSupplier;
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
 import org.apache.commons.compress.parallel.InputStreamSupplier;
 import org.apache.commons.compress.parallel.ScatterGatherBackingStore;
 import org.apache.commons.compress.parallel.ScatterGatherBackingStoreSupplier;
-import org.codehaus.plexus.util.IOUtil;
+import org.apache.commons.compress.utils.IOUtils;
+import org.codehaus.plexus.archiver.util.Streams;
 
 import static org.apache.commons.compress.archivers.zip.ZipArchiveEntryRequest.createZipArchiveEntryRequest;
 
@@ -67,6 +68,7 @@
             this.threshold = threshold;
         }
 
+        @Override
         public ScatterGatherBackingStore get()
             throws IOException
         {
@@ -152,46 +154,28 @@ public void addArchiveEntry( final ZipArchiveEntry zipArchiveEntry, final InputS
         {
             throw new IllegalArgumentException( "Method must be set on the supplied zipArchiveEntry" );
         }
-        if ( "META-INF".equals( zipArchiveEntry.getName() ) || "META-INF/".equals( zipArchiveEntry.getName() ) )
+        final String zipEntryName = zipArchiveEntry.getName();
+        if ( "META-INF".equals( zipEntryName ) || "META-INF/".equals( zipEntryName ) )
         {
-            InputStream payload = source.get();
             // TODO This should be enforced because META-INF non-directory does not make any sense?!
             if ( zipArchiveEntry.isDirectory() )
             {
                 zipArchiveEntry.setMethod( ZipEntry.STORED );
             }
-            metaInfDir.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry,
-                                                                      createInputStreamSupplier( payload ) ) );
-
-            payload.close();
+            metaInfDir.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, source ) );
         }
-        else if ( "META-INF/MANIFEST.MF".equals( zipArchiveEntry.getName() ) )
+        else if ( "META-INF/MANIFEST.MF".equals( zipEntryName ) )
         {
-            InputStream payload = source.get();
-            // TODO This should be enforced because META-INF/MANIFEST as non-file does not make any sense?!
-            if ( zipArchiveEntry.isDirectory() )
-            {
-                zipArchiveEntry.setMethod( ZipEntry.STORED );
-            }
-            manifest.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry,
-                                                                    createInputStreamSupplier( payload ) ) );
-
-            payload.close();
+            manifest.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, source ) );
         }
         else if ( zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink() )
         {
-            final ByteArrayInputStream payload = new ByteArrayInputStream( new byte[]
-            {
-            } );
-
-            directories.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry, createInputStreamSupplier(
-                                                                       payload ) ) );
-
-            payload.close();
+            directories.addArchiveEntry( createZipArchiveEntryRequest( zipArchiveEntry,
+                                                                       () -> Streams.EMPTY_INPUTSTREAM ) );
         }
         else if ( addInParallel )
         {
-            parallelScatterZipCreator.addArchiveEntry( createEntrySupplier( zipArchiveEntry, source ) );
+            parallelScatterZipCreator.addArchiveEntry( () -> createEntry( zipArchiveEntry, source ) );
         }
         else
         {
@@ -199,20 +183,6 @@ else if ( addInParallel )
         }
     }
 
-    private InputStreamSupplier createInputStreamSupplier( final InputStream payload )
-    {
-        return new InputStreamSupplier()
-        {
-
-            @Override
-            public InputStream get()
-            {
-                return payload;
-            }
-
-        };
-    }
-
     public void writeTo( ZipArchiveOutputStream targetStream ) throws IOException, ExecutionException,
                                                                       InterruptedException
     {
@@ -240,48 +210,24 @@ public String getStatisticsMessage()
         return parallelScatterZipCreator.getStatisticsMessage() + " Zip Close: " + zipCloseElapsed + "ms";
     }
 
-    private ZipArchiveEntryRequestSupplier createEntrySupplier( final ZipArchiveEntry zipArchiveEntry,
-                                                                final InputStreamSupplier inputStreamSupplier )
-    {
-
-        return new ZipArchiveEntryRequestSupplier()
-        {
-
-            @Override
-            public ZipArchiveEntryRequest get()
-            {
-                try
-                {
-                    return createEntry( zipArchiveEntry, inputStreamSupplier );
-                }
-                catch ( IOException e )
-                {
-                    throw new RuntimeException( e );
-                }
-            }
-
-        };
-    }
-
     private ZipArchiveEntryRequest createEntry( final ZipArchiveEntry zipArchiveEntry,
-                                                final InputStreamSupplier inputStreamSupplier ) throws IOException
+                                                final InputStreamSupplier inputStreamSupplier )
     {
         // if we re-compress the zip files there is no need to look at the input stream
-
         if ( compressAddedZips )
         {
             return createZipArchiveEntryRequest( zipArchiveEntry, inputStreamSupplier );
         }
 
-        // otherwise we should inspect the first four bites to see if the input stream is zip file or not
-
         InputStream is = inputStreamSupplier.get();
+        // otherwise we should inspect the first four bytes to see if the input stream is zip file or not
         byte[] header = new byte[4];
         try
         {
             int read = is.read( header );
             int compressionMethod = zipArchiveEntry.getMethod();
-            if ( isZipHeader( header ) ) {
+            if ( isZipHeader( header ) )
+            {
                 compressionMethod = ZipEntry.STORED;
             }
 
@@ -291,8 +237,8 @@ private ZipArchiveEntryRequest createEntry( final ZipArchiveEntry zipArchiveEntr
         }
         catch ( IOException e )
         {
-            IOUtil.close( is );
-            throw e;
+            IOUtils.closeQuietly( is );
+            throw new UncheckedIOException( e );
         }
     }
 
@@ -303,18 +249,7 @@ private boolean isZipHeader( byte[] header )
 
     private InputStreamSupplier prependBytesToStream( final byte[] bytes, final int len, final InputStream stream )
     {
-        return new InputStreamSupplier() {
-
-            @Override
-            public InputStream get()
-            {
-                return len > 0
-                            ? new SequenceInputStream( new ByteArrayInputStream( bytes, 0, len ), stream )
-                            : stream;
-            }
-
-        };
-
+        return () -> len > 0 ? new SequenceInputStream( new ByteArrayInputStream( bytes, 0, len ), stream ) : stream;
     }
 
 }


=====================================
src/main/java/org/codehaus/plexus/archiver/zip/ZipResource.java
=====================================
@@ -29,7 +29,7 @@ public class ZipResource extends AbstractPlexusIoResource
 
     public ZipResource( ZipFile zipFile, ZipArchiveEntry entry, InputStreamTransformer streamTransformer )
     {
-        super( entry.getName(), getLastModofied( entry ),
+        super( entry.getName(), getLastModified( entry ),
                entry.isDirectory() ? PlexusIoResource.UNKNOWN_RESOURCE_SIZE : entry.getSize(), !entry.isDirectory(),
                entry.isDirectory(), true );
 
@@ -38,10 +38,10 @@ public ZipResource( ZipFile zipFile, ZipArchiveEntry entry, InputStreamTransform
         this.streamTransformer = streamTransformer;
     }
 
-    private static long getLastModofied( ZipArchiveEntry entry )
+    private static long getLastModified( ZipArchiveEntry entry )
     {
-        long l = entry.getLastModifiedDate().getTime();
-        return l == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : l;
+        long time = entry.getTime();
+        return time == -1 ? PlexusIoResource.UNKNOWN_MODIFICATION_DATE : time;
     }
 
     @Override


=====================================
src/test/java/org/codehaus/plexus/archiver/DuplicateFilesTest.java
=====================================
@@ -3,14 +3,13 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileReader;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.Enumeration;
 
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.codehaus.plexus.DefaultPlexusContainer;
 import org.codehaus.plexus.PlexusTestCase;
 import org.codehaus.plexus.archiver.tar.TarArchiver;
 import org.codehaus.plexus.archiver.tar.TarLongFileMode;
@@ -34,7 +33,8 @@ public void setUp()
         throws Exception
     {
         super.setUp();
-        getContainer().getLoggerManager().setThreshold( Logger.LEVEL_DEBUG );
+        DefaultPlexusContainer container = (DefaultPlexusContainer) getContainer();
+        container.getLoggerManager().setThreshold( Logger.LEVEL_DEBUG );
     }
 
     public void testZipArchiver()


=====================================
src/test/java/org/codehaus/plexus/archiver/jar/BaseJarArchiverTest.java
=====================================
@@ -16,23 +16,24 @@
  */
 package org.codehaus.plexus.archiver.jar;
 
-import org.codehaus.plexus.archiver.ArchiverException;
-import org.codehaus.plexus.util.IOUtil;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.Calendar;
 import java.util.Enumeration;
+import java.util.Locale;
+import java.util.TimeZone;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.util.IOUtil;
+import org.junit.Test;
 
 public abstract class BaseJarArchiverTest
 {
@@ -73,6 +74,13 @@ public void testCreateJar()
         }
     }
 
+    protected static long normalizeLastModifiedTime( long dosTime )
+    {
+        Calendar cal = Calendar.getInstance( TimeZone.getDefault(), Locale.ROOT );
+        cal.setTimeInMillis( dosTime );
+        return dosTime - ( cal.get( Calendar.ZONE_OFFSET ) + cal.get( Calendar.DST_OFFSET ) );
+    }
+
     protected abstract JarArchiver getJarArchiver();
 
 }


=====================================
src/test/java/org/codehaus/plexus/archiver/jar/JarArchiverTest.java
=====================================
@@ -1,10 +1,20 @@
 package org.codehaus.plexus.archiver.jar;
 
+import static org.junit.Assert.assertEquals;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Enumeration;
 import java.util.Random;
+import java.util.TimeZone;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 import org.codehaus.plexus.archiver.ArchiverException;
 import org.junit.Test;
@@ -76,6 +86,67 @@ public void testVeryLargeJar()
         archiver.createArchive();
     }
 
+    @Test
+    public void testReproducibleBuild()
+        throws IOException, ManifestException, ParseException
+    {
+        String[] tzList = { "America/Managua", "America/New_York", "America/Buenos_Aires", "America/Sao_Paulo",
+            "America/Los_Angeles", "Africa/Cairo", "Africa/Lagos", "Africa/Nairobi", "Europe/Lisbon", "Europe/Madrid",
+            "Europe/Moscow", "Europe/Oslo", "Australia/Sydney", "Asia/Tokyo", "Asia/Singapore", "Asia/Qatar",
+            "Asia/Seoul", "Atlantic/Bermuda", "UTC", "GMT", "Etc/GMT-14" };
+        for ( String tzId : tzList )
+        {
+            // Every single run with different Time Zone should set the same modification time.
+            createReproducibleBuild( tzId );
+        }
+    }
+
+    private void createReproducibleBuild( String timeZoneId )
+        throws IOException, ManifestException, ParseException
+    {
+        final TimeZone defaultTz = TimeZone.getDefault();
+        TimeZone.setDefault( TimeZone.getTimeZone( timeZoneId ) );
+        try
+        {
+            String tzName = timeZoneId.substring( timeZoneId.lastIndexOf( '/' ) + 1 );
+            Path jarFile = Files.createTempFile( "JarArchiverTest-" + tzName + "-", ".jar" );
+            jarFile.toFile().deleteOnExit();
+
+            Manifest manifest = new Manifest();
+            Manifest.Attribute attribute = new Manifest.Attribute( "Main-Class", "com.example.app.Main" );
+            manifest.addConfiguredAttribute( attribute );
+
+            JarArchiver archiver = getJarArchiver();
+            archiver.setDestFile( jarFile.toFile() );
+            archiver.addConfiguredManifest( manifest );
+            archiver.addDirectory( new File( "src/test/resources/java-classes" ) );
+
+            SimpleDateFormat isoFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssXXX" );
+            long parsedTime = isoFormat.parse( "2038-01-19T03:14:08Z" ).getTime();
+            FileTime lastModTime = FileTime.fromMillis( parsedTime );
+
+            archiver.configureReproducibleBuild( lastModTime );
+            archiver.createArchive();
+
+            // zip 2 seconds precision, normalized to UTC
+            long expectedTime = normalizeLastModifiedTime( parsedTime - ( parsedTime % 2000 ) );
+            try ( ZipFile zip = new ZipFile( jarFile.toFile() ) )
+            {
+                Enumeration<? extends ZipEntry> entries = zip.entries();
+                while ( entries.hasMoreElements() )
+                {
+                    ZipEntry entry = entries.nextElement();
+                    long time = entry.getTime();
+                    assertEquals( "last modification time does not match", expectedTime, time );
+                }
+            }
+        }
+        finally
+        {
+            TimeZone.setDefault( defaultTz );
+        }
+    }
+
     @Override
     protected JarArchiver getJarArchiver()
     {


=====================================
src/test/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiverTest.java
=====================================
@@ -16,9 +16,16 @@
  */
 package org.codehaus.plexus.archiver.jar;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
 import java.io.File;
 import java.io.InputStream;
 import java.lang.reflect.Method;
+import java.nio.file.attribute.FileTime;
+import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashSet;
@@ -30,10 +37,6 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
 public class JarToolModularJarArchiverTest
     extends BaseJarArchiverTest
 {
@@ -252,25 +255,57 @@ public void testModularMultiReleaseJar()
     {
         assumeTrue( modulesAreSupported() );
 
+        // Add two module-info.class, one on the root and one on the multi-release dir.
+        archiver.addFile( new File( "src/test/resources/java-module-descriptor/module-info.class" ),
+                          "META-INF/versions/9/module-info.class" );
         archiver.addFile( new File( "src/test/resources/java-module-descriptor/module-info.class" ),
-            "META-INF/versions/9/module-info.class" );
+                          "module-info.class" );
+
         Manifest manifest = new Manifest();
+        manifest.addConfiguredAttribute( new Manifest.Attribute( "Main-Class", "com.example.app.Main2" ) );
         manifest.addConfiguredAttribute( new Manifest.Attribute( "Multi-Release", "true" ) );
         archiver.addConfiguredManifest( manifest );
+
         archiver.setModuleVersion( "1.0.0" );
+        // This attribute overwrites the one from the manifest.
         archiver.setModuleMainClass( "com.example.app.Main" );
 
+        SimpleDateFormat isoFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssXXX" );
+        long dateTimeMillis = isoFormat.parse( "2020-02-29T23:59:59Z" ).getTime();
+        FileTime lastModTime = FileTime.fromMillis( dateTimeMillis );
+
+        archiver.configureReproducibleBuild( lastModTime );
         archiver.createArchive();
 
+        // Round-down two seconds precision
+        long roundedDown = lastModTime.toMillis() - ( lastModTime.toMillis() % 2000 );
+        // Normalize to UTC
+        long expectedLastModifiedTime = normalizeLastModifiedTime( roundedDown );
+
         // verify that the resulting modular jar has the proper version and main class set
         try ( ZipFile resultingArchive = new ZipFile( archiver.getDestFile() ) )
         {
-            ZipEntry moduleDescriptorEntry =
-                resultingArchive.getEntry( "META-INF/versions/9/module-info.class" );
+            ZipEntry moduleDescriptorEntry = resultingArchive.getEntry( "META-INF/versions/9/module-info.class" );
             InputStream resultingModuleDescriptor = resultingArchive.getInputStream( moduleDescriptorEntry );
+            assertModuleDescriptor( resultingModuleDescriptor, "1.0.0", "com.example.app.Main", "com.example.app",
+                                    "com.example.resources" );
 
-            assertModuleDescriptor( resultingModuleDescriptor,
-                    "1.0.0", "com.example.app.Main", "com.example.app", "com.example.resources" );
+            ZipEntry rootModuleDescriptorEntry = resultingArchive.getEntry( "module-info.class" );
+            InputStream rootResultingModuleDescriptor = resultingArchive.getInputStream( rootModuleDescriptorEntry );
+            assertModuleDescriptor( rootResultingModuleDescriptor, "1.0.0", "com.example.app.Main", "com.example.app",
+                                    "com.example.resources" );
+
+            // verify every entry has the correct last modified time
+            Enumeration<? extends ZipEntry> entries = resultingArchive.entries();
+            while ( entries.hasMoreElements() )
+            {
+                ZipEntry element = entries.nextElement();
+                assertEquals( "Last Modified Time does not match with expected", expectedLastModifiedTime,
+                              element.getTime() );
+                FileTime expectedFileTime = FileTime.fromMillis( expectedLastModifiedTime );
+                assertEquals( "Last Modified Time does not match with expected", expectedFileTime,
+                              element.getLastModifiedTime() );
+            }
         }
     }
 


=====================================
src/test/java/org/codehaus/plexus/archiver/zip/ArchiveFileComparator.java
=====================================
@@ -122,7 +122,7 @@ private static void assertEquals( ZipFile file1, ZipArchiveEntry entry1,
     {
         Assert.assertEquals( entry1.isDirectory(), entry2.isDirectory() );
         Assert.assertEquals( entry1.isUnixSymlink(), entry2.isUnixSymlink() );
-        long timeDelta = entry1.getLastModifiedDate().getTime() - entry2.getLastModifiedDate().getTime();
+        long timeDelta = entry1.getTime() - entry2.getTime();
         Assert.assertTrue( Math.abs( timeDelta ) <= 1000 );
 
         final InputStream is1 = file1.getInputStream( entry1 );


=====================================
src/test/java/org/codehaus/plexus/archiver/zip/ConcurrentJarCreatorTest.java
=====================================
@@ -1,15 +1,14 @@
 package org.codehaus.plexus.archiver.zip;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.nio.file.Files;
 
 import org.apache.commons.compress.archivers.zip.UnixStat;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
-import org.apache.commons.compress.parallel.InputStreamSupplier;
 import org.apache.commons.compress.utils.IOUtils;
 import org.codehaus.plexus.util.DirectoryScanner;
 import org.junit.Ignore;
@@ -77,21 +76,15 @@ private void doAddAll( String base, ConcurrentJarCreator mos ) throws IOExceptio
             final File file = new File( base, fileName );
             ZipArchiveEntry za = createZipArchiveEntry( file, fileName );
 
-            mos.addArchiveEntry( za, new InputStreamSupplier()
-            {
-
-                public InputStream get()
+            mos.addArchiveEntry( za, () -> {
+                try
                 {
-                    try
-                    {
-                        return file.isFile() ? Files.newInputStream( file.toPath() ) : null;
-                    }
-                    catch ( IOException e )
-                    {
-                        throw new RuntimeException( e );
-                    }
+                    return file.isFile() ? Files.newInputStream( file.toPath() ) : null;
+                }
+                catch ( IOException e )
+                {
+                    throw new UncheckedIOException( e );
                 }
-
             }, true );
         }
 


=====================================
src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java
=====================================
@@ -26,13 +26,12 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
 import java.text.DateFormat;
 import java.text.ParseException;
@@ -78,6 +77,7 @@
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.Os;
+import org.junit.Test;
 
 /**
  * @author Emmanuel Venisse
@@ -633,27 +633,34 @@ public void testSymlinkArchivedFileSet()
      * Zip archives store file modification times with a granularity of two seconds.
      * Verify that ZipArchiver rounds up the last modified time.
      */
+    @Test
     public void testLastModifiedTimeRounding()
         throws Exception
     {
-        File oddSecondsTimestampFile = File.createTempFile( "odd-seconds-timestamp", null );
-        oddSecondsTimestampFile.deleteOnExit();
+        Path oddSecondsTimestampFile = Files.createTempFile( "odd-seconds-timestamp", null );
+        oddSecondsTimestampFile.toFile().deleteOnExit();
         // The milliseconds part is set to zero as not all filesystem support timestamp more granular than second.
-        Files.setLastModifiedTime( oddSecondsTimestampFile.toPath(), FileTime.fromMillis( 1534189011_000L ) );
-        File evenSecondsTimestampFile = File.createTempFile( "even-seconds-timestamp", null );
-        evenSecondsTimestampFile.deleteOnExit();
-        Files.setLastModifiedTime( evenSecondsTimestampFile.toPath(), FileTime.fromMillis( 1534189012_000L ) );
+        Files.setLastModifiedTime( oddSecondsTimestampFile, FileTime.fromMillis( 1534189011_000L ) );
+        Path evenSecondsTimestampFile = Files.createTempFile( "even-seconds-timestamp", null );
+        evenSecondsTimestampFile.toFile().deleteOnExit();
+        Files.setLastModifiedTime( evenSecondsTimestampFile, FileTime.fromMillis( 1534189012_000L ) );
 
         File destFile = getTestFile( "target/output/last-modified-time.zip" );
         ZipArchiver archiver = getZipArchiver( destFile );
-        archiver.addFile( oddSecondsTimestampFile, "odd-seconds" );
-        archiver.addFile( evenSecondsTimestampFile, "even-seconds" );
+        archiver.addFile( oddSecondsTimestampFile.toFile(), "odd-seconds" );
+        archiver.addFile( evenSecondsTimestampFile.toFile(), "even-seconds" );
         archiver.createArchive();
 
         // verify that the last modified time of the entry is equal or newer than the original file
-        ZipFile resultingZipFile = new ZipFile( destFile );
-        assertEquals( 1534189012_000L, resultingZipFile.getEntry( "odd-seconds" ).getTime() );
-        assertEquals( 1534189012_000L, resultingZipFile.getEntry( "even-seconds" ).getTime() );
+        try ( ZipFile resultingZipFile = new ZipFile( destFile ) )
+        {
+            assertEquals( 1534189012_000L, resultingZipFile.getEntry( "odd-seconds" ).getTime() );
+            assertEquals( 1534189012_000L, resultingZipFile.getEntry( "even-seconds" ).getTime() );
+
+            FileTime expected = FileTime.fromMillis( 1534189012_000L );
+            assertEquals( expected, resultingZipFile.getEntry( "odd-seconds" ).getLastModifiedTime() );
+            assertEquals( expected, resultingZipFile.getEntry( "even-seconds" ).getLastModifiedTime() );
+        }
     }
 
     /*
@@ -901,7 +908,7 @@ public void testFixedEntryModificationTime()
 
         final File zipFile = getTestFile( "target/output/zip-with-fixed-entry-modification-times.zip" );
         final ZipArchiver archiver = getZipArchiver( zipFile );
-        archiver.setLastModifiedDate( new Date( almostMinDosTime ) );
+        archiver.setLastModifiedTime( FileTime.fromMillis( almostMinDosTime ) );
         archiver.addDirectory( new File( "src/test/resources/zip-timestamp" ) );
         archiver.createArchive();
 



View it on GitLab: https://salsa.debian.org/java-team/plexus-archiver/-/commit/fab62d2492f565a295c35edf292558ce9a594d34

-- 
View it on GitLab: https://salsa.debian.org/java-team/plexus-archiver/-/commit/fab62d2492f565a295c35edf292558ce9a594d34
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20220929/2d08b521/attachment.htm>


More information about the pkg-java-commits mailing list