[Git][java-team/maven-archiver][upstream] 6 commits: New upstream version 3.3.0

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Tue Oct 11 10:39:29 BST 2022



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


Commits:
acfb772e by Emmanuel Bourg at 2022-09-29T13:03:11+02:00
New upstream version 3.3.0
- - - - -
35e26a88 by Emmanuel Bourg at 2022-09-29T13:11:46+02:00
New upstream version 3.4.0
- - - - -
45cf9b0b by Emmanuel Bourg at 2022-09-29T13:13:55+02:00
New upstream version 3.5.0
- - - - -
ad45cbdf by Emmanuel Bourg at 2022-09-29T13:14:03+02:00
New upstream version 3.5.1
- - - - -
ea8779db by Emmanuel Bourg at 2022-09-29T13:14:07+02:00
New upstream version 3.5.2
- - - - -
0364639b by Emmanuel Bourg at 2022-09-29T13:14:44+02:00
New upstream version 3.6.0
- - - - -


23 changed files:

- + .asf.yaml
- + .github/pull_request_template.md
- + .github/workflows/maven-verify.yml
- + .gitignore
- + Jenkinsfile
- + README.md
- pom.xml
- src/main/java/org/apache/maven/archiver/ManifestConfiguration.java
- src/main/java/org/apache/maven/archiver/ManifestSection.java
- src/main/java/org/apache/maven/archiver/MavenArchiveConfiguration.java
- src/main/java/org/apache/maven/archiver/MavenArchiver.java
- src/main/java/org/apache/maven/archiver/PomPropertiesUtil.java
- src/site/apt/examples/classpath.apt
- src/site/apt/examples/manifest.apt
- src/site/apt/examples/manifestEntries.apt
- src/site/apt/examples/manifestSections.apt
- src/site/site.xml
- src/site/xdoc/download.xml.vm
- src/site/xdoc/index.xml.vm
- src/test/java/org/apache/maven/archiver/ManifestConfigurationTest.java
- src/test/java/org/apache/maven/archiver/MavenArchiveConfigurationTest.java
- src/test/java/org/apache/maven/archiver/MavenArchiverTest.java
- src/test/java/org/apache/maven/archiver/MockArtifact.java


Changes:

=====================================
.asf.yaml
=====================================
@@ -0,0 +1,34 @@
+# 
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+# 
+#       http://www.apache.org/licenses/LICENSE-2.0
+# 
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+# see https://s.apache.org/asfyaml
+github:
+  description: "Apache Maven Archiver"
+  homepage: https://maven.apache.org/shared/maven-archiver/
+  labels:
+    - java
+    - build-management
+    - maven-shared
+    - maven
+  enabled_merge_buttons:
+    squash: true
+    merge: false
+    rebase: true
+notifications:
+  commits: commits at maven.apache.org
+  issues: issues at maven.apache.org
+  pullrequests: issues at maven.apache.org
+  jira_options: link label comment


