You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2019/10/19 06:08:13 UTC

[maven-archiver] branch master updated: MSHARED-837 add an API to configure outputTimestamp for Reproducible B

This is an automated email from the ASF dual-hosted git repository.

hboutemy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-archiver.git


The following commit(s) were added to refs/heads/master by this push:
     new 60f166a  MSHARED-837 add an API to configure outputTimestamp for Reproducible B
60f166a is described below

commit 60f166a66d485c7963035a97c76ca8fd9872d157
Author: Hervé Boutemy <hb...@apache.org>
AuthorDate: Sat Oct 5 19:21:05 2019 +0200

    MSHARED-837 add an API to configure outputTimestamp for Reproducible B
---
 pom.xml                                            |  2 +-
 .../org/apache/maven/archiver/MavenArchiver.java   | 66 ++++++++++++++++++++--
 .../apache/maven/archiver/MavenArchiverTest.java   | 59 +++++++++++++++++++
 3 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2cede4a..ee1a1ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
   <groupId>org.apache.maven</groupId>
   <artifactId>maven-archiver</artifactId>
-  <version>3.4.1-SNAPSHOT</version>
+  <version>3.5.0-SNAPSHOT</version>
 
   <name>Apache Maven Archiver</name>
   <description>Provides utility methods for creating JARs and other archive files from a Maven project.</description>
diff --git a/src/main/java/org/apache/maven/archiver/MavenArchiver.java b/src/main/java/org/apache/maven/archiver/MavenArchiver.java
index 521f5c2..013aacd 100644
--- a/src/main/java/org/apache/maven/archiver/MavenArchiver.java
+++ b/src/main/java/org/apache/maven/archiver/MavenArchiver.java
@@ -42,8 +42,12 @@ import org.apache.maven.shared.utils.StringUtils;
 import javax.lang.model.SourceVersion;
 import java.io.File;
 import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -724,11 +728,11 @@ public class MavenArchiver
 
     /**
      * Define a value for "Created By" entry.
-     * 
+     *
      * @param description description of the plugin, like "Maven Source Plugin"
      * @param groupId groupId where to get version in pom.properties
      * @param artifactId artifactId where to get version in pom.properties
-     * @since 3.4.1
+     * @since 3.5.0
      */
     public void setCreatedBy( String description, String groupId, String artifactId )
     {
@@ -749,13 +753,67 @@ public class MavenArchiver
     /**
      * Add "Build-Jdk-Spec" entry as part of default manifest entries (true by default).
      * For plugins whose output is not impacted by JDK release (like maven-source-plugin), adding
-     * Jdk spec adds unnecessary requirement on JDK version used at build to get reproducible result. 
+     * Jdk spec adds unnecessary requirement on JDK version used at build to get reproducible result.
      *
-     * @since 3.4.1
+     * @since 3.5.0
      */
     public void setBuildJdkSpecDefaultEntry( boolean buildJdkSpecDefaultEntry )
     {
         this.buildJdkSpecDefaultEntry = buildJdkSpecDefaultEntry;
     }
 
+    /**
+     * Parse output timestamp configured for Reproducible Builds' archive entries, either formatted as ISO 8601
+     * <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
+     * <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>.
+     *
+     * @param outputTimestamp the value of <code>${project.build.outputTimestamp}</code> (may be <code>null</code>)
+     * @return the parsed timestamp, may be <code>null</code> if <code>null</code> input or input contains only 1
+     *         character
+     * @since 3.5.0
+     */
+    public Date parseOutputTimestamp( String outputTimestamp )
+    {
+        if ( StringUtils.isNumeric( outputTimestamp ) && StringUtils.isNotEmpty( outputTimestamp ) )
+        {
+            return new Date( Long.parseLong( outputTimestamp ) * 1000 );
+        }
+
+        if ( outputTimestamp == null || outputTimestamp.length() < 2 )
+        {
+            // no timestamp configured (1 character configuration is useful to override a full value during pom
+            // inheritance)
+            return null;
+        }
+
+        DateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssXXX" );
+        try
+        {
+            return df.parse( outputTimestamp );
+        }
+        catch ( ParseException pe )
+        {
+            throw new IllegalArgumentException( "Invalid project.build.outputTimestamp value '" + outputTimestamp + "'",
+                                                pe );
+        }
+    }
+
+    /**
+     * Configure Reproducible Builds archive creation if a timestamp is provided.
+     *
+     * @param outputTimestamp the value of <code>${project.build.outputTimestamp}</code> (may be <code>null</code>)
+     * @return the parsed timestamp
+     * @since 3.5.0
+     * @see #parseOutputTimestamp
+     * @see Archiver#configureReproducible
+     */
+    public Date configureReproducible( String outputTimestamp )
+    {
+        Date outputDate = parseOutputTimestamp( outputTimestamp );
+        if ( outputDate != null )
+        {
+            getArchiver().configureReproducible( outputDate );
+        }
+        return outputDate;
+    }
 }
diff --git a/src/test/java/org/apache/maven/archiver/MavenArchiverTest.java b/src/test/java/org/apache/maven/archiver/MavenArchiverTest.java
index 6e0e81e..2f5965d 100644
--- a/src/test/java/org/apache/maven/archiver/MavenArchiverTest.java
+++ b/src/test/java/org/apache/maven/archiver/MavenArchiverTest.java
@@ -1503,4 +1503,63 @@ public class MavenArchiverTest
         }
 
     }
+
+    @Test
+    public void testParseOutputTimestamp()
+    {
+        MavenArchiver archiver = new MavenArchiver();
+
+        assertNull( archiver.parseOutputTimestamp( null ) );
+        assertNull( archiver.parseOutputTimestamp( "" ) );
+        assertNull( archiver.parseOutputTimestamp( "." ) );
+        assertNull( archiver.parseOutputTimestamp( " " ) );
+        assertNull( archiver.parseOutputTimestamp( "_" ) );
+
+        assertEquals( 1570300662000L, archiver.parseOutputTimestamp( "1570300662" ).getTime() );
+
+        assertEquals( 1570300662000L, archiver.parseOutputTimestamp( "2019-10-05T18:37:42Z" ).getTime() );
+        assertEquals( 1570300662000L, archiver.parseOutputTimestamp( "2019-10-05T20:37:42+02:00" ).getTime() );
+        assertEquals( 1570300662000L, archiver.parseOutputTimestamp( "2019-10-05T16:37:42-02:00" ).getTime() );
+
+        // These must result in IAE because we expect extended ISO format only (ie with - separator for date and
+        // : separator for timezone), hence the XXX SimpleDateFormat for tz offset
+        // X SimpleDateFormat accepts timezone without separator while date has separator, which is a mix between
+        // basic (no separators, both for date and timezone) and extended (separator for both)
+        try
+        {
+            archiver.parseOutputTimestamp( "2019-10-05T20:37:42+0200" );
+            fail();
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+        try
+        {
+            archiver.parseOutputTimestamp( "2019-10-05T20:37:42-0200" );
+            fail();
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+
+        // These unfortunately fail although the input is valid according to ISO 8601
+        // SDF does not allow strict telescoping parsing w/o permitting invalid input as depicted above.
+        // One has to use the new Java Time API for this.
+        try
+        {
+            archiver.parseOutputTimestamp( "2019-10-05T20:37:42+02" );
+            fail();
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+        try
+        {
+            archiver.parseOutputTimestamp( "2019-10-05T20:37:42-02" );
+            fail();
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+    }
 }