Migrate from Maven Archiver to standard jar tool
#508
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a major refactoring of the Maven JAR Plugin for using the standard
jartool instead of Maven Archiver. The standard tool is available through thejava.util.spi.ToolProviderinterface, which was introduced in Java 9. Since Maven 4 upgraded its requirement from Java 8 to Java 17, the use of that interface is no longer problematic.Rational
In early Java days, the
jartool was equivalent to azipcommand with a different syntax and a little bit of special processing for theMETA-INF/MANIFEST.MFfile. Because of this quasi-equivalence, it was not difficult to create JAR files ourselves using any library capable to write ZIP files. This is what Maven Archiver does, together with supporting other archive formats. But today, thejartool became more sophisticated. It now includes options for verifying the consistency of multi-release JAR files, options for updatingmodule-info.class, provides security features specific to Java, etc.. This evolution can be seen in the "Modular JAR files" section of the Maven Plugin documentation, which states that the plugin uses thejartool for updating the JAR file in a way that the Maven Archiver can't do easily. Therefore, since Maven 4 requires Java 17 and since that Java version gives us an easy access to thejartool through thejava.util.spi.ToolProviderinterface, it may be time to abandon our manual creation of a JAR file and rely fully on thejartool instead.Benefits
Safer multi-release JAR files
In a multi-release JAR file, blindingly storing the content of
META-INF/versions/directories as if they were ordinary resources is not equivalent to using thejar --releaseoption. The difference is that in the latter case, thejartool performs some consistency checks. This issue was independently reported by user in #484, which is fixed by this pull request. Note that if this verification is not desired, Maven users can disable it by setting thedetectMultiReleaseJarplugin option tofalse.Main class managed by the
jartoolIn a modular JAR file, it is no longer sufficient to declare the main class in the
Main-Classentry of theMANIFEST.MFfile. The main class needs to be specified by the--main-classoption of thejartool, which will updatemodule-info.class. For compatibility reason the Maven JAR plugin gets the option value from that manifest entry, but internally the use of thejartool is mandatory.Options not yet supported by the plugin
This approach allows to add a
<jarArgs>configuration option, similar to the<compilerArgs>in the Maven Compiler Plugin. Such option would allow developers to use new tool arguments before they are supported by the plugin.Examples of options not yet supported by the plugin are
--module-versionand--hash-modules. Explicit support for those options could be added in a future plugin version, especially since security is becoming more and more a concern.Easier debugging and toolchain
This approach makes easy to generate a
target/jar.argsfile when the build fails or when Maven is run in verbose mode. This is similar to the compiler plugin generating atarget/javac.argsfile. This file allows the user to test easily on the command-line, which makes debugging faster. Likewise, the options can also be passed to another tool, which makes easier to resolve #439 as well.Behavioral changes
The plugin behaviour after the proposed refactoring is different than version 3 in the following aspects:
Removal of default
**/package.htmlexcludesThe current plugin version uses an undocumented
**/package.htmldefault excludes. This default seems to exist since the initial revision in March 2004, but I saw no explanation for this oddity. This default is not mentioned in the documentation. The removal of this oddity is necessary for allowing the proposed new plugin implementation to specify only some root directories to thejartool, since the tool can traverse the directory tree itself.Automatic use of
MANIFEST.MFAfter this refactor, the plugin automatically uses the
META-INF/MANIFEST.MFfile found in theclassesdirectory. Before this refactor, the plugin used that file only if explicitly specified in the<manifestFile>archive configuration. The previous policy was discussed in #255. The new policy is a natural consequence of the way that the JAR plugin is reimplemented, and also more useful in the context of multi-module (in Java module sense) projects since each module could contain its ownMANIFEST.MFfile.Multi-module projects
The refactoral support multi-module projects, including projects that are both multi-module and multi-release, as discussed in apache/maven-compiler-plugin#998.
Dependencies
This pull request depends on a Maven release which include the following pull requests:
META-INF/versionswhen the sub-directories are multi-module maven-compiler-plugin#998