[MEAR-283] enforce timestamp of repackaged skinny war

Timestamp of repackaged EAR modules following same rules / value as
timestamp of packaged modules to support reproducible builds when
skinnyWar option is turned on
diff --git a/src/it/basic/verify.bsh b/src/it/basic/verify.bsh
index 0e96a92..d5e9275 100644
--- a/src/it/basic/verify.bsh
+++ b/src/it/basic/verify.bsh
@@ -35,13 +35,28 @@
     "META-INF/application.xml",
     "META-INF/appserver-application.xml",
 };
+
+// Reproducible Builds: check that every entry has the same timestamp  
+long entryTime = -1;
+
 for ( String included : includedEntries )
 {
     System.out.println( "Checking for existence of " + included );
-    if ( jar.getEntry( included ) == null )
+    JarEntry jarEntry = jar.getEntry( included );
+    if ( jarEntry == null )
     {
         throw new IllegalStateException( "Missing archive entry: " + included );
     }
+    if ( entryTime < 0 )
+    {
+        entryTime = jarEntry.getTime();
+    }
+    if ( entryTime != jarEntry.getTime() )
+    {
+        throw new IllegalStateException( "Invalid jar entry time: " + jarEntry.getTime()
+            + " of archive entry: " + included
+            + ", expected: " + entryTime );
+    }
 }
 
 jar.close();
diff --git a/src/it/skinny-wars/ear-module/pom.xml b/src/it/skinny-wars/ear-module/pom.xml
index 24981aa..6f9911a 100644
--- a/src/it/skinny-wars/ear-module/pom.xml
+++ b/src/it/skinny-wars/ear-module/pom.xml
@@ -27,6 +27,10 @@
   <version>1.0</version>
   <packaging>ear</packaging>
 
+  <properties>
+    <project.build.outputTimestamp>2020-05-01T12:12:12Z</project.build.outputTimestamp>
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>commons-lang</groupId>
diff --git a/src/it/skinny-wars/verify.bsh b/src/it/skinny-wars/verify.bsh
index f501413..279331b 100644
--- a/src/it/skinny-wars/verify.bsh
+++ b/src/it/skinny-wars/verify.bsh
@@ -35,12 +35,27 @@
     "WEB-INF/web.xml",
     "META-INF/MANIFEST.MF"
 };
+
+// Reproducible Builds: check that every entry has the same timestamp  
+long entryTime = -1;
+
 for ( String included : includedEntries )
 {
     System.out.println( "Checking for included archive entry " + included );
-    if ( jar.getEntry( included ) == null )
+    JarEntry jarEntry = jar.getEntry( included );
+    if ( jarEntry == null )
     {
-        throw new IllegalStateException( "Missing archive entry: " + included );
+        throw new IllegalStateException( "Missing WAR entry: " + included );
+    }
+    if ( entryTime < 0 )
+    {
+        entryTime = jarEntry.getTime();
+    }
+    if ( entryTime != jarEntry.getTime() )
+    {
+        throw new IllegalStateException( "Invalid jar entry time: " + jarEntry.getTime()
+            + " of archive entry: " + included
+            + ", expected: " + entryTime );
     }
 }
 
diff --git a/src/main/java/org/apache/maven/plugins/ear/EarMojo.java b/src/main/java/org/apache/maven/plugins/ear/EarMojo.java
index 374339b..4d1841e 100644
--- a/src/main/java/org/apache/maven/plugins/ear/EarMojo.java
+++ b/src/main/java/org/apache/maven/plugins/ear/EarMojo.java
@@ -33,6 +33,7 @@
 import java.util.Arrays;

 import java.util.Collection;

 import java.util.Collections;

+import java.util.Date;

 import java.util.List;

 import java.util.zip.ZipException;

 

@@ -284,7 +285,33 @@
         // Initializes ear modules

         super.execute();

 

+        final File earFile;

+        final MavenArchiver archiver;

+        final Date reproducibleLastModifiedDate;

+        try

+        {

+            earFile = getEarFile( outputDirectory, finalName, classifier );

+            archiver = new EarMavenArchiver( getModules() );

+            final JarArchiver theJarArchiver = getJarArchiver();

+            getLog().debug( "Jar archiver implementation [" + theJarArchiver.getClass().getName() + "]" );

+            archiver.setArchiver( theJarArchiver );

+            archiver.setOutputFile( earFile );

+

+            archiver.setCreatedBy( "Maven EAR Plugin", "org.apache.maven.plugins", "maven-ear-plugin" );

+

+            // configure for Reproducible Builds based on outputTimestamp value

+            reproducibleLastModifiedDate = archiver.configureReproducible( outputTimestamp );

+        }

+        catch ( Exception e )

+        {

+            throw new MojoExecutionException( "Error assembling EAR", e );

+        }

+

         zipArchiver.setUseJvmChmod( useJvmChmod );

+        if ( reproducibleLastModifiedDate != null )

+        {

+            zipArchiver.configureReproducible( reproducibleLastModifiedDate );

+        }

         zipUnArchiver.setUseJvmChmod( useJvmChmod );

 

         final JavaEEVersion javaEEVersion = JavaEEVersion.getJavaEEVersion( version );

@@ -381,18 +408,6 @@
 

         try

         {

-            File earFile = getEarFile( outputDirectory, finalName, classifier );

-            final MavenArchiver archiver = new EarMavenArchiver( getModules() );

-            final JarArchiver theJarArchiver = getJarArchiver();

-            getLog().debug( "Jar archiver implementation [" + theJarArchiver.getClass().getName() + "]" );

-            archiver.setArchiver( theJarArchiver );

-            archiver.setOutputFile( earFile );

-

-            archiver.setCreatedBy( "Maven EAR Plugin", "org.apache.maven.plugins", "maven-ear-plugin" );

-

-            // configure for Reproducible Builds based on outputTimestamp value

-            archiver.configureReproducible( outputTimestamp );

-

             getLog().debug( "Excluding " + Arrays.asList( getPackagingExcludes() ) + " from the generated EAR." );

             getLog().debug( "Including " + Arrays.asList( getPackagingIncludes() ) + " in the generated EAR." );