=====================================
.github/pull_request_template.md
=====================================
@@ -0,0 +1,29 @@
+Following this checklist to help us incorporate your 
+contribution quickly and easily:
+
+ - [ ] Make sure there is a [JIRA issue](https://issues.apache.org/jira/browse/MSHARED) filed 
+       for the change (usually before you start working on it).  Trivial changes like typos do not 
+       require a JIRA issue.  Your pull request should address just this issue, without 
+       pulling in other changes.
+ - [ ] Each commit in the pull request should have a meaningful subject line and body.
+ - [ ] Format the pull request title like `[MSHARED-XXX] - Fixes bug in ApproximateQuantiles`,
+       where you replace `MSHARED-XXX` with the appropriate JIRA issue. Best practice
+       is to use the JIRA issue title in the pull request title and in the first line of the 
+       commit message.
+ - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
+ - [ ] Run `mvn clean verify` to make sure basic checks pass. A more thorough check will 
+       be performed on your pull request automatically.
+ - [ ] You have run the integration tests successfully (`mvn -Prun-its clean verify`).
+
+If your pull request is about ~20 lines of code you don't need to sign an
+[Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf) if you are unsure
+please ask on the developers list.
+
+To make clear that you license your contribution under 
+the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
+you have to acknowledge this by using the following check-box.
+
+ - [ ] I hereby declare this contribution to be licenced under the [Apache License Version 2.0, January 2004](http://www.apache.org/licenses/LICENSE-2.0)
+
+ - [ ] In any other case, please file an [Apache Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
+


=====================================
.github/workflows/maven-verify.yml
=====================================
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Verify
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  build:
+    name: Verify
+    uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml at v2


=====================================
.gitignore
=====================================
@@ -0,0 +1,19 @@
+target/
+.project
+.classpath
+.settings/
+.svn/
+bin/
+# Intellij
+*.ipr
+*.iml
+.idea
+out/
+.DS_Store
+/bootstrap
+/dependencies.xml
+.java-version
+.checkstyle
+.apt_generated/
+.apt_generated_tests/
+.factorypath


=====================================
Jenkinsfile
=====================================
@@ -0,0 +1,20 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+asfMavenTlpStdBuild()


=====================================
README.md
=====================================
@@ -0,0 +1,99 @@
+<!---
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied..
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+Contributing to [Apache Maven Archiver](https://maven.apache.org/shared/maven-archiver/)
+======================
+
+[![ASF Jira](https://img.shields.io/endpoint?url=https%3A%2F%2Fmaven.apache.org%2Fbadges%2Fasf_jira-MSHARED.json)][jira]
+[![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License)][license]
+[![Maven Central](https://img.shields.io/maven-central/v/org.apache.maven/maven-archiver.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven/maven-archiver)
+[![Jenkins Status](https://img.shields.io/jenkins/s/https/ci-maven.apache.org/job/Maven/job/maven-box/job/maven-archiver/job/master.svg)][build]
+[![Jenkins tests](https://img.shields.io/jenkins/t/https/ci-maven.apache.org/job/Maven/job/maven-box/job/maven-archiver/job/master.svg)][test-results]
+
+
+You have found a bug or you have an idea for a cool new feature? Contributing
+code is a great way to give something back to the open source community. Before
+you dig right into the code, there are a few guidelines that we need
+contributors to follow so that we can have a chance of keeping on top of
+things.
+
+Getting Started
+---------------
+
++ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
++ Make sure you have a [GitHub account](https://github.com/signup/free).
++ If you're planning to implement a new feature, it makes sense to discuss your changes 
+  on the [dev list][ml-list] first. 
+  This way you can make sure you're not wasting your time on something that isn't 
+  considered to be in Apache Maven's scope.
++ Submit a ticket for your issue, assuming one does not already exist.
+  + Clearly describe the issue, including steps to reproduce when it is a bug.
+  + Make sure you fill in the earliest version that you know has the issue.
++ Fork the repository on GitHub.
+
+Making and Submitting Changes
+--------------
+
+We accept Pull Requests via GitHub. The [developer mailing list][ml-list] is the
+main channel of communication for contributors.  
+There are some guidelines which will make applying PRs easier for us:
++ Create a topic branch from where you want to base your work (this is usually the master branch).
+  Push your changes to a topic branch in your fork of the repository.
++ Make commits of logical units.
++ Respect the original code style: by using the same [codestyle][code-style],
+  patches should only highlight the actual difference, not being disturbed by any formatting issues:
+  + Only use spaces for indentation.
+  + Create minimal diffs - disable on save actions like reformat source code or organize imports. 
+    If you feel the source code should be reformatted, create a separate PR for this change.
+  + Check for unnecessary whitespace with `git diff --check` before committing.
++ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue.
+```
+[MSHARED-XXX] - Subject of the JIRA Ticket
+ Optional supplemental description.
+```
++ Make sure you have added the necessary tests (JUnit/IT) for your changes.
++ Run all the tests with `mvn -Prun-its verify` to assure nothing else was accidentally broken.
++ Submit a pull request to the repository in the Apache organization.
++ Update your JIRA ticket and include a link to the pull request in the ticket.
+
+If you plan to contribute on a regular basis, please consider filing a [contributor license agreement][cla].
+
+Making Trivial Changes
+----------------------
+
+For changes of a trivial nature to comments and documentation, it is not always
+necessary to create a new ticket in JIRA.  In this case, it is appropriate to
+start the first line of a commit with '(doc)' instead of a ticket number..
+
+Additional Resources
+--------------------
+
++ [Contributing patches](https://maven.apache.org/guides/development/guide-maven-development.html#Creating_and_submitting_a_patch)
++ [Apache Maven Shared Components project page][jira]
++ [Contributor License Agreement][cla]
++ [General GitHub documentation](https://help.github.com/)
++ [GitHub pull request documentation](https://help.github.com/send-pull-requests/)
++ [Apache Maven Twitter Account](https://twitter.com/ASFMavenProject)
++ #Maven IRC channel on freenode.org
+
+[jira]: https://issues.apache.org/jira/projects/MSHARED/
+[license]: https://www.apache.org/licenses/LICENSE-2.0
+[ml-list]: https://maven.apache.org/mailing-lists.html
+[code-style]: https://maven.apache.org/developers/conventions/code.html
+[cla]: https://www.apache.org/licenses/#clas
+[maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index
+[test-results]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-archiver/job/master/lastCompletedBuild/testReport/
+[build]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-archiver/job/master/


=====================================
pom.xml
=====================================
@@ -6,9 +6,9 @@
   regarding copyright ownership.  The ASF licenses this file
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at 
+  with the License.  You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
-  
+
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -22,100 +22,91 @@
   <parent>
     <groupId>org.apache.maven.shared</groupId>
     <artifactId>maven-shared-components</artifactId>
-    <version>30</version>
-    <relativePath>../../pom/maven/maven-shared-components/pom.xml</relativePath>
+    <version>36</version>
+    <relativePath />
   </parent>
 
   <groupId>org.apache.maven</groupId>
   <artifactId>maven-archiver</artifactId>
-  <version>3.2.0</version>
+  <version>3.6.0</version>
 
   <name>Apache Maven Archiver</name>
   <description>Provides utility methods for creating JARs and other archive files from a Maven project.</description>
 
   <properties>
-    <mavenVersion>3.0</mavenVersion>
-    <javaVersion>7</javaVersion>
+    <mavenVersion>3.2.5</mavenVersion>
+    <javaVersion>8</javaVersion>
+    <project.build.outputTimestamp>2022-06-23T12:17:44Z</project.build.outputTimestamp>
   </properties>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/maven/shared/tags/maven-archiver-3.2.0</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/shared/tags/maven-archiver-3.2.0</developerConnection>
-    <url>http://svn.apache.org/viewvc/maven/shared/tags/maven-archiver-3.2.0</url>
+    <connection>scm:git:https://gitbox.apache.org/repos/asf/maven-archiver.git</connection>
+    <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-archiver.git</developerConnection>
+    <url>https://github.com/apache/maven-archiver/tree/${project.scm.tag}</url>
+    <tag>maven-archiver-3.6.0</tag>
   </scm>
   <issueManagement>
     <system>jira</system>
-    <url>https://issues.apache.org/jira/browse/MSHARED/component/12326430</url>
+    <url>https://issues.apache.org/jira/issues/?jql=project%3DMSHARED+AND+component%3Dmaven-archiver</url>
   </issueManagement>
+  <ciManagement>
+    <system>Jenkins</system>
+    <url>https://ci-builds.apache.org/job/Maven/job/maven-box/job/maven-archiver/</url>
+  </ciManagement>
   <distributionManagement>
     <site>
       <id>apache.website</id>
-      <url>scm:svn:https://svn.apache.org/repos/infra/websites/production/maven/components/${maven.site.path}</url>
+      <url>scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path}</url>
     </site>
   </distributionManagement>
 
   <dependencies>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-artifact</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>${mavenVersion}</version>
-    </dependency>
+    <!--
+      Apache Maven dependencies
+    -->
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-core</artifactId>
       <version>${mavenVersion}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven.shared</groupId>
-      <artifactId>maven-shared-utils</artifactId>
-      <version>3.2.0</version>
+      <scope>provided</scope>
     </dependency>
     <!--
-      ! Pulled in as a direct dependency to resolve conflicts.
-      ! We want the most recent commons-io compatible to the target JDK.
+      Plexus dependencies
     -->
     <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <version>2.5</version>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-io</artifactId>
+      <version>3.4.0</version>
     </dependency>
-
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-archiver</artifactId>
-      <version>3.5</version>
+      <version>4.4.0</version>
     </dependency>
-    <!--
-      ! plexus-archiver needs this, or else maven-artifact will 
-      ! pull in a version from the pliocene era
-    -->
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-utils</artifactId>
-      <version>3.0.24</version>
+      <version>3.4.2</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-interpolation</artifactId>
-      <version>1.22</version>
+      <version>1.26</version>
     </dependency>
+    <!--
+      Test dependencies
+    -->
     <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.12</version>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <version>5.8.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.assertj</groupId>
       <artifactId>assertj-core</artifactId>
-      <version>1.7.1</version>
+      <version>3.23.1</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
-
 </project>


=====================================
src/main/java/org/apache/maven/archiver/ManifestConfiguration.java
=====================================
@@ -23,7 +23,6 @@ package org.apache.maven.archiver;
  * Capture common manifest configuration.
  *
  * @author <a href="mailto:brett at apache.org">Brett Porter</a>
- * @version $Id: ManifestConfiguration.java 1748291 2016-06-13 18:00:20Z rfscholte $
  */
 // TODO Is this general enough to be in Plexus Archiver?
 public class ManifestConfiguration
@@ -56,6 +55,21 @@ public class ManifestConfiguration
      */
     private String classpathPrefix = "";
 
+    /**
+     * Add default, reproducible entries {@code Created-By} and {@code Build-Jdk-Spec}.
+     *
+     * @since 3.4.0
+     */
+    private boolean addDefaultEntries = true;
+
+
+    /**
+     * Add build environment information about Maven, JDK, and OS.
+     *
+     * @since 3.4.0
+     */
+    private boolean addBuildEnvironmentEntries;
+
     /**
      * Add default implementation entries if this is an extension specification.
      *
@@ -77,6 +91,8 @@ public class ManifestConfiguration
     private boolean useUniqueVersions = true;
 
     /**
+     * <p>Getter for the field <code>mainClass</code>.</p>
+     *
      * @return mainClass
      */
     public String getMainClass()
@@ -85,6 +101,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>packageName</code>.</p>
+     *
      * @return the package name.
      */
     public String getPackageName()
@@ -93,6 +111,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>isAddClasspath.</p>
+     *
      * @return if addClasspath true or false.
      */
     public boolean isAddClasspath()
@@ -101,6 +121,28 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>isAddDefaultEntries.</p>
+     *
+     * @return {@link #addDefaultEntries}
+     */
+    public boolean isAddDefaultEntries()
+    {
+        return addDefaultEntries;
+    }
+
+    /**
+     * <p>isAddBuildEnvironmentEntries.</p>
+     *
+     * @return {@link #addBuildEnvironmentEntries}
+     */
+    public boolean isAddBuildEnvironmentEntries()
+    {
+        return addBuildEnvironmentEntries;
+    }
+
+    /**
+     * <p>isAddDefaultImplementationEntries.</p>
+     *
      * @return {@link #addDefaultImplementationEntries}
      */
     public boolean isAddDefaultImplementationEntries()
@@ -109,6 +151,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>isAddDefaultSpecificationEntries.</p>
+     *
      * @return {@link #addDefaultSpecificationEntries}
      */
     public boolean isAddDefaultSpecificationEntries()
@@ -117,6 +161,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>isAddExtensions.</p>
+     *
      * @return {@link #addExtensions}
      */
     public boolean isAddExtensions()
@@ -125,6 +171,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>addClasspath</code>.</p>
+     *
      * @param addClasspath turn on addClasspath or off.
      */
     public void setAddClasspath( boolean addClasspath )
@@ -133,6 +181,28 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>addDefaultEntries</code>.</p>
+     *
+     * @param addDefaultEntries add default entries true/false.
+     */
+    public void setAddDefaultEntries( boolean addDefaultEntries )
+    {
+        this.addDefaultEntries = addDefaultEntries;
+    }
+
+    /**
+     * <p>Setter for the field <code>addBuildEnvironmentEntries</code>.</p>
+     *
+     * @param addBuildEnvironmentEntries add build environment information true/false.
+     */
+    public void setAddBuildEnvironmentEntries( boolean addBuildEnvironmentEntries )
+    {
+        this.addBuildEnvironmentEntries = addBuildEnvironmentEntries;
+    }
+
+    /**
+     * <p>Setter for the field <code>addDefaultImplementationEntries</code>.</p>
+     *
      * @param addDefaultImplementationEntries true to add default implementations false otherwise.
      */
     public void setAddDefaultImplementationEntries( boolean addDefaultImplementationEntries )
@@ -141,6 +211,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>addDefaultSpecificationEntries</code>.</p>
+     *
      * @param addDefaultSpecificationEntries add default specifications true/false.
      */
     public void setAddDefaultSpecificationEntries( boolean addDefaultSpecificationEntries )
@@ -149,6 +221,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>addExtensions</code>.</p>
+     *
      * @param addExtensions true to add extensions false otherwise.
      */
     public void setAddExtensions( boolean addExtensions )
@@ -157,6 +231,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>classpathPrefix</code>.</p>
+     *
      * @param classpathPrefix The prefix.
      */
     public void setClasspathPrefix( String classpathPrefix )
@@ -165,6 +241,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>mainClass</code>.</p>
+     *
      * @param mainClass The main class.
      */
     public void setMainClass( String mainClass )
@@ -173,6 +251,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>packageName</code>.</p>
+     *
      * @param packageName The package name.
      */
     public void setPackageName( String packageName )
@@ -181,6 +261,8 @@ public class ManifestConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>classpathPrefix</code>.</p>
+     *
      * @return The classpath prefix.
      */
     public String getClasspathPrefix()
@@ -201,7 +283,8 @@ public class ManifestConfiguration
      * 'repository' (CLASSPATH_LAYOUT_TYPE_REPOSITORY, or the same as a maven classpath layout), and 'custom'
      * (CLASSPATH_LAYOUT_TYPE_CUSTOM). <br>
      * <b>NOTE:</b> If you specify a type of 'custom' you MUST set
-     * {@link ManifestConfiguration#setCustomClasspathLayout(String)}.
+     * {@link org.apache.maven.archiver.ManifestConfiguration#setCustomClasspathLayout(String)}.
+     *
      * @return The classpath layout type.
      */
     public String getClasspathLayoutType()
@@ -213,9 +296,10 @@ public class ManifestConfiguration
      * Set the type of layout to use when formatting classpath entries. Should be one of: 'simple'
      * (CLASSPATH_LAYOUT_TYPE_SIMPLE), 'repository' (CLASSPATH_LAYOUT_TYPE_REPOSITORY, or the same as a maven classpath
      * layout), and 'custom' (CLASSPATH_LAYOUT_TYPE_CUSTOM). The constant names noted here are defined in the
-     * {@link ManifestConfiguration} class. <br>
+     * {@link org.apache.maven.archiver.ManifestConfiguration} class. <br>
      * <b>NOTE:</b> If you specify a type of 'custom' you MUST set
-     * {@link ManifestConfiguration#setCustomClasspathLayout(String)}.
+     * {@link org.apache.maven.archiver.ManifestConfiguration#setCustomClasspathLayout(String)}.
+     *
      * @param classpathLayoutType The classpath layout type.
      */
     public void setClasspathLayoutType( String classpathLayoutType )
@@ -225,7 +309,8 @@ public class ManifestConfiguration
 
     /**
      * Retrieve the layout expression for use when the layout type set in
-     * {@link ManifestConfiguration#setClasspathLayoutType(String)} has the value 'custom'. <b>The default value is
+     * {@link org.apache.maven.archiver.ManifestConfiguration#setClasspathLayoutType(String)} has the value 'custom'.
+     * <b>The default value is
      * null.</b> Expressions will be evaluated against the following ordered list of classpath-related objects:
      * <ol>
      * <li>The current {@code Artifact} instance, if one exists.</li>
@@ -233,6 +318,7 @@ public class ManifestConfiguration
      * </ol>
      * <br>
      * <b>NOTE:</b> If you specify a layout type of 'custom' you MUST set this layout expression.
+     *
      * @return The custom classpath layout.
      */
     public String getCustomClasspathLayout()
@@ -242,7 +328,8 @@ public class ManifestConfiguration
 
     /**
      * Set the layout expression for use when the layout type set in
-     * {@link ManifestConfiguration#setClasspathLayoutType(String)} has the value 'custom'. Expressions will be
+     * {@link org.apache.maven.archiver.ManifestConfiguration#setClasspathLayoutType(String)} has the value 'custom'.
+     * Expressions will be
      * evaluated against the following ordered list of classpath-related objects:
      * <ol>
      * <li>The current {@code Artifact} instance, if one exists.</li>
@@ -250,14 +337,15 @@ public class ManifestConfiguration
      * </ol>
      * <br>
      * <b>NOTE:</b> If you specify a layout type of 'custom' you MUST set this layout expression.
-     * You can take a look at 
+     * You can take a look at
      * <ol>
-     * <li>{@link MavenArchiver#SIMPLE_LAYOUT}</li>
-     * <li>{@link MavenArchiver#SIMPLE_LAYOUT_NONUNIQUE}</li>
-     * <li>{@link MavenArchiver#REPOSITORY_LAYOUT}</li>
-     * <li>{@link MavenArchiver#REPOSITORY_LAYOUT_NONUNIQUE}</li>
+     * <li>{@link org.apache.maven.archiver.MavenArchiver#SIMPLE_LAYOUT}</li>
+     * <li>{@link org.apache.maven.archiver.MavenArchiver#SIMPLE_LAYOUT_NONUNIQUE}</li>
+     * <li>{@link org.apache.maven.archiver.MavenArchiver#REPOSITORY_LAYOUT}</li>
+     * <li>{@link org.apache.maven.archiver.MavenArchiver#REPOSITORY_LAYOUT_NONUNIQUE}</li>
      * </ol>
      * how such an expression looks like.
+     *
      * @param customClasspathLayout The custom classpath layout.
      */
     public void setCustomClasspathLayout( String customClasspathLayout )
@@ -285,6 +373,7 @@ public class ManifestConfiguration
      * <br>
      * <b>NOTE:</b> If the snapshot was installed locally, this flag will not have an effect on that artifact's
      * inclusion, since it will have the same version either way (i.e. -SNAPSHOT naming).
+     *
      * @param useUniqueVersions true to use unique versions or not.
      */
     public void setUseUniqueVersions( boolean useUniqueVersions )


=====================================
src/main/java/org/apache/maven/archiver/ManifestSection.java
=====================================
@@ -23,16 +23,18 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 
 /**
- * @version $Id: ManifestSection.java 1738422 2016-04-10 11:51:15Z khmarbaise $
+ * <p>ManifestSection class.</p>
  */
 public class ManifestSection
 {
 
     private String name = null;
 
-    private Map<String, String> manifestEntries = new LinkedHashMap<String, String>();
+    private final Map<String, String> manifestEntries = new LinkedHashMap<>();
 
     /**
+     * <p>addManifestEntry.</p>
+     *
      * @param key The key of the manifest entry.
      * @param value The appropriate value.
      */
@@ -42,6 +44,8 @@ public class ManifestSection
     }
 
     /**
+     * <p>Getter for the field <code>manifestEntries</code>.</p>
+     *
      * @return The entries.
      */
     public Map<String, String> getManifestEntries()
@@ -50,6 +54,8 @@ public class ManifestSection
     }
 
     /**
+     * <p>Getter for the field <code>name</code>.</p>
+     *
      * @return The name.
      */
     public String getName()
@@ -58,6 +64,8 @@ public class ManifestSection
     }
 
     /**
+     * <p>Setter for the field <code>name</code>.</p>
+     *
      * @param name the name.
      */
     public void setName( String name )
@@ -66,6 +74,8 @@ public class ManifestSection
     }
 
     /**
+     * <p>addManifestEntries.</p>
+     *
      * @param map The map to add.
      */
     public void addManifestEntries( Map<String, String> map )
@@ -74,6 +84,8 @@ public class ManifestSection
     }
 
     /**
+     * <p>isManifestEntriesEmpty.</p>
+     *
      * @return true if empty false otherwise.
      */
     public boolean isManifestEntriesEmpty()


=====================================
src/main/java/org/apache/maven/archiver/MavenArchiveConfiguration.java
=====================================
@@ -29,7 +29,6 @@ import java.util.Map;
  * Capture common archive configuration.
  *
  * @author <a href="mailto:brett at apache.org">Brett Porter</a>
- * @version $Id: MavenArchiveConfiguration.java 1738422 2016-04-10 11:51:15Z khmarbaise $
  */
 // TODO Is this general enough to be in Plexus Archiver?
 public class MavenArchiveConfiguration
@@ -47,9 +46,9 @@ public class MavenArchiveConfiguration
     //TODO: Rename this attribute to manifestConfiguration;
     private ManifestConfiguration manifest;
 
-    private Map<String, String> manifestEntries = new LinkedHashMap<String, String>();
+    private Map<String, String> manifestEntries = new LinkedHashMap<>();
 
-    private List<ManifestSection> manifestSections = new LinkedList<ManifestSection>();
+    private List<ManifestSection> manifestSections = new LinkedList<>();
 
     /**
      * @since 2.2
@@ -62,6 +61,8 @@ public class MavenArchiveConfiguration
     private File pomPropertiesFile;
 
     /**
+     * <p>isCompress.</p>
+     *
      * @return {@link #compress}
      */
     public boolean isCompress()
@@ -70,6 +71,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>isRecompressAddedZips.</p>
+     *
      * @return {@link #recompressAddedZips}
      */
     public boolean isRecompressAddedZips()
@@ -78,6 +81,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>recompressAddedZips</code>.</p>
+     *
      * @param recompressAddedZips {@link #recompressAddedZips}
      */
     public void setRecompressAddedZips( boolean recompressAddedZips )
@@ -86,6 +91,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>isIndex.</p>
+     *
      * @return {@link #index}
      */
     public boolean isIndex()
@@ -94,6 +101,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>isAddMavenDescriptor.</p>
+     *
      * @return {@link #addMavenDescriptor}
      */
     public boolean isAddMavenDescriptor()
@@ -102,6 +111,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>manifestFile</code>.</p>
+     *
      * @return {@link #manifestFile}
      */
     public File getManifestFile()
@@ -110,6 +121,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>manifest</code>.</p>
+     *
      * @return {@link #manifest}
      */
     //TODO: Change the name of this method into getManifestConfiguration()
@@ -123,6 +136,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>compress</code>.</p>
+     *
      * @param compress set compress to true/false.
      */
     public void setCompress( boolean compress )
@@ -131,6 +146,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>index</code>.</p>
+     *
      * @param index set index to true/false.
      */
     public void setIndex( boolean index )
@@ -139,6 +156,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>addMavenDescriptor</code>.</p>
+     *
      * @param addMavenDescriptor activate to add maven descriptor or not..
      */
     public void setAddMavenDescriptor( boolean addMavenDescriptor )
@@ -147,6 +166,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>manifestFile</code>.</p>
+     *
      * @param manifestFile The manifest file.
      */
     public void setManifestFile( File manifestFile )
@@ -155,7 +176,9 @@ public class MavenArchiveConfiguration
     }
 
     /**
-     * @param manifest {@link ManifestConfiguration}
+     * <p>Setter for the field <code>manifest</code>.</p>
+     *
+     * @param manifest {@link org.apache.maven.archiver.ManifestConfiguration}
      */
     public void setManifest( ManifestConfiguration manifest )
     {
@@ -163,6 +186,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>addManifestEntry.</p>
+     *
      * @param key The key of the entry.
      * @param value The value of the entry.
      */
@@ -172,6 +197,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>addManifestEntries.</p>
+     *
      * @param map The whole map which should be added.
      */
     public void addManifestEntries( Map<String, String> map )
@@ -180,6 +207,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>isManifestEntriesEmpty.</p>
+     *
      * @return are there entries true yes false otherwise.
      */
     public boolean isManifestEntriesEmpty()
@@ -188,6 +217,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>manifestEntries</code>.</p>
+     *
      * @return {@link #manifestEntries}
      */
     public Map<String, String> getManifestEntries()
@@ -196,6 +227,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Setter for the field <code>manifestEntries</code>.</p>
+     *
      * @param manifestEntries {@link #manifestEntries}
      */
     public void setManifestEntries( Map<String, String> manifestEntries )
@@ -204,7 +237,9 @@ public class MavenArchiveConfiguration
     }
 
     /**
-     * @param section {@link ManifestSection}
+     * <p>addManifestSection.</p>
+     *
+     * @param section {@link org.apache.maven.archiver.ManifestSection}
      */
     public void addManifestSection( ManifestSection section )
     {
@@ -212,7 +247,9 @@ public class MavenArchiveConfiguration
     }
 
     /**
-     * @param list Added list of {@link ManifestSection}.
+     * <p>addManifestSections.</p>
+     *
+     * @param list Added list of {@link org.apache.maven.archiver.ManifestSection}.
      */
     public void addManifestSections( List<ManifestSection> list )
     {
@@ -220,6 +257,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>isManifestSectionsEmpty.</p>
+     *
      * @return if manifestSections is empty or not.
      */
     public boolean isManifestSectionsEmpty()
@@ -228,6 +267,8 @@ public class MavenArchiveConfiguration
     }
 
     /**
+     * <p>Getter for the field <code>manifestSections</code>.</p>
+     *
      * @return {@link #manifestSections}
      */
     public List<ManifestSection> getManifestSections()
@@ -236,7 +277,9 @@ public class MavenArchiveConfiguration
     }
 
     /**
-     * @param manifestSections set The list of {@link ManifestSection}.
+     * <p>Setter for the field <code>manifestSections</code>.</p>
+     *
+     * @param manifestSections set The list of {@link org.apache.maven.archiver.ManifestSection}.
      */
     public void setManifestSections( List<ManifestSection> manifestSections )
     {


=====================================
src/main/java/org/apache/maven/archiver/MavenArchiver.java
=====================================
@@ -19,6 +19,27 @@ package org.apache.maven.archiver;
  * under the License.
  */
 
+import javax.lang.model.SourceVersion;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.attribute.FileTime;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.artifact.versioning.ArtifactVersion;
@@ -36,25 +57,24 @@ import org.codehaus.plexus.interpolation.PrefixedPropertiesValueSource;
 import org.codehaus.plexus.interpolation.RecursionInterceptor;
 import org.codehaus.plexus.interpolation.StringSearchInterpolator;
 import org.codehaus.plexus.interpolation.ValueSource;
-import org.apache.maven.shared.utils.StringUtils;
+import org.codehaus.plexus.util.StringUtils;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import static org.apache.maven.archiver.ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM;
+import static org.apache.maven.archiver.ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY;
+import static org.apache.maven.archiver.ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_SIMPLE;
 
 /**
+ * <p>MavenArchiver class.</p>
+ *
  * @author <a href="evenisse at apache.org">Emmanuel Venisse</a>
  * @author kama
- * @version $Revision: 1748306 $ $Date: 2016-06-13 21:33:58 +0200 (Mon, 13 Jun 2016) $
+ * @version $Id: $Id
  */
 public class MavenArchiver
 {
 
+    private static final String CREATED_BY = "Maven Archiver";
+
     /**
      * The simply layout.
      */
@@ -81,34 +101,49 @@ public class MavenArchiver
         "${artifact.groupIdPath}/${artifact.artifactId}/" + "${artifact.baseVersion}/${artifact.artifactId}-"
             + "${artifact.baseVersion}${dashClassifier?}.${artifact.extension}";
 
+    private static final Instant DATE_MIN = Instant.parse( "1980-01-01T00:00:02Z" );
+
+    private static final Instant DATE_MAX = Instant.parse( "2099-12-31T23:59:59Z" );
+
     private static final List<String> ARTIFACT_EXPRESSION_PREFIXES;
 
     static
     {
-        List<String> artifactExpressionPrefixes = new ArrayList<String>();
+        List<String> artifactExpressionPrefixes = new ArrayList<>();
         artifactExpressionPrefixes.add( "artifact." );
 
         ARTIFACT_EXPRESSION_PREFIXES = artifactExpressionPrefixes;
     }
 
+    static boolean isValidModuleName( String name )
+    {
+        return SourceVersion.isName( name );
+    }
+
     private JarArchiver archiver;
 
     private File archiveFile;
 
+    private String createdBy;
+
+    private boolean buildJdkSpecDefaultEntry = true;
+    
     /**
-     * @param session The Maven Session.
-     * @param project The Maven Project.
-     * @param config The MavenArchiveConfiguration
-     * @return The {@link Manifest}
-     * @throws ManifestException In case of a failure.
-     * @throws DependencyResolutionRequiredException Resolution failure.
+     * <p>getManifest.</p>
+     *
+     * @param session the Maven Session
+     * @param project the Maven Project
+     * @param config the MavenArchiveConfiguration
+     * @return the {@link org.codehaus.plexus.archiver.jar.Manifest}
+     * @throws org.codehaus.plexus.archiver.jar.ManifestException in case of a failure
+     * @throws org.apache.maven.artifact.DependencyResolutionRequiredException resolution failure
      */
     public Manifest getManifest( MavenSession session, MavenProject project, MavenArchiveConfiguration config )
         throws ManifestException, DependencyResolutionRequiredException
     {
         boolean hasManifestEntries = !config.isManifestEntriesEmpty();
         Map<String, String> entries =
-            hasManifestEntries ? config.getManifestEntries() : Collections.<String, String>emptyMap();
+            hasManifestEntries ? config.getManifestEntries() : Collections.emptyMap();
 
         Manifest manifest = getManifest( session, project, config.getManifest(), entries );
 
@@ -121,7 +156,7 @@ public class MavenArchiver
                 String key = entry.getKey();
                 String value = entry.getValue();
                 Manifest.Attribute attr = manifest.getMainSection().getAttribute( key );
-                if ( key.equals( "ClassPath" ) && attr != null )
+                if ( key.equals( Attributes.Name.CLASS_PATH.toString() ) && attr != null )
                 {
                     // Merge the user-supplied Class-Path value with the programmatically
                     // created Class-Path. Note that the user-supplied value goes first
@@ -164,33 +199,36 @@ public class MavenArchiver
     }
 
     /**
-     * Return a pre-configured manifest
+     * Return a pre-configured manifest.
      *
-     * @param project {@link MavenProject}
-     * @param config {@link ManifestConfiguration}
-     * @return {@link Manifest}
-     * @throws ManifestException Manifest exception.
-     * @throws DependencyResolutionRequiredException Dependency resolution exception.
+     * @param project {@link org.apache.maven.project.MavenProject}
+     * @param config {@link org.apache.maven.archiver.ManifestConfiguration}
+     * @return {@link org.codehaus.plexus.archiver.jar.Manifest}
+     * @throws org.codehaus.plexus.archiver.jar.ManifestException Manifest exception.
+     * @throws org.apache.maven.artifact.DependencyResolutionRequiredException Dependency resolution exception.
      */
     // TODO Add user attributes list and user groups list
     public Manifest getManifest( MavenProject project, ManifestConfiguration config )
         throws ManifestException, DependencyResolutionRequiredException
     {
-        return getManifest( null, project, config, Collections.<String, String>emptyMap() );
+        return getManifest( null, project, config, Collections.emptyMap() );
     }
 
     /**
-     * @param mavenSession {@link MavenSession}
-     * @param project {@link MavenProject}
-     * @param config {@link ManifestConfiguration}
-     * @return {@link Manifest}
-     * @throws ManifestException The manifest exception.
-     * @throws DependencyResolutionRequiredException The dependency resolution required exception.
+     * <p>getManifest.</p>
+     *
+     * @param mavenSession {@link org.apache.maven.execution.MavenSession}
+     * @param project      {@link org.apache.maven.project.MavenProject}
+     * @param config       {@link org.apache.maven.archiver.ManifestConfiguration}
+     * @return {@link org.codehaus.plexus.archiver.jar.Manifest}
+     * @throws org.codehaus.plexus.archiver.jar.ManifestException              the manifest exception
+     * @throws org.apache.maven.artifact.DependencyResolutionRequiredException the dependency resolution required
+     *                                                                         exception
      */
     public Manifest getManifest( MavenSession mavenSession, MavenProject project, ManifestConfiguration config )
         throws ManifestException, DependencyResolutionRequiredException
     {
-        return getManifest( mavenSession, project, config, Collections.<String, String>emptyMap() );
+        return getManifest( mavenSession, project, config, Collections.emptyMap() );
     }
 
     private void addManifestAttribute( Manifest manifest, Map<String, String> map, String key, String value )
@@ -213,7 +251,7 @@ public class MavenArchiver
         }
         else
         {
-            // if the value is empty we have create an entry with an empty string
+            // if the value is empty, create an entry with an empty string
             // to prevent null print in the manifest file
             Manifest.Attribute attr = new Manifest.Attribute( key, "" );
             manifest.addConfiguredAttribute( attr );
@@ -221,13 +259,16 @@ public class MavenArchiver
     }
 
     /**
-     * @param session {@link MavenSession}
-     * @param project {@link MavenProject}
-     * @param config {@link ManifestConfiguration}
+     * <p>getManifest.</p>
+     *
+     * @param session {@link org.apache.maven.execution.MavenSession}
+     * @param project {@link org.apache.maven.project.MavenProject}
+     * @param config  {@link org.apache.maven.archiver.ManifestConfiguration}
      * @param entries The entries.
-     * @return {@link Manifest}
-     * @throws ManifestException The manifest exception.
-     * @throws DependencyResolutionRequiredException The dependency resolution required exception.
+     * @return {@link org.codehaus.plexus.archiver.jar.Manifest}
+     * @throws org.codehaus.plexus.archiver.jar.ManifestException              the manifest exception
+     * @throws org.apache.maven.artifact.DependencyResolutionRequiredException the dependency resolution required
+     *                                                                         exception
      */
     protected Manifest getManifest( MavenSession session, MavenProject project, ManifestConfiguration config,
                                     Map<String, String> entries )
@@ -235,11 +276,18 @@ public class MavenArchiver
     {
         // TODO: Should we replace "map" with a copy? Note, that we modify it!
 
-        // Added basic entries
         Manifest m = new Manifest();
-        addCreatedByEntry( session, m, entries );
 
-        addCustomEntries( m, entries, config );
+        if ( config.isAddDefaultEntries() )
+        {
+            handleDefaultEntries( m, entries );
+        }
+
+
+        if ( config.isAddBuildEnvironmentEntries() )
+        {
+            handleBuildEnvironmentEntries( session, m, entries );
+        }
 
         if ( config.isAddClasspath() )
         {
@@ -273,7 +321,7 @@ public class MavenArchiver
                     }
                     else
                     {
-                        List<ValueSource> valueSources = new ArrayList<ValueSource>();
+                        List<ValueSource> valueSources = new ArrayList<>();
 
                         handleExtraExpression( artifact, valueSources );
 
@@ -287,48 +335,49 @@ public class MavenArchiver
 
                         try
                         {
-                            if ( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_SIMPLE.equals( layoutType ) )
-                            {
-                                if ( config.isUseUniqueVersions() )
-                                {
-                                    classpath.append( interpolator.interpolate( SIMPLE_LAYOUT, recursionInterceptor ) );
-                                }
-                                else
-                                {
-                                    classpath.append( interpolator.interpolate( SIMPLE_LAYOUT_NONUNIQUE,
-                                                                                recursionInterceptor ) );
-                                }
-                            }
-                            else if ( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY.equals( layoutType ) )
-                            {
-                                // we use layout /$groupId[0]/../${groupId[n]/$artifactId/$version/{fileName}
-                                // here we must find the Artifact in the project Artifacts to create the maven layout
-                                if ( config.isUseUniqueVersions() )
-                                {
-                                    classpath.append( interpolator.interpolate( REPOSITORY_LAYOUT,
-                                                                                recursionInterceptor ) );
-                                }
-                                else
-                                {
-                                    classpath.append( interpolator.interpolate( REPOSITORY_LAYOUT_NONUNIQUE,
-                                                                                recursionInterceptor ) );
-                                }
-                            }
-                            else if ( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM.equals( layoutType ) )
+                            switch ( layoutType )
                             {
-                                if ( layout == null )
-                                {
-                                    throw new ManifestException( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM
-                                        + " layout type was declared, but custom layout expression was not"
-                                        + " specified. Check your <archive><manifest><customLayout/> element." );
-                                }
-
-                                classpath.append( interpolator.interpolate( layout, recursionInterceptor ) );
-                            }
-                            else
-                            {
-                                throw new ManifestException( "Unknown classpath layout type: '" + layoutType
-                                    + "'. Check your <archive><manifest><layoutType/> element." );
+                                case CLASSPATH_LAYOUT_TYPE_SIMPLE:
+                                    if ( config.isUseUniqueVersions() )
+                                    {
+                                        classpath.append( interpolator.interpolate( SIMPLE_LAYOUT,
+                                                recursionInterceptor ) );
+                                    }
+                                    else
+                                    {
+                                        classpath.append( interpolator.interpolate( SIMPLE_LAYOUT_NONUNIQUE,
+                                                recursionInterceptor ) );
+                                    }
+                                    break;
+                                case CLASSPATH_LAYOUT_TYPE_REPOSITORY:
+                                    // we use layout /$groupId[0]/../${groupId[n]/$artifactId/$version/{fileName}
+                                    // here we must find the Artifact in the project Artifacts
+                                    // to create the maven layout
+                                    if ( config.isUseUniqueVersions() )
+                                    {
+                                        classpath.append( interpolator.interpolate( REPOSITORY_LAYOUT,
+                                                recursionInterceptor ) );
+                                    }
+                                    else
+                                    {
+                                        classpath.append( interpolator.interpolate( REPOSITORY_LAYOUT_NONUNIQUE,
+                                                recursionInterceptor ) );
+                                    }
+                                    break;
+                                case CLASSPATH_LAYOUT_TYPE_CUSTOM:
+                                    if ( layout == null )
+                                    {
+                                        throw new ManifestException( CLASSPATH_LAYOUT_TYPE_CUSTOM
+                                                + " layout type was declared, but custom layout expression was not"
+                                                + " specified. Check your <archive><manifest><customLayout/>"
+                                                + " element." );
+                                    }
+
+                                    classpath.append( interpolator.interpolate( layout, recursionInterceptor ) );
+                                    break;
+                                default:
+                                    throw new ManifestException( "Unknown classpath layout type: '" + layoutType
+                                            + "'. Check your <archive><manifest><layoutType/> element." );
                             }
                         }
                         catch ( InterpolationException e )
@@ -380,6 +429,8 @@ public class MavenArchiver
             handleExtensions( project, entries, m );
         }
 
+        addCustomEntries( m, entries, config );
+
         return m;
     }
 
@@ -418,7 +469,7 @@ public class MavenArchiver
     {
         // TODO: this is only for applets - should we distinguish them as a packaging?
         StringBuilder extensionsList = new StringBuilder();
-        Set<Artifact> artifacts = (Set<Artifact>) project.getArtifacts();
+        Set<Artifact> artifacts = project.getArtifacts();
 
         for ( Artifact artifact : artifacts )
         {
@@ -440,11 +491,10 @@ public class MavenArchiver
             addManifestAttribute( m, entries, "Extension-List", extensionsList.toString() );
         }
 
-        for ( Object artifact1 : artifacts )
+        for ( Artifact artifact : artifacts )
         {
             // TODO: the correct solution here would be to have an extension type, and to read
             // the real extension values either from the artifact's manifest or some part of the POM
-            Artifact artifact = (Artifact) artifact1;
             if ( "jar".equals( artifact.getType() ) )
             {
                 String artifactId = artifact.getArtifactId().replace( '.', '_' );
@@ -456,7 +506,7 @@ public class MavenArchiver
                 if ( artifact.getRepository() != null )
                 {
                     iname = artifactId + "-Implementation-URL";
-                    String url = artifact.getRepository().getUrl() + "/" + artifact.toString();
+                    String url = artifact.getRepository().getUrl() + "/" + artifact;
                     addManifestAttribute( m, entries, iname, url );
                 }
             }
@@ -468,18 +518,11 @@ public class MavenArchiver
     {
         addManifestAttribute( m, entries, "Implementation-Title", project.getName() );
         addManifestAttribute( m, entries, "Implementation-Version", project.getVersion() );
-        // MJAR-5
-        addManifestAttribute( m, entries, "Implementation-Vendor-Id", project.getGroupId() );
 
         if ( project.getOrganization() != null )
         {
             addManifestAttribute( m, entries, "Implementation-Vendor", project.getOrganization().getName() );
         }
-
-        if ( project.getUrl() != null )
-        {
-            addManifestAttribute( m, entries, "Implementation-URL", project.getUrl() );
-        }
     }
 
     private void handleSpecificationEntries( MavenProject project, Map<String, String> entries, Manifest m )
@@ -508,9 +551,6 @@ public class MavenArchiver
     private void addCustomEntries( Manifest m, Map<String, String> entries, ManifestConfiguration config )
         throws ManifestException
     {
-        addManifestAttribute( m, entries, "Built-By", System.getProperty( "user.name" ) );
-        addManifestAttribute( m, entries, "Build-Jdk", System.getProperty( "java.version" ) );
-
         /*
          * TODO: rethink this, it wasn't working Artifact projectArtifact = project.getArtifact(); if (
          * projectArtifact.isSnapshot() ) { Manifest.Attribute buildNumberAttr = new Manifest.Attribute( "Build-Number",
@@ -523,7 +563,9 @@ public class MavenArchiver
     }
 
     /**
-     * @return {@link JarArchiver}
+     * <p>Getter for the field <code>archiver</code>.</p>
+     *
+     * @return {@link org.codehaus.plexus.archiver.jar.JarArchiver}
      */
     public JarArchiver getArchiver()
     {
@@ -531,7 +573,9 @@ public class MavenArchiver
     }
 
     /**
-     * @param archiver {@link JarArchiver}
+     * <p>Setter for the field <code>archiver</code>.</p>
+     *
+     * @param archiver {@link org.codehaus.plexus.archiver.jar.JarArchiver}
      */
     public void setArchiver( JarArchiver archiver )
     {
@@ -539,6 +583,8 @@ public class MavenArchiver
     }
 
     /**
+     * <p>setOutputFile.</p>
+     *
      * @param outputFile Set output file.
      */
     public void setOutputFile( File outputFile )
@@ -547,13 +593,15 @@ public class MavenArchiver
     }
 
     /**
-     * @param session {@link MavenSession}
-     * @param project {@link MavenProject}
-     * @param archiveConfiguration {@link MavenArchiveConfiguration}
+     * <p>createArchive.</p>
+     *
+     * @param session {@link org.apache.maven.execution.MavenSession}
+     * @param project {@link org.apache.maven.project.MavenProject}
+     * @param archiveConfiguration {@link org.apache.maven.archiver.MavenArchiveConfiguration}
      * @throws org.codehaus.plexus.archiver.ArchiverException Archiver Exception.
-     * @throws ManifestException Manifest Exception.
-     * @throws IOException IO Exception.
-     * @throws DependencyResolutionRequiredException Dependency resolution exception.
+     * @throws org.codehaus.plexus.archiver.jar.ManifestException Manifest Exception.
+     * @throws java.io.IOException IO Exception.
+     * @throws org.apache.maven.artifact.DependencyResolutionRequiredException Dependency resolution exception.
      */
     public void createArchive( MavenSession session, MavenProject project,
                                MavenArchiveConfiguration archiveConfiguration )
@@ -562,8 +610,7 @@ public class MavenArchiver
     {
         // we have to clone the project instance so we can write out the pom with the deployment version,
         // without impacting the main project instance...
-        MavenProject workingProject = null;
-        workingProject = (MavenProject) project.clone();
+        MavenProject workingProject = project.clone();
 
         boolean forced = archiveConfiguration.isForced();
         if ( archiveConfiguration.isAddMavenDescriptor() )
@@ -606,6 +653,8 @@ public class MavenArchiver
         // Create the manifest
         // ----------------------------------------------------------------------
 
+        archiver.setMinimalDefaultManifest( true );
+
         File manifestFile = archiveConfiguration.getManifestFile();
 
         if ( manifestFile != null )
@@ -645,23 +694,43 @@ public class MavenArchiver
             // "Forced build is disabled, but disabling the forced mode isn't supported by the archiver." );
         }
 
+        String automaticModuleName = manifest.getMainSection().getAttributeValue( "Automatic-Module-Name" );
+        if ( automaticModuleName != null )
+        {
+            if ( !isValidModuleName( automaticModuleName ) )
+            {
+                throw new ManifestException( "Invalid automatic module name: '" + automaticModuleName + "'" );
+            }
+        }
+
         // create archive
         archiver.createArchive();
     }
 
-    private void addCreatedByEntry( MavenSession session, Manifest m, Map<String, String> entries )
+    private void handleDefaultEntries( Manifest m, Map<String, String> entries )
         throws ManifestException
     {
-        String createdBy = "Apache Maven";
-        if ( session != null ) // can be null due to API backwards compatibility
-        {
-            String mavenVersion = session.getSystemProperties().getProperty( "maven.version" );
-            if ( mavenVersion != null )
-            {
-                createdBy += " " + mavenVersion;
-            }
-        }
-        addManifestAttribute( m, entries, "Created-By", createdBy );
+         String createdBy = this.createdBy;
+         if ( createdBy == null )
+         {
+             createdBy = createdBy( CREATED_BY, "org.apache.maven", "maven-archiver" );
+         }
+         addManifestAttribute( m, entries, "Created-By", createdBy );
+         if ( buildJdkSpecDefaultEntry )
+         {
+             addManifestAttribute( m, entries, "Build-Jdk-Spec", System.getProperty( "java.specification.version" ) );
+         }
+    }
+
+    private void handleBuildEnvironmentEntries( MavenSession session, Manifest m, Map<String, String> entries )
+        throws ManifestException
+    {
+        addManifestAttribute( m, entries, "Build-Tool",
+            session != null ? session.getSystemProperties().getProperty( "maven.build.version" ) : "Apache Maven" );
+        addManifestAttribute( m, entries, "Build-Jdk", String.format( "%s (%s)", System.getProperty( "java.version" ),
+            System.getProperty( "java.vendor" ) ) );
+        addManifestAttribute( m, entries, "Build-Os", String.format( "%s (%s; %s)", System.getProperty( "os.name" ),
+            System.getProperty( "os.version" ), System.getProperty( "os.arch" ) ) );
     }
 
     private Artifact findArtifactWithFile( Set<Artifact> artifacts, File file )
@@ -679,4 +748,169 @@ public class MavenArchiver
         }
         return null;
     }
+
+    private static String getCreatedByVersion( String groupId, String artifactId )
+    {
+        final Properties properties = loadOptionalProperties( MavenArchiver.class.getResourceAsStream(
+            "/META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" ) );
+
+        return properties.getProperty( "version" );
+    }
+
+    private static Properties loadOptionalProperties( final InputStream inputStream )
+    {
+        Properties properties = new Properties();
+        if ( inputStream != null )
+        {
+            try ( InputStream in = inputStream )
+            {
+                properties.load( in );
+            }
+            catch ( IllegalArgumentException | IOException ex )
+            {
+                // ignore and return empty properties
+            }
+        }
+        return properties;
+    }
+
+    /**
+     * 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.5.0
+     */
+    public void setCreatedBy( String description, String groupId, String artifactId )
+    {
+        createdBy = createdBy( description, groupId, artifactId );
+    }
+
+    private String createdBy( String description, String groupId, String artifactId )
+    {
+        String createdBy = description;
+        String version = getCreatedByVersion( groupId, artifactId );
+        if ( version != null )
+        {
+            createdBy += " " + version;
+        }
+        return createdBy;
+    }
+
+    /**
+     * 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.
+     *
+     * @param buildJdkSpecDefaultEntry the value for "Build-Jdk-Spec" entry
+     * @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
+     * @throws IllegalArgumentException if the outputTimestamp is neither ISO 8601 nor an integer, or it's not within
+     *             the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z
+     * @deprecated Use {@link #parseBuildOutputTimestamp(String)} instead.
+     */
+    @Deprecated
+    public Date parseOutputTimestamp( String outputTimestamp )
+    {
+        return parseBuildOutputTimestamp( outputTimestamp ).map( Date::from ).orElse( null );
+    }
+
+    /**
+     * Configure Reproducible Builds archive creation if a timestamp is provided.
+     *
+     * @param outputTimestamp the value of {@code ${project.build.outputTimestamp}} (may be {@code null})
+     * @return the parsed timestamp as {@link java.util.Date}
+     * @since 3.5.0
+     * @see #parseOutputTimestamp
+     * @deprecated Use {@link #configureReproducibleBuild(String)} instead.
+     */
+    @Deprecated
+    public Date configureReproducible( String outputTimestamp )
+    {
+        configureReproducibleBuild( outputTimestamp );
+        return parseOutputTimestamp( outputTimestamp );
+    }
+
+    /**
+     * Parse output timestamp configured for Reproducible Builds' archive entries.
+     *
+     * <p>Either as {@link java.time.format.DateTimeFormatter#ISO_OFFSET_DATE_TIME} or as a number 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}} (may be {@code null})
+     * @return the parsed timestamp as an {@code Optional<Instant>}, {@code empty} if input is {@code null} or input
+     *         contains only 1 character (not a number)
+     * @since 3.6.0
+     * @throws IllegalArgumentException if the outputTimestamp is neither ISO 8601 nor an integer, or it's not within
+     *             the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z
+     */
+    public static Optional<Instant> parseBuildOutputTimestamp( String outputTimestamp )
+    {
+        // Fail-fast on nulls
+        if ( outputTimestamp == null )
+        {
+            return Optional.empty();
+        }
+
+        // Number representing seconds since the epoch
+        if ( StringUtils.isNotEmpty( outputTimestamp ) && StringUtils.isNumeric( outputTimestamp ) )
+        {
+            return Optional.of( Instant.ofEpochSecond( Long.parseLong( outputTimestamp ) ) );
+        }
+
+        // no timestamp configured (1 character configuration is useful to override a full value during pom
+        // inheritance)
+        if ( outputTimestamp.length() < 2 )
+        {
+            return Optional.empty();
+        }
+
+        try
+        {
+            // Parse the date in UTC such as '2011-12-03T10:15:30Z' or with an offset '2019-10-05T20:37:42+06:00'.
+            final Instant date = OffsetDateTime.parse( outputTimestamp )
+                .withOffsetSameInstant( ZoneOffset.UTC ).truncatedTo( ChronoUnit.SECONDS ).toInstant();
+
+            if ( date.isBefore( DATE_MIN ) || date.isAfter( DATE_MAX ) )
+            {
+                throw new IllegalArgumentException( "'" + date + "' is not within the valid range "
+                    + DATE_MIN + " to " + DATE_MAX );
+            }
+            return Optional.of( date );
+        }
+        catch ( DateTimeParseException 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} (may be {@code null})
+     * @since 3.6.0
+     * @see #parseBuildOutputTimestamp(String)
+     */
+    public void configureReproducibleBuild( String outputTimestamp )
+    {
+        parseBuildOutputTimestamp( outputTimestamp )
+            .map( FileTime::from )
+            .ifPresent( modifiedTime -> getArchiver().configureReproducibleBuild( modifiedTime ) );
+    }
 }


=====================================
src/main/java/org/apache/maven/archiver/PomPropertiesUtil.java
=====================================
@@ -21,45 +21,39 @@ package org.apache.maven.archiver;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Properties;
 
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.project.MavenProject;
-import org.apache.maven.shared.utils.io.IOUtil;
 import org.codehaus.plexus.archiver.Archiver;
 
 /**
- * This class is responsible for creating the pom.properties file.
+ * This class is responsible for creating the <code>pom.properties</code> file
+ * in <code>META-INF/maven/${groupId}/${artifactId}</code>.
  *
- * @version $Id: PomPropertiesUtil.java 1745000 2016-05-21 23:00:43Z michaelo $
+ * @author slachiewicz
+ * @version $Id: $Id
  */
 public class PomPropertiesUtil
 {
-    private static final String CREATED_BY_MAVEN = "Created by Apache Maven";
-
     private Properties loadPropertiesFile( File file )
         throws IOException
     {
         Properties fileProps = new Properties();
-        InputStream istream = null;
-        try
+        try ( InputStream istream = Files.newInputStream( file.toPath() ) )
         {
-            istream = new FileInputStream( file );
             fileProps.load( istream );
-            istream.close();
-            istream = null;
             return fileProps;
         }
-        finally
-        {
-            IOUtil.close( istream );
-        }
     }
 
     private boolean sameContents( Properties props, File file )
@@ -74,8 +68,7 @@ public class PomPropertiesUtil
         return fileProps.equals( props );
     }
 
-    private void createPropertiesFile( MavenSession session, Properties properties, File outputFile,
-                                       boolean forceCreation )
+    private void createPropertiesFile( Properties properties, File outputFile, boolean forceCreation )
         throws IOException
     {
         File outputDir = outputFile.getParentFile();
@@ -87,57 +80,45 @@ public class PomPropertiesUtil
         {
             return;
         }
-        PrintWriter pw = new PrintWriter( outputFile, "ISO-8859-1" );
-        try
+        
+        try ( PrintWriter pw = new PrintWriter( outputFile, "ISO-8859-1" );
+              StringWriter sw = new StringWriter() )
         {
-            String createdBy = CREATED_BY_MAVEN;
-            if ( session != null ) // can be null due to API backwards compatibility
-            {
-                String mavenVersion = session.getSystemProperties().getProperty( "maven.version" );
-                if ( mavenVersion != null )
-                {
-                    createdBy += " " + mavenVersion;
-                }
-            }
-
-            StringWriter sw = new StringWriter();
+            
             properties.store( sw, null );
 
-            BufferedReader r = new BufferedReader( new StringReader( sw.toString() ) );
-
-            pw.println( "#" + createdBy );
-            String line;
-            while ( ( line = r.readLine() ) != null )
+            List<String> lines = new ArrayList<>();
+            try ( BufferedReader r = new BufferedReader( new StringReader( sw.toString() ) ) )
             {
-                if ( !line.startsWith( "#" ) )
+                String line;
+                while ( ( line = r.readLine() ) != null )
                 {
-                    pw.println( line );
+                    if ( !line.startsWith( "#" ) )
+                    {
+                        lines.add( line );
+                    }
                 }
             }
 
-            r.close();
-            r = null;
-            sw.close();
-            sw = null;
-            pw.close();
-            pw = null;
-        }
-        finally
-        {
-            IOUtil.close( pw );
+            Collections.sort( lines );
+            for ( String l : lines )
+            {
+                pw.println( l );
+            }
         }
     }
 
     /**
      * Creates the pom.properties file.
-     * @param session {@link MavenSession}
-     * @param project {@link MavenProject}
-     * @param archiver {@link Archiver}
+     *
+     * @param session {@link org.apache.maven.execution.MavenSession}
+     * @param project {@link org.apache.maven.project.MavenProject}
+     * @param archiver {@link org.codehaus.plexus.archiver.Archiver}
      * @param customPomPropertiesFile optional custom pom properties file
      * @param pomPropertiesFile The pom properties file.
      * @param forceCreation force creation true/false
      * @throws org.codehaus.plexus.archiver.ArchiverException archiver exception.
-     * @throws IOException IO exception.
+     * @throws java.io.IOException IO exception.
      */
     public void createPomProperties( MavenSession session, MavenProject project, Archiver archiver,
                                      File customPomPropertiesFile, File pomPropertiesFile, boolean forceCreation )
@@ -164,7 +145,7 @@ public class PomPropertiesUtil
 
         p.setProperty( "version", version );
 
-        createPropertiesFile( session, p, pomPropertiesFile, forceCreation );
+        createPropertiesFile( p, pomPropertiesFile, forceCreation );
 
         archiver.addFile( pomPropertiesFile, "META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" );
     }


=====================================
src/site/apt/examples/classpath.apt
=====================================
@@ -28,17 +28,17 @@ Set Up The Classpath
 * {Contents}
 
   * {{{Add}Add A Class-Path Entry To The Manifest}}
-  
+
   * {{{Make}Make The Jar Executable}}
-  
+
   * {{{Prefix}Altering The Classpath: Defining a Classpath Directory Prefix}}
-  
+
   * {{{Repository}Altering The Classpath: Using a Maven Repository-Style Classpath}}
-  
+
   * {{{Custom}Altering The Classpath: Using a Custom Classpath Format}}
-  
+
   * {{{Snapshot}Handling Snapshot Versions}}
-  
+
   []
 
 * {Add} A Class-Path Entry To The Manifest
@@ -90,7 +90,6 @@ Set Up The Classpath
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar
 +-----+
@@ -149,7 +148,6 @@ Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 Main-Class: fully.qualified.MainClass
 Class-Path: plexus-utils-1.1.jar commons-lang-2.1.jar
@@ -213,7 +211,7 @@ Class-Path: lib/plexus-utils-1.1.jar lib/commons-lang-2.1.jar
 
   Occasionally, you may want to include a Maven repository-style directory structure in your
   archive. If you wish to reference the dependency archives within those directories in your
-  manifest classpath, try using the <<<\<classpathLayoutType\>>>> element with a value of 
+  manifest classpath, try using the <<<\<classpathLayoutType\>>>> element with a value of
   <<<'repository'>>>, like this:
 
 +-----+
@@ -230,10 +228,6 @@ Class-Path: lib/plexus-utils-1.1.jar lib/commons-lang-2.1.jar
               <addClasspath>true</addClasspath>
               <classpathPrefix>lib/</classpathPrefix>
               <classpathLayoutType>repository</classpathLayoutType>
-              
-              <!-- NOTE: Deprecated in version 2.4. Use 'classpathLayoutType' instead.
-              <classpathMavenRepositoryLayout>true</classpathMavenRepositoryLayout>
-              -->
             </manifest>
           </archive>
         </configuration>
@@ -257,11 +251,6 @@ Class-Path: lib/plexus-utils-1.1.jar lib/commons-lang-2.1.jar
 </project>
 +-----+
 
-  <<Note:>> In version 2.3, this feature was available by setting the <<<\<classpathMavenRepositoryLayout\>>>>
-  element to the value <<<true>>>. This configuration option has been *deprecated* in version 2.4, 
-  in favor of the more general <<<\<classpathLayoutType\>>>> element, where a value of <<<'repository'>>>
-  will render the same behavior.
-
  The manifest classpath produced using the above configuration would look like this:
 
 +-----+
@@ -276,7 +265,7 @@ Class-Path: lib/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar lib/co
 
   At times, you may have dependency archives in a custom format within your own archive, one that doesn't
   conform to any of the above classpath layouts. If you wish to define a custom layout for dependency archives
-  within your archive's manifest classpath, try using the <<<\<classpathLayoutType\>>>> element with a value of 
+  within your archive's manifest classpath, try using the <<<\<classpathLayoutType\>>>> element with a value of
   <<<'custom'>>>, along with the <<<\<customClasspathLayout\>>>> element, like this:
 
 +-----+
@@ -315,35 +304,35 @@ Class-Path: lib/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar lib/co
 </project>
 +-----+
 
-  This classpath layout is a little more involved than the previous examples. 
+  This classpath layout is a little more involved than the previous examples.
   To understand how the value of the <<<\<customClasspathLayout\>>>> configuration
-  is interpreted, it's useful to understand the rules applied when resolving 
+  is interpreted, it's useful to understand the rules applied when resolving
   expressions within the value:
-  
+
   [[1]] If present, trim off the prefix 'artifact.' from the expression.
-  
-  [[2]] Attempt to resolve the expression as a reference to the Artifact using 
-        reflection (eg. <<<'artifactId'>>> becomes a reference to the method 
+
+  [[2]] Attempt to resolve the expression as a reference to the Artifact using
+        reflection (eg. <<<'artifactId'>>> becomes a reference to the method
         <<<'getArtifactId()'>>>).
-  
-  [[3]] Attempt to resolve the expression as a reference to the ArtifactHandler of 
+
+  [[3]] Attempt to resolve the expression as a reference to the ArtifactHandler of
         the current Artifact, again using reflection (eg. <<<'extension'>>> becomes a reference
         to the method <<<'getExtension()'>>>).
-        
-  [[4]] Attempt to resolve the expression as a key in the special-case Properties instance, 
+
+  [[4]] Attempt to resolve the expression as a key in the special-case Properties instance,
         which contains the following mappings:
-        
-        * <<<'dashClassifier'>>>: If the Artifact has a classifier, this will be 
-                                  <<<'-${artifact.classifier}'>>>, otherwise this 
+
+        * <<<'dashClassifier'>>>: If the Artifact has a classifier, this will be
+                                  <<<'-${artifact.classifier}'>>>, otherwise this
                                   is an empty string.
-        
+
         * <<<'dashClassifier?'>>>: This is a synonym of <<<'dashClassifier'>>>.
-        
-        * <<<'groupIdPath'>>>: This is the equivalent of <<<'${artifact.groupId}'>>>, 
+
+        * <<<'groupIdPath'>>>: This is the equivalent of <<<'${artifact.groupId}'>>>,
                                with all <<<'.'>>> characters replaced by <<<'/'>>>.
-                               
+
         []
-        
+
   []
 
  The manifest classpath produced using the above configuration would look like this:
@@ -359,18 +348,18 @@ Class-Path: WEB-INF/lib/org/codehaus/plexus/plexus-utils-1.1.jar WEB-INF/lib/com
 
   <(Since 2.4)>
 
-  Depending on how you construct your archive, you may have the ability to specify whether 
+  Depending on how you construct your archive, you may have the ability to specify whether
   snapshot dependency archives are included with the version suffix <<<'-SNAPSHOT'>>>, or
   whether the unique timestamp and build-number for that archive is used. For instance,
   the {{{/plugins/maven-assembly-plugin}Assembly Plugin}} allows
-  you to make this decision in the <<<\<outputFileNameMapping\>>>> element of its 
+  you to make this decision in the <<<\<outputFileNameMapping\>>>> element of its
   <<<\<dependencySet>>>> descriptor section.
-  
+
 ** Forcing the use of -SNAPSHOT versions when using the simple (default) or repository classpath layout
 
   To force the use of <<<'-SNAPSHOT'>>> version naming, simply disable the <<<\<useUniqueVersions\>>>>
   configuration element, like this:
-  
+
 +-----+
 <useUniqueVersions>false</useUniqueVersions>
 +-----+
@@ -379,13 +368,13 @@ Class-Path: WEB-INF/lib/org/codehaus/plexus/plexus-utils-1.1.jar WEB-INF/lib/com
 
   To force the use of <<<'-SNAPSHOT'>>> version naming, simply replace <<<'${artifact.version}'>>>
   with <<<'${artifact.baseVersion}'>>> in the custom layout example above, so it looks like this:
-  
+
 +-----+
 <customClasspathLayout>WEB-INF/lib/${artifact.groupIdPath}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</customClasspathLayout>
 +-----+
 
   The full example configuration would look like this:
-  
+
 +-----+
 <project>
   ...


=====================================
src/site/apt/examples/manifest.apt
=====================================
@@ -33,10 +33,12 @@ Manifest
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 +-----+
 
+ <<Note:>> The <<<Build-Jdk>>> does not take toolchains configuration into account. It is the same
+ JDK version as running the Maven instance.
+
 * Adding Implementation And Specification Details
 
  Starting with version 2.1, Maven Archiver no longer creates the
@@ -79,21 +81,15 @@ Build-Jdk: ${java.version}
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 Specification-Title: ${project.name}
 Specification-Version: ${project.artifact.selectedVersion.majorVersion}.${project.artifact.selectedVersion.minorVersion}
 Specification-Vendor: ${project.organization.name}
 Implementation-Title: ${project.name}
 Implementation-Version: ${project.version}
-Implementation-Vendor-Id: ${project.groupId}
 Implementation-Vendor: ${project.organization.name}
-Implementation-URL: ${project.url}
 +-----+
 
  <<Note:>> If your pom.xml does not have an <<<\<organization\>>>>/<<<\<name\>>>>
  element, then the <<<Specification-Vendor>>> and <<<Implementation-Vendor>>>
  entries will <<not>> be in the manifest.
-
- <<Note:>> If your pom.xml does not have a <<<\<url\>>>> element, referenced through interpolation,
- then the <<<Implementation-URL>>> entry will <<not>> be in the manifest..


=====================================
src/site/apt/examples/manifestEntries.apt
=====================================
@@ -69,7 +69,6 @@ Manifest Entries
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 mode: development
 url: http://some.url.org/


=====================================
src/site/apt/examples/manifestSections.apt
=====================================
@@ -75,7 +75,6 @@ Manifest Sections
 +-----+
 Manifest-Version: 1.0
 Created-By: Apache Maven ${maven.version}
-Built-By: ${user.name}
 Build-Jdk: ${java.version}
 
 Name: foo


=====================================
src/site/site.xml
=====================================
@@ -19,7 +19,13 @@ specific language governing permissions and limitations
 under the License.
 -->
 
-<project xmlns="http://maven.apache.org/DECORATION/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.0.0 http://maven.apache.org/xsd/decoration-1.0.0.xsd">
+<project xmlns="http://maven.apache.org/DECORATION/1.8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0 https://maven.apache.org/xsd/decoration-1.8.0.xsd">
+  <skin>
+    <groupId>org.apache.maven.skins</groupId>
+    <artifactId>maven-fluido-skin</artifactId>
+    <version>1.9</version>
+  </skin>
   <body>
     <menu name="Overview">
       <item name="Introduction" href="index.html"/>
@@ -27,7 +33,7 @@ under the License.
       <item name="Source Xref" href="xref/index.html"/>
       <!--item name="FAQ" href="faq.html"/-->
       <!-- According to https://issues.apache.org/jira/browse/MNGSITE-152 -->
-      <item name="License" href="http://www.apache.org/licenses/"/>
+      <item name="License" href="https://www.apache.org/licenses/"/>
       <item name="Download" href="download.html"/>
     </menu>
 


=====================================
src/site/xdoc/download.xml.vm
=====================================
@@ -34,7 +34,7 @@ under the License.
 
       <p>In order to guard against corrupted downloads/installations, it is highly recommended to
       <a href="http://www.apache.org/dev/release-signing#verifying-signature">verify the signature</a>
-      of the release bundles against the public <a href="http://www.apache.org/dist/maven/KEYS">KEYS</a> used by the Apache Maven
+      of the release bundles against the public <a href="https://www.apache.org/dist/maven/KEYS">KEYS</a> used by the Apache Maven
       developers.</p>
 
       <p>${project.name} is distributed under the <a href="http://www.apache.org/licenses/">Apache License, version 2.0</a>.</p>
@@ -108,8 +108,8 @@ under the License.
           <tr>
             <td>${project.name} ${project.version} (Source zip)</td>
             <td><a href="[preferred]maven/shared/${project.artifactId}-${project.version}-source-release.zip">maven/shared/${project.artifactId}-${project.version}-source-release.zip</a></td>
-            <td><a href="http://www.apache.org/dist/maven/shared/${project.artifactId}-${project.version}-source-release.zip.md5">maven/shared/${project.artifactId}-${project.version}-source-release.zip.md5</a></td>
-            <td><a href="http://www.apache.org/dist/maven/shared/${project.artifactId}-${project.version}-source-release.zip.asc">maven/shared/${project.artifactId}-${project.version}-source-release.zip.asc</a></td>
+            <td><a href="https://www.apache.org/dist/maven/shared/${project.artifactId}-${project.version}-source-release.zip.sha512">maven/shared/${project.artifactId}-${project.version}-source-release.zip.sha512</a></td>
+            <td><a href="https://www.apache.org/dist/maven/shared/${project.artifactId}-${project.version}-source-release.zip.asc">maven/shared/${project.artifactId}-${project.version}-source-release.zip.asc</a></td>
           </tr>
         </tbody>
       </table>


=====================================
src/site/xdoc/index.xml.vm
=====================================
@@ -39,13 +39,17 @@
   <compress/>
   <forced/>
   <index/>
+  <pomPropertiesFile/>
+
+  <manifestFile/>
   <<a href="#class_manifest">manifest</a>>
     <addClasspath/>
+    <addDefaultEntries/>
     <addDefaultImplementationEntries/>
     <addDefaultSpecificationEntries/>
+    <addBuildEnvironmentEntries/>
     <addExtensions/>
     <classpathLayoutType/>
-    <classpathMavenRepositoryLayout/>
     <classpathPrefix/>
     <customClasspathLayout/>
     <mainClass/>
@@ -55,7 +59,6 @@
   <manifestEntries>
     <key>value</key>
   </manifestEntries>
-  <manifestFile/>
   <manifestSections>
     <<a href="#class_manifestSection">manifestSection</a>>
       <name/>
@@ -64,7 +67,6 @@
       </manifestEntries>
     <manifestSection/>
   </manifestSections>
-  <pomPropertiesFile/>
 </archive>
       </source>
 
@@ -114,7 +116,7 @@
               and rebuild the archive, only if the latter timestamp precedes the
               former timestamps. Checking for timestamps will typically offer a
               performance gain (in particular, if the following steps in a build
-              can be suppressed, if an archive isn't recrated) on the cost that
+              can be suppressed, if an archive isn't recreated) on the cost that
               you get inaccurate results from time to time. In particular, removal
               of source files won't be detected.
               <p>
@@ -136,6 +138,22 @@
             <td>boolean</td>
             <td></td>
           </tr>
+          <tr>
+            <td>pomPropertiesFile</td>
+            <td>
+              Use this to override the auto created
+              <a href="#pom-properties-content">pom.properties</a> file
+              (only if <code>addMavenDescriptor</code> is set to <code>true</code>)
+            </td>
+            <td>File</td>
+            <td>2.3</td>
+          </tr>
+          <tr>
+            <td>manifestFile</td>
+            <td>With this you can supply your own manifest file.</td>
+            <td>File</td>
+            <td></td>
+          </tr>
           <tr>
             <td><a href="#class_manifest">manifest</a></td>
             <td></td>
@@ -148,31 +166,27 @@
             <td>Map</td>
             <td></td>
           </tr>
-          <tr>
-            <td>manifestFile</td>
-            <td>With this you can supply your own manifest file.</td>
-            <td>File</td>
-            <td></td>
-          </tr>
           <tr>
             <td><a href="#class_manifestSection">manifestSections</a></td>
             <td></td>
             <td></td>
             <td></td>
           </tr>
-          <tr>
-            <td>pomPropertiesFile</td>
-            <td>
-              Use this to override the auto created
-              <a href="#pom-properties-content">pom.properties</a> file
-              (only if <code>addMavenDescriptor</code> is set to <code>true</code>)
-            </td>
-            <td>File</td>
-            <td>2.3</td>
-          </tr>
         </table>
       </subsection>
 
+      <a name="pom-properties-content"/>
+      <subsection name="pom.properties content">
+        <p>
+          The auto created <code>pom.properties</code> file will contain the
+          following content:
+        </p>
+        <source>
+artifactId=\${project.artifactId}
+groupId=\${project.groupId}
+version=\${project.version}</source>
+      </subsection>
+
       <a name="class_manifest"/>
       <subsection name="manifest">
         <table>
@@ -191,6 +205,20 @@
             <td>boolean</td>
             <td></td>
           </tr>
+          <tr>
+            <td>addDefaultEntries</td>
+            <td>
+              If the manifest will contain these entries:
+              <source>
+Created-By: Maven Archiver ${maven-archiver.version}
+Build-Jdk-Spec: ${java.specification.version}</source>
+              Since 3.5.0, the default value of <code>Created-By</code> entry can be overridden using
+              <a href="./apidocs/org/apache/maven/archiver/MavenArchiver.html">MavenArchiver.setCreatedBy(...)</a> API.<br />
+              The default value is <code>true</code>.
+            </td>
+            <td>boolean</td>
+            <td>3.4.0</td>
+          </tr>
           <tr>
             <td>addDefaultImplementationEntries</td>
             <td>
@@ -198,10 +226,7 @@
               <source>
 Implementation-Title: \${project.name}
 Implementation-Version: \${project.version}
-Implementation-Vendor-Id: \${project.groupId}
-Implementation-Vendor: \${project.organization.name}
-Implementation-URL: \${project.url}
-              </source>
+Implementation-Vendor: \${project.organization.name}</source>
               The default value is <code>false</code>.
             </td>
             <td>boolean</td>
@@ -214,13 +239,25 @@ Implementation-URL: \${project.url}
               <source>
 Specification-Title: \${project.name}
 Specification-Version: \${project.artifact.selectedVersion.majorVersion}.\${project.artifact.selectedVersion.minorVersion}
-Specification-Vendor: \${project.organization.name}
-              </source>
+Specification-Vendor: \${project.organization.name}</source>
               The default value is <code>false</code>.
             </td>
             <td>boolean</td>
             <td>2.1</td>
           </tr>
+          <tr>
+            <td>addBuildEnvironmentEntries</td>
+            <td>
+              If the manifest will contain these entries:
+              <source>
+Build-Tool: ${maven.build.version}
+Build-Jdk: ${java.version} (${java.vendor})
+Build-Os:  ${os.name} (${os.version}; (${os.arch})</source>
+              The default value is <code>false</code>.
+            </td>
+            <td>boolean</td>
+            <td>3.4.0</td>
+          </tr>
           <tr>
             <td>addExtensions</td>
             <td>
@@ -246,17 +283,6 @@ Specification-Vendor: \${project.organization.name}
             <td>String</td>
             <td>2.4</td>
           </tr>
-          <tr>
-            <td>classpathMavenRepositoryLayout</td>
-            <td>
-              The created <code>Class-Path</code> entry will contain paths
-              that follow the Maven 2 repository layout:
-              <code>${groupId}/${artifactId}/${version}/${fileName}</code>.
-              The default value is <code>false</code>.
-            </td>
-            <td>boolean</td>
-            <td>2.3</td>
-          </tr>
           <tr>
             <td>classpathPrefix</td>
             <td>
@@ -333,19 +359,6 @@ Specification-Vendor: \${project.organization.name}
           </tr>
         </table>
       </subsection>
-
-      <a name="pom-properties-content"/>
-      <subsection name="pom.properties content">
-        <p>
-          The auto created <code>pom.properties</code> file will contain the
-          following content:
-        </p>
-        <source>
-version=\${project.version}
-groupId=\${project.groupId}
-artifactId=\${project.artifactId}
-        </source>
-      </subsection>
     </section>
   </body>
-</document>
\ No newline at end of file
+</document>


=====================================
src/test/java/org/apache/maven/archiver/ManifestConfigurationTest.java
=====================================
@@ -21,15 +21,15 @@ package org.apache.maven.archiver;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
 
-public class ManifestConfigurationTest
+class ManifestConfigurationTest
 {
 
     private ManifestConfiguration manifestConfiguration;
 
-    @Before
+    @BeforeEach
     public void before()
     {
         this.manifestConfiguration = new ManifestConfiguration();


=====================================
src/test/java/org/apache/maven/archiver/MavenArchiveConfigurationTest.java
=====================================
@@ -24,32 +24,29 @@ import static org.assertj.core.api.Assertions.entry;
 
 import java.util.Map;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author Karl Heinz Marbaise <a href="mailto:khmarbaise at apache.org">khmarbaise at apache.org</a>.
  */
-public class MavenArchiveConfigurationTest
+class MavenArchiveConfigurationTest
 {
 
-    private ManifestConfiguration manifestConfiguration;
-
     private MavenArchiveConfiguration archive;
 
-    @Before
+    @BeforeEach
     public void before()
     {
-        this.manifestConfiguration = new ManifestConfiguration();
         archive = new MavenArchiveConfiguration();
-        archive.setManifest( manifestConfiguration );
+        archive.setManifest( new ManifestConfiguration() );
         archive.setForced( false );
         archive.setCompress( false );
         archive.setIndex( false );
     }
 
     @Test
-    public void addingSingleEntryShouldBeReturned()
+    void addingSingleEntryShouldBeReturned()
     {
         archive.addManifestEntry( "key1", "value1" );
         Map<String, String> manifestEntries = archive.getManifestEntries();
@@ -57,7 +54,7 @@ public class MavenArchiveConfigurationTest
     }
 
     @Test
-    public void addingTwoEntriesShouldBeReturnedInInsertOrder()
+    void addingTwoEntriesShouldBeReturnedInInsertOrder()
     {
         archive.addManifestEntry( "key1", "value1" );
         archive.addManifestEntry( "key2", "value2" );
@@ -66,7 +63,7 @@ public class MavenArchiveConfigurationTest
     }
 
     @Test
-    public void addingThreeEntriesShouldBeReturnedInInsertOrder()
+    void addingThreeEntriesShouldBeReturnedInInsertOrder()
     {
         archive.addManifestEntry( "key1", "value1" );
         archive.addManifestEntry( "key2", "value2" );


=====================================
src/test/java/org/apache/maven/archiver/MavenArchiverTest.java
=====================================
@@ -23,7 +23,6 @@ import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.artifact.handler.ArtifactHandler;
 import org.apache.maven.artifact.handler.DefaultArtifactHandler;
-import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.MavenExecutionRequest;
@@ -33,21 +32,28 @@ import org.apache.maven.model.Build;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Organization;
 import org.apache.maven.project.MavenProject;
-import org.apache.maven.shared.utils.StringUtils;
-import org.apache.maven.shared.utils.io.FileUtils;
-import org.apache.maven.shared.utils.io.IOUtil;
-import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 import org.codehaus.plexus.archiver.jar.ManifestException;
-import org.junit.Test;
-import org.sonatype.aether.RepositorySystemSession;
-import org.sonatype.aether.util.DefaultRepositorySystemSession;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.StringUtils;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystemSession;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.EmptySource;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URL;
+import java.time.Instant;
+import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -63,9 +69,10 @@ import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 
-import static org.junit.Assert.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 
-public class MavenArchiverTest
+class MavenArchiverTest
 {
     static class ArtifactComparator
         implements Comparator<Artifact>
@@ -81,8 +88,25 @@ public class MavenArchiverTest
         }
     }
 
+    @ParameterizedTest
+    @EmptySource
+    @ValueSource( strings = { ".", "dash-is-invalid", "plus+is+invalid", "colon:is:invalid", "new.class",
+        "123.at.start.is.invalid", "digit.at.123start.is.invalid" } )
+    void testInvalidModuleNames( String value )
+    {
+        assertThat( MavenArchiver.isValidModuleName( value ) ).isFalse();
+    }
+
+    @ParameterizedTest
+    @ValueSource( strings = { "a", "a.b", "a_b", "trailing0.digits123.are456.ok789", "UTF8.chars.are.okay.äëïöüẍ",
+        "ℤ€ℕ" } )
+    void testValidModuleNames( String value )
+    {
+        assertThat( MavenArchiver.isValidModuleName( value ) ).isTrue();
+    }
+
     @Test
-    public void testGetManifestExtensionList()
+    void testGetManifestExtensionList()
         throws Exception
     {
         MavenArchiver archiver = new MavenArchiver();
@@ -94,7 +118,7 @@ public class MavenArchiverTest
 
         MavenProject project = new MavenProject( model );
         // we need to sort the artifacts for test purposes
-        Set<Artifact> artifacts = new TreeSet<Artifact>( new ArtifactComparator() );
+        Set<Artifact> artifacts = new TreeSet<>( new ArtifactComparator() );
         project.setArtifacts( artifacts );
 
         // there should be a mock or a setter for this field.
@@ -106,13 +130,11 @@ public class MavenArchiverTest
             }
         };
 
-        Manifest manifest;
-
-        manifest = archiver.getManifest( session, project, config );
+        Manifest manifest = archiver.getManifest( session, project, config );
 
-        assertNotNull( manifest.getMainAttributes() );
+        assertThat( manifest.getMainAttributes() ).isNotNull();
 
-        assertEquals( null, manifest.getMainAttributes().getValue( "Extension-List" ) );
+        assertThat( manifest.getMainAttributes().getValue( "Extension-List" ) ).isNull();
 
         MockArtifact artifact1 = new MockArtifact();
         artifact1.setGroupId( "org.apache.dummy" );
@@ -125,7 +147,7 @@ public class MavenArchiverTest
 
         manifest = archiver.getManifest( session, project, config );
 
-        assertEquals( null, manifest.getMainAttributes().getValue( "Extension-List" ) );
+        assertThat( manifest.getMainAttributes().getValue( "Extension-List" ) ).isNull();
 
         MockArtifact artifact2 = new MockArtifact();
         artifact2.setGroupId( "org.apache.dummy" );
@@ -138,7 +160,7 @@ public class MavenArchiverTest
 
         manifest = archiver.getManifest( session, project, config );
 
-        assertEquals( "dummy2", manifest.getMainAttributes().getValue( "Extension-List" ) );
+        assertThat( manifest.getMainAttributes().getValue( "Extension-List" ) ).isEqualTo( "dummy2" );
 
         MockArtifact artifact3 = new MockArtifact();
         artifact3.setGroupId( "org.apache.dummy" );
@@ -151,7 +173,7 @@ public class MavenArchiverTest
 
         manifest = archiver.getManifest( session, project, config );
 
-        assertEquals( "dummy2", manifest.getMainAttributes().getValue( "Extension-List" ) );
+        assertThat( manifest.getMainAttributes().getValue( "Extension-List" ) ).isEqualTo( "dummy2" );
 
         MockArtifact artifact4 = new MockArtifact();
         artifact4.setGroupId( "org.apache.dummy" );
@@ -164,11 +186,11 @@ public class MavenArchiverTest
 
         manifest = archiver.getManifest( session, project, config );
 
-        assertEquals( "dummy2 dummy4", manifest.getMainAttributes().getValue( "Extension-List" ) );
+        assertThat( manifest.getMainAttributes().getValue( "Extension-List" ) ).isEqualTo( "dummy2 dummy4" );
     }
 
     @Test
-    public void testMultiClassPath()
+    void testMultiClassPath()
         throws Exception
     {
         final File tempFile = File.createTempFile( "maven-archiver-test-", ".jar" );
@@ -182,7 +204,7 @@ public class MavenArchiverTest
             Model model = new Model();
             model.setArtifactId( "dummy" );
 
-            MavenProject project = new MavenProject( model)
+            MavenProject project = new MavenProject( model )
             {
                 public List<String> getRuntimeClasspathElements()
                 {
@@ -205,9 +227,11 @@ public class MavenArchiverTest
 
             Manifest manifest = archiver.getManifest( session, project, archiveConfiguration );
             String classPath = manifest.getMainAttributes().getValue( "Class-Path" );
-            assertTrue( "User specified Class-Path entry was not added to manifest", classPath.contains( "help/" ) );
-            assertTrue( "Class-Path generated by addClasspath was not added to manifest",
-                        classPath.contains( tempFile.getName() ) );
+            assertThat( classPath )
+                    .as( "User specified Class-Path entry was not prepended to manifest" )
+                    .startsWith( "help/" )
+                    .as( "Class-Path generated by addClasspath was not appended to manifest" )
+                    .endsWith( tempFile.getName() );
         }
         finally
         {
@@ -217,7 +241,7 @@ public class MavenArchiverTest
     }
 
     @Test
-    public void testRecreation()
+    void testRecreation()
         throws Exception
     {
         File jarFile = new File( "target/test/dummy.jar" );
@@ -231,100 +255,80 @@ public class MavenArchiverTest
         MavenArchiveConfiguration config = new MavenArchiveConfiguration();
         config.setForced( false );
 
-        FileUtils.deleteDirectory( "target/maven-archiver" );
+        File directory = new File( "target/maven-archiver" );
+        org.apache.commons.io.FileUtils.deleteDirectory( directory );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
-        jarFile.setLastModified( System.currentTimeMillis() - 60000L );
+        assertThat( jarFile ).exists();
+
+        long history = System.currentTimeMillis() - 60000L;
+        jarFile.setLastModified( history );
         long time = jarFile.lastModified();
 
-        List<File> files = FileUtils.getFiles( new File( "target/maven-archiver" ), "**/**", null, true );
-        for ( Object file : files )
+        List<File> files = FileUtils.getFiles( directory, "**/**", null, true );
+        for ( File file : files )
         {
-            File f = (File) file;
-            f.setLastModified( time );
+            assertThat( file.setLastModified( time ) ).isTrue();
         }
 
         archiver.createArchive( session, project, config );
-        assertEquals( jarFile.lastModified(), time );
 
         config.setForced( true );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.lastModified() > time );
+        // I'm not sure if it could only be greater than time or if it is sufficient to be greater or equal..
+        assertThat( jarFile.lastModified() ).isGreaterThanOrEqualTo( time );
     }
 
     @Test
-    public void testNotGenerateImplementationVersionForMANIFESTMF()
+    void testNotGenerateImplementationVersionForMANIFESTMF()
         throws Exception
     {
-        JarFile jar = null;
-        try
-        {
-            File jarFile = new File( "target/test/dummy.jar" );
-            JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
+        File jarFile = new File( "target/test/dummy.jar" );
+        JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
 
-            MavenArchiver archiver = getMavenArchiver( jarArchiver );
+        MavenArchiver archiver = getMavenArchiver( jarArchiver );
 
-            MavenSession session = getDummySession();
-            MavenProject project = getDummyProject();
+        MavenSession session = getDummySession();
+        MavenProject project = getDummyProject();
 
-            MavenArchiveConfiguration config = new MavenArchiveConfiguration();
-            config.setForced( true );
-            config.getManifest().setAddDefaultImplementationEntries( false );
-            archiver.createArchive( session, project, config );
-            assertTrue( jarFile.exists() );
+        MavenArchiveConfiguration config = new MavenArchiveConfiguration();
+        config.setForced( true );
+        config.getManifest().setAddDefaultImplementationEntries( false );
+        archiver.createArchive( session, project, config );
+        assertThat( jarFile ).exists();
 
-            jar = new JarFile( jarFile );
-            Map<Object, Object> entries = jar.getManifest().getMainAttributes();
-            assertFalse( entries.containsKey( Attributes.Name.IMPLEMENTATION_VERSION ) ); // "Implementation-Version"
-        }
-        finally
+        try ( JarFile jar = new JarFile( jarFile ) )
         {
-            // cleanup streams
-            if ( jar != null )
-            {
-                jar.close();
-            }
+            assertThat( jar.getManifest().getMainAttributes() )
+                    .doesNotContainKey( Attributes.Name.IMPLEMENTATION_VERSION ); // "Implementation-Version"
         }
     }
 
     @Test
-    public void testGenerateImplementationVersionForMANIFESTMF()
+    void testGenerateImplementationVersionForMANIFESTMF()
         throws Exception
     {
-        JarFile jar = null;
-        try
-        {
-            File jarFile = new File( "target/test/dummy.jar" );
-            JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
-
-            MavenArchiver archiver = getMavenArchiver( jarArchiver );
+        File jarFile = new File( "target/test/dummy.jar" );
+        JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
 
-            MavenSession session = getDummySession();
-            MavenProject project = getDummyProject();
-
-            String ls = System.getProperty( "line.separator" );
-            project.setDescription( "foo " + ls + " bar " );
-            MavenArchiveConfiguration config = new MavenArchiveConfiguration();
-            config.setForced( true );
-            config.getManifest().setAddDefaultImplementationEntries( true );
-            config.addManifestEntry( "Description", project.getDescription() );
-            archiver.createArchive( session, project, config );
-            assertTrue( jarFile.exists() );
+        MavenArchiver archiver = getMavenArchiver( jarArchiver );
 
-            jar = new JarFile( jarFile );
+        MavenSession session = getDummySession();
+        MavenProject project = getDummyProject();
 
-            Map<Object, Object> entries = jar.getManifest().getMainAttributes();
+        String ls = System.getProperty( "line.separator" );
+        project.setDescription( "foo " + ls + " bar " );
+        MavenArchiveConfiguration config = new MavenArchiveConfiguration();
+        config.setForced( true );
+        config.getManifest().setAddDefaultImplementationEntries( true );
+        config.addManifestEntry( "Description", project.getDescription() );
+        archiver.createArchive( session, project, config );
+        assertThat( jarFile ).exists();
 
-            assertTrue( entries.containsKey( Attributes.Name.IMPLEMENTATION_VERSION ) );
-            assertEquals( "0.1.1", entries.get( Attributes.Name.IMPLEMENTATION_VERSION ) );
-        }
-        finally
+        try ( JarFile jar = new JarFile( jarFile ) )
         {
-            // cleanup streams
-            if ( jar != null )
-            {
-                jar.close();
-            }
+            assertThat( jar.getManifest().getMainAttributes() )
+                    .containsKey( Attributes.Name.IMPLEMENTATION_VERSION )
+                    .containsEntry( Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1" );
         }
     }
 
@@ -363,7 +367,7 @@ public class MavenArchiverTest
         mftConfig.setClasspathPrefix( "./lib/" );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
     }
 
     @Test
@@ -394,10 +398,10 @@ public class MavenArchiverTest
         config.addManifestEntry( "key2", "value2" );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         final Attributes mainAttributes = getJarFileManifest( jarFile ).getMainAttributes();
-        assertEquals( "value1", mainAttributes.getValue( "Key1" ) );
-        assertEquals( "value2", mainAttributes.getValue( "Key2" ) );
+        assertThat( mainAttributes.getValue( "Key1" ) ).isEqualTo( "value1" );
+        assertThat( mainAttributes.getValue( "Key2" ) ).isEqualTo( "value2" );
     }
 
     @Test
@@ -419,17 +423,17 @@ public class MavenArchiverTest
         config.getManifest().setAddDefaultImplementationEntries( true );
         config.addManifestEntry( "Description", project.getDescription() );
         // config.addManifestEntry( "EntryWithTab", " foo tab " + ( '\u0009' ) + ( '\u0009' ) // + " bar tab" + ( //
-                                                                                              // '\u0009' // ) );
+        // '\u0009' // ) );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         final Manifest manifest = getJarFileManifest( jarFile );
         Attributes attributes = manifest.getMainAttributes();
-        assertTrue( project.getDescription().indexOf( ls ) > 0 );
+        assertThat( project.getDescription().indexOf( ls ) ).isGreaterThan( 0 );
         Attributes.Name description = new Attributes.Name( "Description" );
         String value = attributes.getValue( description );
-        assertNotNull( value );
-        assertFalse( value.indexOf( ls ) > 0 );
+        assertThat( value ).isNotNull();
+        assertThat( value.indexOf( ls ) ).isLessThanOrEqualTo( 0 );
     }
 
     @Test
@@ -447,28 +451,50 @@ public class MavenArchiverTest
         config.getManifest().setAddDefaultImplementationEntries( true );
         config.getManifest().setAddDefaultSpecificationEntries( true );
 
-        // noinspection deprecation
         MavenSession session = getDummySessionWithoutMavenVersion();
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Attributes manifest = getJarFileManifest( jarFile ).getMainAttributes();
 
-        assertEquals( "Apache Maven", manifest.get( new Attributes.Name( "Created-By" ) ) ); // no version number
+        // no version number
+        assertThat( manifest )
+                .containsEntry( new Attributes.Name( "Created-By" ), "Maven Archiver" )
+                .containsEntry( Attributes.Name.SPECIFICATION_TITLE, "archiver test" )
+                .containsEntry( Attributes.Name.SPECIFICATION_VERSION, "0.1" )
+                .containsEntry( Attributes.Name.SPECIFICATION_VENDOR, "Apache" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_TITLE, "archiver test" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_VENDOR, "Apache" )
+                .containsEntry( new Attributes.Name( "Build-Jdk-Spec" ),
+                        System.getProperty( "java.specification.version" ) );
+    }
+
+    @Test
+    public void testMinimalManifestEntries()
+        throws Exception
+    {
+        File jarFile = new File( "target/test/dummy.jar" );
+        JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
+
+        MavenArchiver archiver = getMavenArchiver( jarArchiver );
 
-        assertEquals( "archiver test", manifest.get( Attributes.Name.SPECIFICATION_TITLE ) );
-        assertEquals( "0.1", manifest.get( Attributes.Name.SPECIFICATION_VERSION ) );
-        assertEquals( "Apache", manifest.get( Attributes.Name.SPECIFICATION_VENDOR ) );
+        MavenSession session = getDummySession();
+        MavenProject project = getDummyProject();
+        MavenArchiveConfiguration config = new MavenArchiveConfiguration();
+        config.setForced( true );
+        config.getManifest().setAddDefaultEntries( false );
 
-        assertEquals( "archiver test", manifest.get( Attributes.Name.IMPLEMENTATION_TITLE ) );
-        assertEquals( "0.1.1", manifest.get( Attributes.Name.IMPLEMENTATION_VERSION ) );
-        assertEquals( "org.apache.dummy", manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR_ID ) );
-        assertEquals( "Apache", manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR ) );
-        assertEquals( "http://maven.apache.org", manifest.get( Attributes.Name.IMPLEMENTATION_URL ) );
+        archiver.createArchive( session, project, config );
+        assertThat( jarFile ).exists();
+
+        final Manifest jarFileManifest = getJarFileManifest( jarFile );
+        Attributes manifest = jarFileManifest.getMainAttributes();
 
-        assertEquals( System.getProperty( "java.version" ), manifest.get( new Attributes.Name( "Build-Jdk" ) ) );
-        assertEquals( System.getProperty( "user.name" ), manifest.get( new Attributes.Name( "Built-By" ) ) );
+        assertThat( manifest ).hasSize( 1 ).containsOnlyKeys( new Attributes.Name( "Manifest-Version" ) );
+        assertThat( manifest.getValue( "Manifest-Version" ) ).isEqualTo( "1.0" );
     }
 
+
     @Test
     public void testManifestEntries()
         throws Exception
@@ -484,76 +510,86 @@ public class MavenArchiverTest
         config.setForced( true );
         config.getManifest().setAddDefaultImplementationEntries( true );
         config.getManifest().setAddDefaultSpecificationEntries( true );
+        config.getManifest().setAddBuildEnvironmentEntries( true );
 
-        Map<String, String> manifestEntries = new HashMap<String, String>();
+        Map<String, String> manifestEntries = new HashMap<>();
         manifestEntries.put( "foo", "bar" );
         manifestEntries.put( "first-name", "olivier" );
+        manifestEntries.put( "Automatic-Module-Name", "org.apache.maven.archiver" );
         manifestEntries.put( "keyWithEmptyValue", null );
         config.setManifestEntries( manifestEntries );
 
         ManifestSection manifestSection = new ManifestSection();
         manifestSection.setName( "UserSection" );
         manifestSection.addManifestEntry( "key", "value" );
-        List<ManifestSection> manifestSections = new ArrayList<ManifestSection>();
+        List<ManifestSection> manifestSections = new ArrayList<>();
         manifestSections.add( manifestSection );
         config.setManifestSections( manifestSections );
         config.getManifest().setMainClass( "org.apache.maven.Foo" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         final Manifest jarFileManifest = getJarFileManifest( jarFile );
         Attributes manifest = jarFileManifest.getMainAttributes();
 
-        assertEquals( "Apache Maven 3.0.4", manifest.get( new Attributes.Name( "Created-By" ) ) );
-
-        assertEquals( "archiver test", manifest.get( Attributes.Name.SPECIFICATION_TITLE ) );
-        assertEquals( "0.1", manifest.get( Attributes.Name.SPECIFICATION_VERSION ) );
-        assertEquals( "Apache", manifest.get( Attributes.Name.SPECIFICATION_VENDOR ) );
-
-        assertEquals( "archiver test", manifest.get( Attributes.Name.IMPLEMENTATION_TITLE ) );
-        assertEquals( "0.1.1", manifest.get( Attributes.Name.IMPLEMENTATION_VERSION ) );
-        assertEquals( "org.apache.dummy", manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR_ID ) );
-        assertEquals( "Apache", manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR ) );
-        assertEquals( "http://maven.apache.org", manifest.get( Attributes.Name.IMPLEMENTATION_URL ) );
-
-        assertEquals( "org.apache.maven.Foo", manifest.get( Attributes.Name.MAIN_CLASS ) );
-
-        assertEquals( "bar", manifest.get( new Attributes.Name( "foo" ) ) );
-        assertEquals( "olivier", manifest.get( new Attributes.Name( "first-name" ) ) );
-
-        assertEquals( System.getProperty( "java.version" ), manifest.get( new Attributes.Name( "Build-Jdk" ) ) );
-        assertEquals( System.getProperty( "user.name" ), manifest.get( new Attributes.Name( "Built-By" ) ) );
-
-        assertTrue( StringUtils.isEmpty( manifest.getValue( new Attributes.Name( "keyWithEmptyValue" ) ) ) );
-        assertTrue( manifest.containsKey( new Attributes.Name( "keyWithEmptyValue" ) ) );
+        // no version number
+        assertThat( manifest )
+                .containsEntry( new Attributes.Name( "Created-By" ), "Maven Archiver" )
+                .containsEntry( new Attributes.Name( "Build-Tool" ),
+                        session.getSystemProperties().get( "maven.build.version" ) )
+                .containsEntry( new Attributes.Name( "Build-Jdk" ), String.format( "%s (%s)",
+                        System.getProperty( "java.version" ), System.getProperty( "java.vendor" ) ) )
+                .containsEntry( new Attributes.Name( "Build-Os" ), String.format( "%s (%s; %s)",
+                        System.getProperty( "os.name" ), System.getProperty( "os.version" ),
+                        System.getProperty( "os.arch" ) ) )
+                .containsEntry( Attributes.Name.SPECIFICATION_TITLE, "archiver test" )
+                .containsEntry( Attributes.Name.SPECIFICATION_VERSION, "0.1" )
+                .containsEntry( Attributes.Name.SPECIFICATION_VENDOR, "Apache" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_TITLE, "archiver test" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_VERSION, "0.1.1" )
+                .containsEntry( Attributes.Name.IMPLEMENTATION_VENDOR, "Apache" )
+                .containsEntry( Attributes.Name.MAIN_CLASS, "org.apache.maven.Foo" )
+                .containsEntry( new Attributes.Name( "foo" ), "bar" )
+                .containsEntry( new Attributes.Name( "first-name" ), "olivier" );
+
+        assertThat( manifest.getValue( "Automatic-Module-Name" ) ).isEqualTo( "org.apache.maven.archiver" );
+
+        assertThat( manifest ).containsEntry( new Attributes.Name( "Build-Jdk-Spec" ),
+                System.getProperty( "java.specification.version" ) );
+
+        assertThat( StringUtils.isEmpty( manifest.getValue( new Attributes.Name( "keyWithEmptyValue" ) ) ) ).isTrue();
+        assertThat( manifest ).containsKey( new Attributes.Name( "keyWithEmptyValue" ) );
 
         manifest = jarFileManifest.getAttributes( "UserSection" );
 
-        assertEquals( "value", manifest.get( new Attributes.Name( "key" ) ) );
+        assertThat( manifest ).containsEntry( new Attributes.Name( "key" ), "value" );
     }
 
     @Test
-    public void testCreatedByManifestEntryWithoutMavenVersion()
-        throws Exception
+    public void testManifestWithInvalidAutomaticModuleNameThrowsOnCreateArchive()
+            throws Exception
     {
         File jarFile = new File( "target/test/dummy.jar" );
         JarArchiver jarArchiver = getCleanJarArchiver( jarFile );
 
         MavenArchiver archiver = getMavenArchiver( jarArchiver );
 
-        MavenSession session = getDummySessionWithoutMavenVersion();
+        MavenSession session = getDummySession();
         MavenProject project = getDummyProject();
-
         MavenArchiveConfiguration config = new MavenArchiveConfiguration();
-        config.setForced( true );
 
-        archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
-
-        final Manifest manifest = getJarFileManifest( jarFile );
-        Map<Object, Object> entries = manifest.getMainAttributes();
+        Map<String, String> manifestEntries = new HashMap<>();
+        manifestEntries.put( "Automatic-Module-Name", "123.in-valid.new.name" );
+        config.setManifestEntries( manifestEntries );
 
-        assertEquals( "Apache Maven", entries.get( new Attributes.Name( "Created-By" ) ) );
+        try
+        {
+            archiver.createArchive( session, project, config );
+        }
+        catch ( ManifestException e )
+        {
+            assertThat( e.getMessage() ).isEqualTo( "Invalid automatic module name: '123.in-valid.new.name'" );
+        }
     }
 
     /*
@@ -573,18 +609,19 @@ public class MavenArchiverTest
         ManifestSection manifestSection = new ManifestSection();
         manifestSection.setName( "SectionOne" );
         manifestSection.addManifestEntry( "key", "value" );
-        List<ManifestSection> manifestSections = new ArrayList<ManifestSection>();
+        List<ManifestSection> manifestSections = new ArrayList<>();
         manifestSections.add( manifestSection );
         config.setManifestSections( manifestSections );
 
         Manifest manifest = archiver.getManifest( session, project, config );
 
         Attributes section = manifest.getAttributes( "SectionOne" );
-        assertNotNull( "The section is not present in the manifest as it should be.", section );
+        assertThat( section ).as( "The section is not present in the manifest as it should be." ).isNotNull();
 
         String attribute = section.getValue( "key" );
-        assertNotNull( "The attribute we are looking for is not present in the section.", attribute );
-        assertEquals( "The value of the attribute is wrong.", "value", attribute );
+        assertThat( attribute )
+                .as( "The attribute we are looking for is not present in the section." ).isNotNull()
+                .as( "The value of the attribute is wrong." ).isEqualTo( "value" );
     }
 
     @Test
@@ -607,20 +644,18 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
         config.getManifest().setCustomClasspathLayout( "${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         final Manifest manifest = getJarFileManifest( jarFile );
         String classPath = manifest.getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        String[] classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "dummy1-1.0.jar", "dummy2-1.5.jar", "dummy3-2.0.jar" );
     }
 
     private void deleteAndAssertNotPresent( File jarFile )
     {
         jarFile.delete();
-        assertFalse( jarFile.exists() );
+        assertThat( jarFile ).doesNotExist();
     }
 
     @Test
@@ -643,15 +678,13 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
         config.getManifest().setCustomClasspathLayout( "${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         final Manifest manifest = getJarFileManifest( jarFile );
         String classPath = manifest.getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        String[] classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "dummy1-1.1-20081022.112233-1.jar", classPathEntries[0] );
-        assertEquals( "dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "dummy1-1.1-20081022.112233-1.jar", "dummy2-1.5.jar", "dummy3-2.0.jar" );
     }
 
     @Test
@@ -674,20 +707,21 @@ public class MavenArchiverTest
         config.getManifest().setUseUniqueVersions( true );
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
+                "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
+                "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
     }
 
     @Test
@@ -711,21 +745,18 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_SIMPLE );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
 
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
     }
 
     @Test
@@ -747,24 +778,21 @@ public class MavenArchiverTest
         config.getManifest().setAddClasspath( true );
         config.getManifest().setClasspathPrefix( "lib" );
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
-        config.getManifest().setCustomClasspathLayout( MavenArchiver.SIMPLE_LAYOUT);
+        config.getManifest().setCustomClasspathLayout( MavenArchiver.SIMPLE_LAYOUT );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
 
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
     }
 
     @Test
@@ -786,24 +814,21 @@ public class MavenArchiverTest
         config.getManifest().setAddClasspath( true );
         config.getManifest().setClasspathPrefix( "lib" );
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
-        config.getManifest().setCustomClasspathLayout( MavenArchiver.SIMPLE_LAYOUT_NONUNIQUE);
+        config.getManifest().setCustomClasspathLayout( MavenArchiver.SIMPLE_LAYOUT_NONUNIQUE );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/dummy1-1.0.1.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries )
+                .containsExactly( "lib/dummy1-1.0.1.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
 
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/dummy1-1.0.1.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "lib/dummy1-1.0.1.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
     }
 
     @Test
@@ -828,21 +853,22 @@ public class MavenArchiverTest
         config.getManifest().setCustomClasspathLayout( MavenArchiver.REPOSITORY_LAYOUT );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
+                "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
 
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.jar",
+                "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
     }
 
     @Test
@@ -867,21 +893,22 @@ public class MavenArchiverTest
         config.getManifest().setCustomClasspathLayout( MavenArchiver.REPOSITORY_LAYOUT_NONUNIQUE );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar", classPathEntries[0] );
-        assertEquals( "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar",
+                "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
 
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar", classPathEntries[0] );
-        assertEquals( "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "lib/org/apache/dummy/dummy1/1.0.1/dummy1-1.0.1.jar",
+                "lib/org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "lib/org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
     }
 
     @Test
@@ -904,20 +931,17 @@ public class MavenArchiverTest
         config.getManifest().setClasspathPrefix( "lib" );
 
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "lib/dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "lib/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "lib/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) )
+                .containsExactly( "lib/dummy1-1.0.jar", "lib/dummy2-1.5.jar", "lib/dummy3-2.0.jar" );
     }
 
     @Test
@@ -939,21 +963,22 @@ public class MavenArchiverTest
         config.getManifest().setAddClasspath( true );
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_REPOSITORY );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar",
+                "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/dummy1-1.1-20081022.112233-1.jar",
+                "org/apache/dummy/foo/dummy2/1.5/dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/dummy3-2.0.jar" );
     }
 
     @Test
@@ -976,21 +1001,22 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
         config.getManifest().setCustomClasspathLayout( "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.version}/TEST-${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar",
+                "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
 
         final Manifest manifest1 = getJarFileManifest( jarFile );
         String classPath = manifest1.getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "org/apache/dummy/dummy1/1.0/TEST-dummy1-1.0.jar",
+                "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
     }
 
     @Test
@@ -1012,23 +1038,22 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
         config.getManifest().setCustomClasspathLayout( "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.baseVersion}/TEST-${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
-                      classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries ).containsExactly(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
+                "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
-                      classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-20081022.112233-1.jar",
+                "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
     }
 
     @Test
@@ -1051,20 +1076,21 @@ public class MavenArchiverTest
         config.getManifest().setClasspathLayoutType( ManifestConfiguration.CLASSPATH_LAYOUT_TYPE_CUSTOM );
         config.getManifest().setCustomClasspathLayout( "${artifact.groupIdPath}/${artifact.artifactId}/${artifact.baseVersion}/TEST-${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}" );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
         Manifest manifest = archiver.getManifest( session, project, config );
         String[] classPathEntries =
             StringUtils.split( new String( manifest.getMainAttributes().getValue( "Class-Path" ).getBytes() ), " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPathEntries[0] ).isEqualTo(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar" );
+        assertThat( classPathEntries[1] ).isEqualTo( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar" );
+        assertThat( classPathEntries[2] ).isEqualTo( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
 
         String classPath = getJarFileManifest( jarFile ).getMainAttributes().getValue( Attributes.Name.CLASS_PATH );
-        assertNotNull( classPath );
-        classPathEntries = StringUtils.split( classPath, " " );
-        assertEquals( "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar", classPathEntries[0] );
-        assertEquals( "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar", classPathEntries[1] );
-        assertEquals( "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar", classPathEntries[2] );
+        assertThat( classPath ).isNotNull();
+        assertThat( StringUtils.split( classPath, " " ) ).containsExactly(
+                "org/apache/dummy/dummy1/1.1-SNAPSHOT/TEST-dummy1-1.1-SNAPSHOT.jar",
+                "org/apache/dummy/foo/dummy2/1.5/TEST-dummy2-1.5.jar",
+                "org/apache/dummy/bar/dummy3/2.0/TEST-dummy3-2.0.jar" );
     }
 
     @Test
@@ -1081,7 +1107,7 @@ public class MavenArchiverTest
         MavenArchiveConfiguration config = new MavenArchiveConfiguration();
         config.setForced( true );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         final String groupId = project.getGroupId();
         final String artifactId = project.getArtifactId();
@@ -1090,15 +1116,17 @@ public class MavenArchiverTest
         JarFile virtJarFile = new JarFile( jarFile );
         ZipEntry pomPropertiesEntry =
             virtJarFile.getEntry( "META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" );
-        assertNotNull( pomPropertiesEntry );
-
-        InputStream is = virtJarFile.getInputStream( pomPropertiesEntry );
-        Properties p = loadProperties( is );
+        assertThat( pomPropertiesEntry ).isNotNull();
 
-        assertEquals( groupId, p.getProperty( "groupId" ) );
-        assertEquals( artifactId, p.getProperty( "artifactId" ) );
-        assertEquals( version, p.getProperty( "version" ) );
+        try ( InputStream is = virtJarFile.getInputStream( pomPropertiesEntry ) )
+        {
+            Properties p = new Properties();
+            p.load( is );
 
+            assertThat( p.getProperty( "groupId" ) ).isEqualTo( groupId );
+            assertThat( p.getProperty( "artifactId" ) ).isEqualTo( artifactId );
+            assertThat( p.getProperty( "version" ) ).isEqualTo( version );
+        }
         virtJarFile.close();
     }
 
@@ -1118,27 +1146,30 @@ public class MavenArchiverTest
         config.setForced( true );
         config.setPomPropertiesFile( customPomPropertiesFile );
         archiver.createArchive( session, project, config );
-        assertTrue( jarFile.exists() );
+        assertThat( jarFile ).exists();
 
         final String groupId = project.getGroupId();
         final String artifactId = project.getArtifactId();
         final String version = project.getVersion();
 
-        JarFile virtJarFile = new JarFile( jarFile );
-        ZipEntry pomPropertiesEntry =
-            virtJarFile.getEntry( "META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" );
-        assertNotNull( pomPropertiesEntry );
-
-        InputStream is = virtJarFile.getInputStream( pomPropertiesEntry );
-        Properties p = loadProperties( is );
-
-        assertEquals( groupId, p.getProperty( "groupId" ) );
-        assertEquals( artifactId, p.getProperty( "artifactId" ) );
-        assertEquals( version, p.getProperty( "version" ) );
-        assertEquals( "1337", p.getProperty( "build.revision" ) );
-        assertEquals( "tags/0.1.1", p.getProperty( "build.branch" ) );
+        try ( JarFile virtJarFile = new JarFile( jarFile ) )
+        {
+            ZipEntry pomPropertiesEntry = virtJarFile
+                    .getEntry( "META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties" );
+            assertThat( pomPropertiesEntry ).isNotNull();
 
-        virtJarFile.close();
+            try ( InputStream is = virtJarFile.getInputStream( pomPropertiesEntry ) )
+            {
+                Properties p = new Properties();
+                p.load( is );
+
+                assertThat( p.getProperty( "groupId" ) ).isEqualTo( groupId );
+                assertThat( p.getProperty( "artifactId" ) ).isEqualTo( artifactId );
+                assertThat( p.getProperty( "version" ) ).isEqualTo( version );
+                assertThat( p.getProperty( "build.revision" ) ).isEqualTo( "1337" );
+                assertThat( p.getProperty( "build.branch" ) ).isEqualTo( "tags/0.1.1" );
+            }
+        }
     }
 
     private JarArchiver getCleanJarArchiver( File jarFile )
@@ -1164,7 +1195,7 @@ public class MavenArchiverTest
         build.setOutputDirectory( "target" );
         project.setBuild( build );
         project.setName( "archiver test" );
-        project.setUrl( "http://maven.apache.org" );
+        project.setUrl( "https://maven.apache.org" );
         Organization organization = new Organization();
         organization.setName( "Apache" );
         project.setOrganization( organization );
@@ -1191,9 +1222,9 @@ public class MavenArchiverTest
         model.setVersion( "0.1.1" );
 
         final MavenProject project = new MavenProject( model );
-        project.setExtensionArtifacts( Collections.<Artifact>emptySet() );
-        project.setRemoteArtifactRepositories( Collections.<ArtifactRepository>emptyList() );
-        project.setPluginArtifactRepositories( Collections.<ArtifactRepository>emptyList() );
+        project.setExtensionArtifacts( Collections.emptySet() );
+        project.setRemoteArtifactRepositories( Collections.emptyList() );
+        project.setPluginArtifactRepositories( Collections.emptyList() );
         return project;
     }
 
@@ -1337,7 +1368,8 @@ public class MavenArchiverTest
         URL resource = Thread.currentThread().getContextClassLoader().getResource( file );
         if ( resource == null )
         {
-            fail("Cannot retrieve java.net.URL for file: " + file + " on the current test classpath." );
+            throw new IllegalStateException( "Cannot retrieve java.net.URL for file: " + file
+                + " on the current test classpath." );
         }
 
         URI uri = new File( resource.getPath() ).toURI().normalize();
@@ -1348,7 +1380,9 @@ public class MavenArchiverTest
     private MavenSession getDummySession()
     {
         Properties systemProperties = new Properties();
-        systemProperties.put( "maven.version", "3.0.4" );
+        systemProperties.put( "maven.version", "3.1.1" );
+        systemProperties.put( "maven.build.version",
+            "Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 17:22:22+0200)" );
 
         return getDummySession( systemProperties );
     }
@@ -1360,29 +1394,26 @@ public class MavenArchiverTest
 
     private MavenSession getDummySession( Properties systemProperties )
     {
-        PlexusContainer container = null;
-        File settings = null;
-        List<String> goals = null;
         Date startTime = new Date();
 
         MavenExecutionRequest request = new DefaultMavenExecutionRequest();
         request.setSystemProperties( systemProperties );
-        request.setGoals( goals );
+        request.setGoals( null );
         request.setStartTime( startTime );
-        request.setUserSettingsFile( settings );
+        request.setUserSettingsFile( null );
 
         MavenExecutionResult result = new DefaultMavenExecutionResult();
 
         RepositorySystemSession rss = new DefaultRepositorySystemSession();
 
-        return new MavenSession( container, rss, request, result );
+        return new MavenSession( null, rss, request, result );
 
     }
 
     private Set<Artifact> getArtifacts( Artifact... artifacts )
     {
         final ArtifactHandler mockArtifactHandler = getMockArtifactHandler();
-        Set<Artifact> result = new TreeSet<Artifact>( new ArtifactComparator() );
+        Set<Artifact> result = new TreeSet<>( new ArtifactComparator() );
         for ( Artifact artifact : artifacts )
         {
             artifact.setArtifactHandler( mockArtifactHandler );
@@ -1391,39 +1422,100 @@ public class MavenArchiverTest
         return result;
     }
 
-    private Properties loadProperties( InputStream is )
+    public Manifest getJarFileManifest( File jarFile )
         throws IOException
     {
-        Properties p = new Properties();
-        try
+        try ( JarFile jar = new JarFile( jarFile ) )
         {
-            p.load( is );
-            is.close();
-            is = null;
-            return p;
-        }
-        finally
-        {
-            IOUtil.close( is );
+            return jar.getManifest();
         }
     }
 
-    public Manifest getJarFileManifest( File jarFile )
-        throws IOException
+    @Test
+    public void testParseOutputTimestamp()
     {
-        JarFile jar = null;
-        try
-        {
-            jar = new JarFile( jarFile );
-            return jar.getManifest();
-        }
-        finally
-        {
-            if ( jar != null )
-            {
-                jar.close();
-            }
-        }
+        MavenArchiver archiver = new MavenArchiver();
+
+        assertThat( archiver.parseOutputTimestamp( null ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "" ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "." ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( " " ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "_" ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "-" ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "/" ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "!" ) ).isNull();
+        assertThat( archiver.parseOutputTimestamp( "*" ) ).isNull();
+
+        assertThat( archiver.parseOutputTimestamp( "1570300662" ).getTime() ).isEqualTo( 1570300662000L );
+        assertThat( archiver.parseOutputTimestamp( "0" ).getTime() ).isZero();
+        assertThat( archiver.parseOutputTimestamp( "1" ).getTime() ).isEqualTo( 1000L );
+
+        assertThat( archiver.parseOutputTimestamp( "2019-10-05T18:37:42Z" ).getTime() )
+            .isEqualTo( 1570300662000L );
+        assertThat( archiver.parseOutputTimestamp( "2019-10-05T20:37:42+02:00" ).getTime() )
+            .isEqualTo( 1570300662000L );
+        assertThat( archiver.parseOutputTimestamp( "2019-10-05T16:37:42-02:00" ).getTime() )
+            .isEqualTo( 1570300662000L );
+
+        // 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)
+        assertThatExceptionOfType( IllegalArgumentException.class )
+            .isThrownBy( () -> archiver.parseOutputTimestamp( "2019-10-05T20:37:42+0200" ) );
+        assertThatExceptionOfType( IllegalArgumentException.class )
+            .isThrownBy( () -> archiver.parseOutputTimestamp( "2019-10-05T20:37:42-0200" ) );
+    }
+
+    @ParameterizedTest
+    @NullAndEmptySource
+    @ValueSource( strings = { ".", " ", "_", "-", "T", "/", "!", "!", "*", "ñ" } )
+    public void testEmptyParseOutputTimestampInstant( String value )
+    {
+        // Empty optional if null or 1 char
+        assertThat( MavenArchiver.parseBuildOutputTimestamp( value ) ).isEmpty();
+    }
+
+    @ParameterizedTest
+    @CsvSource( { "0,0", "1,1", "9,9", "1570300662,1570300662", "2147483648,2147483648",
+        "2019-10-05T18:37:42Z,1570300662", "2019-10-05T20:37:42+02:00,1570300662",
+        "2019-10-05T16:37:42-02:00,1570300662", "1988-02-22T15:23:47.76598Z,572541827",
+        "2011-12-03T10:15:30+01:00,1322903730", "1980-01-01T00:00:02Z,315532802", "2099-12-31T23:59:59Z,4102444799" } )
+    public void testParseOutputTimestampInstant( String value, long expected )
+    {
+        assertThat( MavenArchiver.parseBuildOutputTimestamp( value ) )
+            .contains( Instant.ofEpochSecond( expected ) );
+    }
+
+    @ParameterizedTest
+    @ValueSource( strings = { "2019-10-05T20:37:42+0200", "2019-10-05T20:37:42-0200", "2019-10-05T25:00:00Z",
+        "2019-10-05", "XYZ", "Tue, 3 Jun 2008 11:05:30 GMT", "2011-12-03T10:15:30+01:00[Europe/Paris]" } )
+    public void testThrownParseOutputTimestampInstant( String outputTimestamp )
+    {
+        // Invalid parsing
+        assertThatExceptionOfType( IllegalArgumentException.class )
+            .isThrownBy( () -> MavenArchiver.parseBuildOutputTimestamp( outputTimestamp ) )
+            .withCauseInstanceOf( DateTimeParseException.class );
+    }
 
+    @ParameterizedTest
+    @ValueSource( strings = { "1980-01-01T00:00:01Z", "2100-01-01T00:00Z", "2100-02-28T23:59:59Z",
+        "2099-12-31T23:59:59-01:00", "1980-01-01T00:15:35+01:00", "1980-01-01T10:15:35+14:00" } )
+    public void testThrownParseOutputTimestampInvalidRange( String outputTimestamp )
+    {
+        // date is not within the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z
+        assertThatExceptionOfType( IllegalArgumentException.class )
+            .isThrownBy( () -> MavenArchiver.parseBuildOutputTimestamp( outputTimestamp ) )
+            .withMessageContaining("is not within the valid range 1980-01-01T00:00:02Z to 2099-12-31T23:59:59Z");
+    }
+
+    @ParameterizedTest
+    @CsvSource( { "2011-12-03T10:15:30+01,1322903730", "2019-10-05T20:37:42+02,1570300662",
+        "2011-12-03T10:15:30+06,1322885730", "1988-02-22T20:37:42+06,572539062" } )
+    @EnabledForJreRange( min = JRE.JAVA_9 )
+    public void testShortOffset( String value, long expected )
+    {
+        assertThat( MavenArchiver.parseBuildOutputTimestamp( value ) )
+            .contains( Instant.ofEpochSecond( expected ) );
     }
 }


=====================================
src/test/java/org/apache/maven/archiver/MockArtifact.java
=====================================
@@ -32,10 +32,11 @@ import java.io.File;
 import java.util.Collection;
 import java.util.List;
 
-/**
- * @todo move to maven-artifact-test
+/*
+ * TODO move to maven-artifact-test
  */
-class MockArtifact
+ at SuppressWarnings( "deprecation" )
+public class MockArtifact
     implements Artifact
 {
     private String groupId;



View it on GitLab: https://salsa.debian.org/java-team/maven-archiver/-/compare/39ded5165c17a81901a94ab03e7765ce64247f34...0364639b1368924c26db09b711a23735e36bb0db

-- 
View it on GitLab: https://salsa.debian.org/java-team/maven-archiver/-/compare/39ded5165c17a81901a94ab03e7765ce64247f34...0364639b1368924c26db09b711a23735e36bb0db
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/20221011/912c25e6/attachment.htm>


More information about the pkg-java-commits mailing list