desruisseaux commented on code in PR #508:
URL: https://github.com/apache/maven-jar-plugin/pull/508#discussion_r3891866900


##########
src/main/java/org/apache/maven/plugins/jar/AbstractJarMojo.java:
##########
@@ -207,167 +205,208 @@ protected final Log getLog() {
     protected abstract String getType();
 
     /**
-     * Returns the JAR file to generate, based on an optional classifier.
+     * {@return the scope of dependencies}
+     * It should be {@link PathScope#MAIN_COMPILE} or {@link 
PathScope#TEST_COMPILE}.
+     * Note that we use compile scope rather than runtime scope because 
dependencies
+     * cannot appear in {@code requires} statement if they didn't had compile 
scope.
+     */
+    protected abstract PathScope getDependencyScope();
+
+    /**
+     * {@return the JAR tool to use for archiving the code}
      *
-     * @param basedir the output directory
-     * @param resultFinalName the name of the JAR file
-     * @param classifier an optional classifier
-     * @return the file to generate
+     * @throws MojoException if no JAR tool was found
+     *
+     * @since 4.0.0-beta-2
      */
-    protected Path getJarFile(Path basedir, String resultFinalName, String 
classifier) {
-        Objects.requireNonNull(basedir, "basedir is not allowed to be null");
-        Objects.requireNonNull(resultFinalName, "finalName is not allowed to 
be null");
-        String fileName = resultFinalName + (hasClassifier(classifier) ? '-' + 
classifier : "") + ".jar";
-        return basedir.resolve(fileName);
+    protected ToolProvider getJarTool() throws MojoException {
+        return ToolProvider.findFirst(toolId).orElseThrow(() -> new 
MojoException("No such \"" + toolId + "\" tool."));
     }
 
     /**
-     * Generates the JAR.
+     * Returns the output time stamp or, as a fallback, the {@code 
SOURCE_DATE_EPOCH} environment variable.
+     * If the time stamp is expressed in seconds, it is converted to ISO 8601 
format. Otherwise it is returned as-is.
      *
-     * @return the path to the created archive file
-     * @throws MojoException in case of an error
+     * @return the time stamp in presumed ISO 8601 format, or {@code null} if 
none
+     *
+     * @since 4.0.0-beta-2
      */
-    public Path createArchive() throws MojoException {
-        Path basedir = outputDirectory != null
-                ? outputDirectory
-                : Path.of(project.getBuild().getDirectory());
-        String resultFinalName =
-                finalName != null ? finalName : 
project.getBuild().getFinalName();
-        Path jarFile = getJarFile(basedir, resultFinalName, getClassifier());
-
-        FileSetManager fileSetManager = new FileSetManager();
-        FileSet jarContentFileSet = new FileSet();
-        
jarContentFileSet.setDirectory(getClassesDirectory().toAbsolutePath().toString());
-        jarContentFileSet.setIncludes(Arrays.asList(getIncludes()));
-        jarContentFileSet.setExcludes(Arrays.asList(getExcludes()));
-
-        String[] includedFiles = 
fileSetManager.getIncludedFiles(jarContentFileSet);
-
-        if (detectMultiReleaseJar
-                && Arrays.stream(includedFiles)
-                        .anyMatch(
-                                p -> p.startsWith("META-INF" + 
File.separatorChar + "versions" + File.separatorChar))) {
-            getLog().debug("Adding 'Multi-Release: true' manifest entry.");
-            archive.addManifestEntry(Attributes.Name.MULTI_RELEASE.toString(), 
"true");
+    protected String getOutputTimestamp() {
+        String time = nullIfAbsent(outputTimestamp);
+        if (time == null) {
+            time = nullIfAbsent(System.getenv("SOURCE_DATE_EPOCH"));
+            if (time == null) {
+                return null;
+            }
         }
+        if (Runtime.version().feature() < ToolExecutor.JDK_SUPPORT_DATE) {
+            log.warn("Reproducible build requires Java " + 
ToolExecutor.JDK_SUPPORT_DATE + " or later.");
+            return null;
+        }
+        for (int i = time.length(); --i >= 0; ) {
+            char c = time.charAt(i);
+            if ((c < '0' || c > '9') && (i != 0 || c != '-')) {
+                return time;
+            }
+        }
+        return Instant.ofEpochSecond(Long.parseLong(time)).toString();
+    }
 
-        // May give false positives if the files is named as module descriptor
-        // but is not in the root of the archive or in the versioned area
-        // (and hence not actually a module descriptor).
-        // That is fine since the modular Jar archiver will gracefully
-        // handle such case.
-        // And also such case is unlikely to happen as file ending
-        // with "module-info.class" is unlikely to be included in Jar file
-        // unless it is a module descriptor.
-        boolean containsModuleDescriptor =
-                Arrays.stream(includedFiles).anyMatch(p -> 
p.endsWith(MODULE_DESCRIPTOR_FILE_NAME));
-
-        String archiverName = containsModuleDescriptor ? "mjar" : "jar";
+    /**
+     * {@return the patterns of files to include, or an empty list if no 
include pattern was specified}
+     */
+    protected List<String> getIncludes() {
+        return asList(includes);
+    }
 
-        MavenArchiver archiver = new MavenArchiver();
-        archiver.setCreatedBy("Maven JAR Plugin", "org.apache.maven.plugins", 
"maven-jar-plugin");
-        
archiver.setBuildJdkSpecDefaultEntry(archive.getManifest().isAddBuildEnvironmentEntries());
-        archiver.setArchiver((JarArchiver) archivers.get(archiverName));
-        archiver.setOutputFile(jarFile.toFile());
+    /**
+     * {@return the patterns of files to exclude, or an empty list if no 
exclude pattern was specified}
+     */
+    protected List<String> getExcludes() {
+        return asList(excludes);
+    }
 
-        // configure for Reproducible Builds based on outputTimestamp value
-        archiver.configureReproducibleBuild(outputTimestamp);
+    /**
+     * Returns the output directory and ensures that the directory exists.
+     * The returned directory will be either {@link #outputDirectory} if 
non-null,
+     * or {@link org.apache.maven.api.model.Build#getDirectory()} otherwise.
+     *
+     * <p>The directory is usually {@code target} and should always exist 
since it is usually the output
+     * of the compiler plugin. If nevertheless the directory does not exist, 
then this method creates it.
+     * However, this method does not try to create the parent directory, which 
should be the Maven sub-project.</p>
+     *
+     * @return the directory containing the generated <abbr>JAR</abbr> files.
+     * @throws IOException if the output directory did not existed and could 
not be created
+     */
+    protected Path getOutputDirectory() throws IOException {
+        Path dir = outputDirectory;
+        if (dir == null) {
+            dir = Path.of(project.getBuild().getDirectory());
+        }
+        if (Files.notExists(dir)) {
+            dir = Files.createDirectory(dir);
+        }
+        return dir;
+    }
 
-        archive.setForced(forceCreation);
+    /**
+     * Returns the given elements as a list if non-null.
+     *
+     * @param elements the elements, or {@code null}
+     * @return the elements as a list, or {@code null} if the given array was 
null
+     */
+    private static List<String> asList(String[] elements) {
+        return (elements == null) ? List.of() : Arrays.asList(elements);
+    }
 
-        try {
-            Path contentDirectory = getClassesDirectory();
-            if (!Files.exists(contentDirectory)) {
-                if (!forceCreation) {
-                    getLog().warn("JAR will be empty - no content was marked 
for inclusion!");
-                }
-            } else {
-                archiver.getArchiver().addDirectory(contentDirectory.toFile(), 
getIncludes(), getExcludes());
+    /**
+     * Generates the <abbr>JAR</abbr> files.
+     * Map keys are module names or {@code null} if the project does not use 
module hierarchy.
+     * Values are (<var>type</var>, <var>path</var>) pairs associated with 
each module where
+     * <var>type</var> is {@code "pom"}, {@code "jar"} or {@code "test-jar"} 
and <var>path</var>
+     * is the path to the <abbr>POM</abbr> or <abbr>JAR</abbr> file.
+     *
+     * <p>Note that a null key does not necessarily means that the 
<abbr>JAR</abbr> is not modular.
+     * It only means that the project was not compiled with module hierarchy,
+     * i.e. {@code target/classes/} subdirectories having module names.

Review Comment:
   Done.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to