sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Apache SIS distribution file should not use PACK200 anymore. That format has been deprecated for removal in Java 11. This commit is part of https://issues.apache.org/jira/browse/SIS-430.
Date Sun, 04 Nov 2018 20:29:54 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new d4884c9  Apache SIS distribution file should not use PACK200 anymore. That format has been deprecated for removal in Java 11. This commit is part of https://issues.apache.org/jira/browse/SIS-430.
d4884c9 is described below

commit d4884c90123341be2fc26cb8ba568847297fae78
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sun Nov 4 21:28:58 2018 +0100

    Apache SIS distribution file should not use PACK200 anymore. That format has been deprecated for removal in Java 11.
    This commit is part of https://issues.apache.org/jira/browse/SIS-430.
---
 application/sis-console/pom.xml                    |   2 +-
 application/sis-console/src/main/artifact/README   |   6 +-
 application/sis-console/src/main/artifact/bin/sis  |  10 -
 .../org/apache/sis/internal/maven/Assembler.java   | 192 ++++++++----
 .../apache/sis/internal/maven/BundleCreator.java   | 114 -------
 .../org/apache/sis/internal/maven/Filenames.java   |  42 +--
 .../apache/sis/internal/maven/JarCollector.java    |  20 +-
 .../org/apache/sis/internal/maven/PackInput.java   | 227 --------------
 .../org/apache/sis/internal/maven/PackOutput.java  | 338 ---------------------
 .../java/org/apache/sis/internal/maven/Packer.java | 123 --------
 .../apache/sis/internal/maven/package-info.java    |  10 +-
 11 files changed, 182 insertions(+), 902 deletions(-)

diff --git a/application/sis-console/pom.xml b/application/sis-console/pom.xml
index 19fce93..71cb211 100644
--- a/application/sis-console/pom.xml
+++ b/application/sis-console/pom.xml
@@ -87,7 +87,7 @@
     </plugins>
   </build>
 
-  <!-- Create the binary distribution file, including PACK200 bundle. -->
+  <!-- Create the binary distribution file. -->
   <profiles>
     <profile>
       <id>apache-release</id>
diff --git a/application/sis-console/src/main/artifact/README b/application/sis-console/src/main/artifact/README
index 727b920..ce5f727 100644
--- a/application/sis-console/src/main/artifact/README
+++ b/application/sis-console/src/main/artifact/README
@@ -27,11 +27,7 @@ There is not yet 'sis.bat' file for Windows.
 The following steps need to be done manually:
 
 1) Unzip 'apache-sis-1.0-bin.zip' in any directory.
-2) In the 'apache-sis-1.0/lib' directory, execute:
-
-     unpack200 --remove-pack-file sis.pack.gz sis.jar
-
-3) Invoke 'java -jar lib/sis.jar' on the command line.
+2) Invoke 'java -jar lib/sis.jar' on the command line.
 
 
 Configuration (Unix only)
diff --git a/application/sis-console/src/main/artifact/bin/sis b/application/sis-console/src/main/artifact/bin/sis
index 929ceb7..ed98e33 100755
--- a/application/sis-console/src/main/artifact/bin/sis
+++ b/application/sis-console/src/main/artifact/bin/sis
@@ -20,16 +20,6 @@ BASE_DIR="`dirname $0`/.."
 SIS_DATA="${SIS_DATA:-$BASE_DIR/data}"
 export SIS_DATA
 
-# Unpack the JAR file when first needed.
-if [ ! -f $BASE_DIR/lib/sis.jar ]
-then
-  if ! unpack200 --remove-pack-file $BASE_DIR/lib/sis.pack.gz $BASE_DIR/lib/sis.jar
-  then
-    echo Can not install Apache SIS.
-    exit 1
-  fi
-fi
-
 # Execute SIS with any optional JAR that the user may put in the 'lib' directory.
 java -classpath "$BASE_DIR/lib/*" \
      -Djava.util.logging.config.file="$BASE_DIR/conf/logging.properties" \
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Assembler.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Assembler.java
index e04587b..bb5a0d0 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Assembler.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Assembler.java
@@ -20,9 +20,16 @@ import java.io.File;
 import java.io.IOException;
 import java.io.FilenameFilter;
 import java.io.FileInputStream;
-import java.io.FilterOutputStream;
-import java.util.LinkedHashMap;
+import java.io.InputStream;
 import java.util.Map;
+import java.util.Set;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Mojo;
@@ -37,20 +44,27 @@ import static org.apache.sis.internal.maven.Filenames.*;
 
 
 /**
- * Creates a ZIP files containing the content of the <code>application/sis-console/src/main/artifact</code>
- * directory together with the Pack200 file created by <code>BundleCreator</code>.
+ * Creates a ZIP file containing the Apache SIS binary distribution.
+ * The created file contains:
+ *
+ * <ul>
+ *   <li>the content of the <code>application/sis-console/src/main/artifact</code> directory;</li>
+ *   <li>the JAR files of all modules and their dependencies, without their native resources;</li>
+ *   <li>the native resources in a separated {@code lib/} directory.</li>
+ * </ul>
+ *
  * This MOJO can be invoked from the command line in the {@code sis-console} module as below:
  *
  * <blockquote><code>mvn package org.apache.sis.core:sis-build-helper:dist</code></blockquote>
  *
  * <p><b>Current limitation:</b>
  * The current implementation uses some hard-coded paths and filenames.
- * See the <cite>Distribution file and Pack200 bundle</cite> section in
+ * See the <cite>Distribution file</cite> section in
  * <a href="http://sis.apache.org/build.html">Build from source</a> page
  * for more information.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.4
  * @module
  */
@@ -93,42 +107,33 @@ public final class Assembler extends AbstractMojo implements FilenameFilter {
         if (!sourceDirectory.isDirectory()) {
             throw new MojoExecutionException("Directory not found: " + sourceDirectory);
         }
-        final File targetDirectory = new File(rootDirectory, TARGET_DIRECTORY);
-        final String version = project.getVersion();
-        final String artifactBase = FINALNAME_PREFIX + version;
-        final Map<String,byte[]> nativeFiles = new LinkedHashMap<>();
-        try {
-            final File targetFile = new File(distributionDirectory(targetDirectory), artifactBase + ".zip");
-            try (ZipArchiveOutputStream zip = new ZipArchiveOutputStream(targetFile)) {
-                zip.setLevel(9);
-                appendRecursively(sourceDirectory, artifactBase, zip, new byte[8192]);
-                /*
-                 * At this point, all the "application/sis-console/src/main/artifact" and sub-directories
-                 * have been zipped.  Now generate the Pack200 file and zip it directly (without creating
-                 * a temporary "sis.pack.gz" file).
-                 */
-                final Packer packer = new Packer(project.getName(), version, BundleCreator.files(project), targetDirectory, nativeFiles);
-                ZipArchiveEntry entry = new ZipArchiveEntry(artifactBase + '/' + LIB_DIRECTORY + '/' + FATJAR_FILE + PACK_EXTENSION);
-                entry.setMethod(ZipArchiveEntry.STORED);
+        final String artifactBase = FINALNAME_PREFIX + project.getVersion();
+        final File targetFile = distributionFile(rootDirectory, artifactBase + ".zip");
+        try (ZipArchiveOutputStream zip = new ZipArchiveOutputStream(targetFile)) {
+            zip.setLevel(9);
+            appendRecursively(sourceDirectory, artifactBase, zip);
+            /*
+             * At this point, all the "application/sis-console/src/main/artifact" and sub-directories
+             * have been zipped. Now append the JAR files for each module and their dependencies.
+             */
+            final Map<String,byte[]> nativeFiles = new LinkedHashMap<>();
+            for (final File file : files(project)) {
+                ZipArchiveEntry entry = new ZipArchiveEntry(artifactBase + '/' + LIB_DIRECTORY + '/' + file.getName());
                 zip.putArchiveEntry(entry);
-                packer.preparePack200(FATJAR_FILE + ".jar").pack(new FilterOutputStream(zip) {
-                    /** Closes the archive entry, not the ZIP file. */
-                    @Override public void close() throws IOException {
-                        zip.closeArchiveEntry();
-                    }
-                });
-                /*
-                 * At this point we finished creating all entries in the ZIP file, except native resources.
-                 * Copy them now.
-                 */
-                for (final Map.Entry<String,byte[]> nf : nativeFiles.entrySet()) {
-                    entry = new ZipArchiveEntry(artifactBase + '/' + LIB_DIRECTORY + '/' + nf.getKey());
-                    entry.setUnixMode(0555);        // Readable and executable for all, but not writable.
-                    zip.putArchiveEntry(entry);
-                    zip.write(nf.getValue());
-                    zip.closeArchiveEntry();
-                    nf.setValue(null);
-                }
+                appendJAR(file, zip, nativeFiles);
+                zip.closeArchiveEntry();
+            }
+            /*
+             * At this point we finished creating all entries in the ZIP file, except native resources.
+             * Copy them now.
+             */
+            for (final Map.Entry<String,byte[]> nf : nativeFiles.entrySet()) {
+                ZipArchiveEntry entry = new ZipArchiveEntry(artifactBase + '/' + LIB_DIRECTORY + '/' + nf.getKey());
+                entry.setUnixMode(0555);        // Readable and executable for all, but not writable.
+                zip.putArchiveEntry(entry);
+                zip.write(nf.getValue());
+                zip.closeArchiveEntry();
+                nf.setValue(null);
             }
         } catch (IOException e) {
             throw new MojoExecutionException(e.getLocalizedMessage(), e);
@@ -136,14 +141,31 @@ public final class Assembler extends AbstractMojo implements FilenameFilter {
     }
 
     /**
+     * Returns all files to include for the given Maven project.
+     */
+    private static Set<File> files(final MavenProject project) throws MojoExecutionException {
+        final Set<File> files = new LinkedHashSet<>();
+        files.add(project.getArtifact().getFile());
+        for (final Artifact dep : project.getArtifacts()) {
+            final String scope = dep.getScope();
+            if (Artifact.SCOPE_COMPILE.equalsIgnoreCase(scope) ||
+                Artifact.SCOPE_RUNTIME.equalsIgnoreCase(scope))
+            {
+                files.add(dep.getFile());
+            }
+        }
+        if (files.remove(null)) {
+            throw new MojoExecutionException("Invocation of this MOJO shall be done together with a \"package\" Maven phase.");
+        }
+        return files;
+    }
+
+    /**
      * Adds the given file in the ZIP file. If the given file is a directory, then this method
      * recursively adds all files contained in this directory. This method is invoked for zipping
-     * the "application/sis-console/src/main/artifact" directory and sub-directories before to zip
-     * the Pack200 file.
+     * the "application/sis-console/src/main/artifact" directory and sub-directories before to zip.
      */
-    private void appendRecursively(final File file, String relativeFile, final ZipArchiveOutputStream out,
-            final byte[] buffer) throws IOException
-    {
+    private void appendRecursively(final File file, String relativeFile, final ZipArchiveOutputStream out) throws IOException {
         if (file.isDirectory()) {
             relativeFile += '/';
         }
@@ -154,17 +176,13 @@ public final class Assembler extends AbstractMojo implements FilenameFilter {
         out.putArchiveEntry(entry);
         if (!entry.isDirectory()) {
             try (FileInputStream in = new FileInputStream(file)) {
-                // TODO: use InputStream.transferTo(OutputStream) with JDK9.
-                int n;
-                while ((n = in.read(buffer)) >= 0) {
-                    out.write(buffer, 0, n);
-                }
+                in.transferTo(out);
             }
         }
         out.closeArchiveEntry();
         if (entry.isDirectory()) {
             for (final String filename : file.list(this)) {
-                appendRecursively(new File(file, filename), relativeFile.concat(filename), out, buffer);
+                appendRecursively(new File(file, filename), relativeFile.concat(filename), out);
             }
         }
     }
@@ -180,4 +198,74 @@ public final class Assembler extends AbstractMojo implements FilenameFilter {
     public boolean accept(final File directory, final String filename) {
         return !filename.isEmpty() && filename.charAt(0) != '.' && !filename.equals(CONTENT_FILE);
     }
+
+    /**
+     * Returns {@code true} if the given JAR file contains at least one resource in the
+     * {@value Filenames#NATIVE_DIRECTORY} directory. Those files will need to be rewritten
+     * in order to exclude those resources.
+     */
+    private static boolean hasNativeResources(final ZipFile in) {
+        final Enumeration<? extends ZipEntry> entries = in.entries();
+        while (entries.hasMoreElements()) {
+            if (entries.nextElement().getName().startsWith(NATIVE_DIRECTORY)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Copies a JAR file in the given ZIP file, except the native resources which are stored in the given map.
+     *
+     * @param  file         the JAR file to copy.
+     * @param  bundle       destination where to copy the JAR file.
+     * @param  nativeFiles  where to store the native resources.
+     */
+    private void appendJAR(final File file, final ZipArchiveOutputStream bundle, final Map<String,byte[]> nativeFiles)
+            throws IOException
+    {
+        try (ZipFile in = new ZipFile(file)) {
+            if (hasNativeResources(in)) {
+                final ZipOutputStream out = new ZipOutputStream(bundle);
+                out.setLevel(9);
+                final Enumeration<? extends ZipEntry> entries = in.entries();
+                while (entries.hasMoreElements()) {
+                    final ZipEntry entry = entries.nextElement();
+                    final String    name = entry.getName();
+                    try (InputStream eis = in.getInputStream(entry)) {
+                        if (!name.startsWith(NATIVE_DIRECTORY)) {
+                            out.putNextEntry(new ZipEntry(name));
+                            eis.transferTo(out);                            // Copy the entry verbatim.
+                            out.closeEntry();
+                        } else if (!entry.isDirectory()) {
+                            final long size = entry.getSize();              // For memorizing the entry without copying it now.
+                            if (size <= 0 || size > Integer.MAX_VALUE) {
+                                throw new IOException(String.format("Errors while copying %s:%n"
+                                        + "Unsupported size for \"%s\" entry: %d", file, name, size));
+                            }
+                            final byte[] content = new byte[(int) size];
+                            final int actual = eis.read(content);
+                            if (actual != size) {
+                                throw new IOException(String.format("Errors while copying %s:%n"
+                                        + "Expected %d bytes in \"%s\" but found %d", file, size, name, actual));
+                            }
+                            if (nativeFiles.put(name.substring(NATIVE_DIRECTORY.length()), content) != null) {
+                                throw new IOException(String.format("Errors while copying %s:%n"
+                                        + "Duplicated entry: %s", file, name));
+                            }
+                        }
+                    }
+                }
+                out.finish();
+                return;
+            }
+        }
+        /*
+         * If the JAR file has no native resources to exclude, we can copy the JAR file verbatim.
+         * This is faster than inflating and deflating again the JAR file.
+         */
+        try (FileInputStream in = new FileInputStream(file)) {
+            in.transferTo(bundle);
+        }
+    }
 }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/BundleCreator.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/BundleCreator.java
deleted file mode 100644
index c89af37..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/BundleCreator.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.
- */
-package org.apache.sis.internal.maven;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.apache.maven.project.MavenProject;
-
-import static org.apache.sis.internal.maven.Filenames.*;
-
-
-/**
- * Merges the binaries produced by <code>JarCollector</code> and compress them using Pack200.
- * This mojo can be invoked from the command line as below:
- *
- * <blockquote><code>mvn org.apache.sis.core:sis-build-helper:pack --non-recursive</code></blockquote>
- *
- * Do not forget the <code>--non-recursive</code> option, otherwise the Mojo will be executed many time.
- *
- * <p><b>Current limitation:</b>
- * The current implementation uses some hard-coded paths and filenames.
- * See the <cite>Distribution file and Pack200 bundle</cite> section in
- * <a href="http://sis.apache.org/build.html">Build from source</a> page
- * for more information.</p>
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.3
- * @module
- */
-@Mojo(name = "pack", defaultPhase = LifecyclePhase.INSTALL, requiresDependencyResolution = ResolutionScope.COMPILE)
-public final class BundleCreator extends AbstractMojo {
-    /**
-     * Project information (name, version, URL).
-     */
-    @Parameter(property="project", required=true, readonly=true)
-    private MavenProject project;
-
-    /**
-     * The root directory (without the "<code>target/binaries</code>" sub-directory) where JARs
-     * are to be copied. It should be the directory of the root <code>pom.xml</code>.
-     */
-    @Parameter(property="session.executionRootDirectory", required=true)
-    private String rootDirectory;
-
-    /**
-     * Invoked by reflection for creating the MOJO.
-     */
-    public BundleCreator() {
-    }
-
-    /**
-     * Creates the Pack200 file from the JAR files collected in the "<code>target/binaries</code>" directory.
-     *
-     * @throws MojoExecutionException if the plugin execution failed.
-     */
-    @Override
-    public void execute() throws MojoExecutionException {
-        final File targetDirectory = new File(rootDirectory, TARGET_DIRECTORY);
-        if (!targetDirectory.isDirectory()) {
-            throw new MojoExecutionException("Directory not found: " + targetDirectory);
-        }
-        final String version = project.getVersion();
-        try {
-            final Packer packer = new Packer(project.getName(), version, files(project), targetDirectory, null);
-            packer.preparePack200(FINALNAME_PREFIX + version + ".jar").pack();
-        } catch (IOException e) {
-            throw new MojoExecutionException(e.getLocalizedMessage(), e);
-        }
-    }
-
-    /**
-     * Returns all files to include for the given Maven project.
-     */
-    static Set<File> files(final MavenProject project) throws MojoExecutionException {
-        final Set<File> files = new LinkedHashSet<>();
-        files.add(project.getArtifact().getFile());
-        for (final Artifact dep : project.getArtifacts()) {
-            final String scope = dep.getScope();
-            if (Artifact.SCOPE_COMPILE.equalsIgnoreCase(scope) ||
-                Artifact.SCOPE_RUNTIME.equalsIgnoreCase(scope))
-            {
-                files.add(dep.getFile());
-            }
-        }
-        if (files.remove(null)) {
-            throw new MojoExecutionException("Invocation of this MOJO shall be done together with a \"package\" Maven phase.");
-        }
-        return files;
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Filenames.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Filenames.java
index 6779f7c..3a68cec 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Filenames.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Filenames.java
@@ -17,18 +17,18 @@
 package org.apache.sis.internal.maven;
 
 import java.io.File;
-import java.io.IOException;
+import org.apache.maven.plugin.MojoExecutionException;
 
 
 /**
  * Hard-coded file and directory names used by this package.
  *
  * <p><b>Reminder:</b>
- * If the above constants are modified, please remind to edit the <cite>Distribution file
- * and Pack200 bundle</cite> section in the <code>src/site/apt/index.apt</code> file.</p>
+ * If the above constants are modified, please remind to edit the <cite>Distribution file</cite>
+ * section in the <code>site/content/build.mdtext</code> file.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.4
  * @module
  */
@@ -51,13 +51,19 @@ final class Filenames {
      * dependencies on platforms that do not support hard links. Also the file to ignore when copying
      * entries in a ZIP file.
      */
+    static final String OTHER_DEPENDENCIES_FILE = "other_dependencies.txt";
+
+    /**
+     * The file to ignore when copying entries in a ZIP file.
+     * Those files appear in the {@value #ARTIFACT_PATH} directory.
+     */
     static final String CONTENT_FILE = "content.txt";
 
     /**
      * The sub-directory inside {@value #TARGET_DIRECTORY} containing pack files.
      * This directory will be automatically created if it does not already exist.
      */
-    static final String DISTRIBUTION_DIRECTORY = "distribution";
+    private static final String DISTRIBUTION_DIRECTORY = "distribution";
 
     /**
      * The path to the directory (relative to the project directory) to zip for creating the distribution ZIP file.
@@ -65,17 +71,17 @@ final class Filenames {
     static final String ARTIFACT_PATH = "src/main/artifact";
 
     /**
-     * The name of the sub-directory inside {@value #ARTIFACT_PATH} where the Pack200 file will be located.
+     * The name of the sub-directory inside {@value #ARTIFACT_PATH} where the JAR files will be located.
      * Note that we will not write in the real directory, but only in the directory structure which is
      * reproduced in the ZIP file.
      */
     static final String LIB_DIRECTORY = "lib";
 
     /**
-     * The name (without extension) of the big JAR file which will contains everything.
-     * This file will be located in the {@value #LIB_DIRECTORY} directory.
+     * The prefix of native resources in JAR files. All those resources will be excluded from
+     * the JAR copied in the zip file and stored in a {@code nativeFiles} map instead.
      */
-    static final String FATJAR_FILE = "sis";
+    static final String NATIVE_DIRECTORY = "native/";
 
     /**
      * The prefix of the final filename. This is hard coded for now.
@@ -83,28 +89,24 @@ final class Filenames {
     static final String FINALNAME_PREFIX = "apache-sis-";
 
     /**
-     * The extension for Pack200 files.
-     */
-    static final String PACK_EXTENSION = ".pack.gz";
-
-    /**
      * Do not allow instantiation of this class.
      */
     private Filenames() {
     }
 
     /**
-     * Returns the distribution directory, creating it if needed.
+     * Returns the distribution file, creating its directory if needed.
      *
-     * @param  targetDirectory  the {@code target} directory.
+     * @param  rootDirectory  the project root directory.
+     * @param  filename       name of the file to create.
      */
-    static File distributionDirectory(final File targetDirectory) throws IOException {
-        final File outDirectory = new File(targetDirectory, DISTRIBUTION_DIRECTORY);
+    static File distributionFile(final String rootDirectory, final String filename) throws MojoExecutionException {
+        final File outDirectory = new File(new File(rootDirectory, TARGET_DIRECTORY), DISTRIBUTION_DIRECTORY);
         if (!outDirectory.isDirectory()) {
             if (!outDirectory.mkdir()) {
-                throw new IOException("Can't create the \"" + DISTRIBUTION_DIRECTORY + "\" directory.");
+                throw new MojoExecutionException("Can't create the \"" + DISTRIBUTION_DIRECTORY + "\" directory.");
             }
         }
-        return outDirectory;
+        return new File(outDirectory, filename);
     }
 }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/JarCollector.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/JarCollector.java
index 1e3b80f..141d0a1 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/JarCollector.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/JarCollector.java
@@ -44,10 +44,10 @@ import static org.apache.sis.internal.maven.Filenames.*;
  * Collects <code>.jar</code> files in a single "{@code target/binaries}" directory.
  * Dependencies are collected as well, except if already presents. This mojo uses hard links
  * on platforms that support them. If hard links are not supported, then this mojo will instead
- * creates a "{@code target/binaries/content.txt}" file listing the dependencies.
+ * creates a "{@code target/binaries/other_dependencies.txt}" file listing the dependencies.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -223,8 +223,8 @@ public final class JarCollector extends AbstractMojo implements FileFilter {
 
     /**
      * Creates a link from the given source file to the given target file.
-     * On JDK6 or on platform that do not support links, this method rather
-     * updates the <code>content.txt</code> file.
+     * On platforms that do not support links, this method rather updates
+     * the {@value Filenames#OTHER_DEPENDENCIES_FILE} file.
      *
      * @param  file  the source file to read.
      * @param  copy  the destination file to create.
@@ -237,17 +237,17 @@ public final class JarCollector extends AbstractMojo implements FileFilter {
             return;
         } catch (UnsupportedOperationException | FileSystemException e) {
             /*
-             * If hard links are not supported, edit the "content.txt" file instead.
+             * If hard links are not supported, edit the "other_dependencies.txt" file instead.
              * Note that a hard link may be unsupported because the source and target
              * are on different Windows drives or mount points, in which case we get
              * a FileSystemException instead than UnsupportedOperationException.
              */
         }
         /*
-         * If we can not use hard links, creates or updates a "target/content.txt" file instead.
+         * If we can not use hard links, creates or updates a "target/other_dependencies.txt" file instead.
          * This file will contains the list of all dependencies, without duplicated values.
          */
-        final File dependenciesFile = new File(copy.getParentFile(), CONTENT_FILE);
+        final File dependenciesFile = new File(copy.getParentFile(), OTHER_DEPENDENCIES_FILE);
         final Set<String> dependencies = loadDependencyList(dependenciesFile);
         if (dependencies.add(file.getPath())) {
             // Save the dependencies list only if it has been modified.
@@ -261,9 +261,9 @@ public final class JarCollector extends AbstractMojo implements FileFilter {
     }
 
     /**
-     * Loads the {@value #CONTENT_FILE} from the given directory, if it exists.
-     * Otherwise returns an empty but modifiable set. This method is invoked on
-     * platforms that do not support hard links.
+     * Loads the {@value #OTHER_DEPENDENCIES_FILE} from the given directory, if it exists.
+     * Otherwise returns an empty but modifiable set. This method is invoked on platforms
+     * that do not support hard links.
      */
     private static Set<String> loadDependencyList(final File dependenciesFile) throws IOException {
         final Set<String> dependencies = new LinkedHashSet<>();
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackInput.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackInput.java
deleted file mode 100644
index 3073038..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackInput.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * 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.
- */
-package org.apache.sis.internal.maven;
-
-import java.util.Map;
-import java.util.Enumeration;
-import java.util.jar.*;
-import java.io.File;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-
-
-/**
- * A JAR file to be used for input by {@link Packer}.
- * Those files will be open in read-only mode.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.3
- * @module
- */
-final class PackInput implements Closeable {
-    /**
-     * The {@code value} directory.
-     */
-    private static final String META_INF = "META-INF/";
-
-    /**
-     * Files from the {@code META-INF} directory to include.
-     * Every files not in this list will be excluded.
-     */
-    private static final String[] INCLUDES = {"registryFile.jai"};
-
-    /**
-     * The {@code value} directory.
-     */
-    static final String SERVICES = META_INF + "services/";
-
-    /**
-     * The prefix of native resources in JAR files. All those resources will be excluded from
-     * the PACK200 file and stored in {@link #nativeFiles} instead (unless the map is null).
-     */
-    private static final String NATIVE = "native/";
-
-    /**
-     * The attribute name in {@code MANIFEST.MF} files for splash screen.
-     */
-    static final Attributes.Name SPLASH_SCREEN = new Attributes.Name("SplashScreen-Image");
-
-    /**
-     * The JAR file.
-     */
-    private JarFile file;
-
-    /**
-     * The main class obtained from the manifest, or {@code null} if none.
-     */
-    final String mainClass;
-
-    /**
-     * The splash screen image obtained from the manifest, or {@code null} if none.
-     */
-    final String splashScreen;
-
-    /**
-     * The map where to store native files found during iteration over the JAR entries.
-     * Keys are filename without the {@value #NATIVE} prefix. Values are the actual data.
-     * If null, then no native files filtering is done.
-     */
-    private final Map<String,byte[]> nativeFiles;
-
-    /**
-     * An enumeration over the entries. We are going to iterate only once.
-     */
-    private Enumeration<JarEntry> entries;
-
-    /**
-     * The current entry under iteration.
-     */
-    private JarEntry entry;
-
-    /**
-     * Opens the given JAR file in read-only mode.
-     *
-     * @param  file        the file to open.
-     * @param  nativeFiles if non-null, where to store native files found during iteration over the JAR entries.
-     * @throws IOException if the file can't be open.
-     */
-    PackInput(final File file, final Map<String,byte[]> nativeFiles) throws IOException {
-        this.nativeFiles = nativeFiles;
-        this.file = new JarFile(file);
-        final Manifest manifest = this.file.getManifest();
-        if (manifest != null) {
-            final Attributes attributes = manifest.getMainAttributes();
-            if (attributes != null) {
-                mainClass    = attributes.getValue(Attributes.Name.MAIN_CLASS);
-                splashScreen = attributes.getValue(SPLASH_SCREEN);
-                return;
-            }
-        }
-        mainClass    = null;
-        splashScreen = null;
-    }
-
-    /**
-     * Returns the entries in the input JAR file.
-     *
-     * @return the next entry, or {@code null} if the iteration is finished.
-     */
-    JarEntry nextEntry() throws IOException {
-        if (entries == null) {
-            entries = file.entries();
-        }
-        while (entries.hasMoreElements()) {
-            entry = entries.nextElement();
-            final String name = entry.getName();
-            if (name.startsWith(META_INF) && !name.startsWith(SERVICES)) {
-                if (!include(name.substring(META_INF.length()))) {
-                    continue;
-                }
-            }
-            if (nativeFiles != null && name.startsWith(NATIVE)) {
-                if (!entry.isDirectory()) {
-                    if (nativeFiles.put(name.substring(NATIVE.length()), load()) != null) {
-                        throw new IOException("Duplicated entry: " + name);
-                    }
-                }
-                continue;
-            }
-            entry.setMethod(JarEntry.DEFLATED);
-            entry.setCompressedSize(-1);                    // Change in method has changed the compression size.
-            return entry;
-        }
-        return entry = null;
-    }
-
-    /**
-     * Returns {@code true} if the given name is part of the {@link #INCLUDES} list.
-     */
-    private static boolean include(final String name) {
-        for (final String include : INCLUDES) {
-            if (name.equals(include)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Loads in memory the content of current JAR entry.
-     * This method should be invoked only for entries of reasonable size.
-     */
-    private byte[] load() throws IOException {
-        final long size = entry.getSize();
-        if (size <= 0 || size > Integer.MAX_VALUE) {
-            throw new IOException("Unsupported size for \"" + entry.getName() + "\": " + size);
-        }
-        final byte[] content = new byte[(int) size];
-        final int actual;
-        try (InputStream in = getInputStream()) {
-            actual = in.read(content);
-        }
-        if (actual != size) {
-            throw new IOException("Expected " + size + " bytes in \"" + entry.getName() + "\" but found " + actual);
-        }
-        return content;
-    }
-
-    /**
-     * Returns the input stream for the current entry.
-     *
-     * @param entry The entry for which to get an input stream.
-     */
-    InputStream getInputStream() throws IOException {
-        return file.getInputStream(entry);
-    }
-
-    /**
-     * Returns the input stream for the entry of the given name. This method must be invoked
-     * before the first call to {@link #nextEntry}. Each entry can be requested only once.
-     *
-     * @param  name  the name of the entry
-     * @return the input stream for the requested entry, or {@code null} if none.
-     * @throws IOException if the entry can not be read.
-     * @throws IllegalStateException Programming error (pre-condition violated).
-     */
-    InputStream getInputStream(final String name) throws IOException {
-        if (entries != null) {
-            throw new IllegalStateException("Too late for this method.");
-        }
-        final JarEntry candidate = file.getJarEntry(name);
-        if (candidate == null) {
-            return null;
-        }
-        return file.getInputStream(candidate);
-    }
-
-    /**
-     * Closes this input.
-     *
-     * @throws IOException if an error occurred while closing the file.
-     */
-    @Override
-    public void close() throws IOException {
-        if (file != null) {
-            file.close();
-        }
-        file    = null;
-        entry   = null;
-        entries = null;
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackOutput.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackOutput.java
deleted file mode 100644
index 6043a98..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/PackOutput.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * 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.
- */
-package org.apache.sis.internal.maven;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Enumeration;
-import java.util.jar.*;
-import java.io.File;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.FileOutputStream;
-import java.util.zip.GZIPOutputStream;
-
-import static java.util.jar.Pack200.Packer.*;
-import static org.apache.sis.internal.maven.Filenames.*;
-
-
-/**
- * A JAR file to be created for output by {@link Packer}.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
- * @since   0.3
- * @module
- */
-final class PackOutput implements Closeable {
-    /**
-     * The extension of class files in a JAR file.
-     */
-    private static final String CLASS = ".class";
-
-    /**
-     * The output file path.
-     */
-    private final File outputJAR;
-
-    /**
-     * The stream where to write the JAR.
-     * Created only when {@link #open(File)} is invoked.
-     */
-    private JarOutputStream outputStream;
-
-    /**
-     * The manifest attribute value, or {@code null} if none. We will set this field to the
-     * value of the last {@link PackInput} to be used by this {@code PackOutput}. This is on
-     * the assumption that the last input is the main one.
-     */
-    private String mainClass, splashScreen;
-
-    /**
-     * The JAR to be used as inputs. The elements in this map will be removed by the
-     * {@link #write()} method as we are done copying the content of JAR files.
-     */
-    private final Map<File,PackInput> inputJARs;
-
-    /**
-     * The entries which were already written in the output JAR file.
-     * There is two kind of entries which need this check:
-     *
-     * <ul>
-     *   <li>Directories, which may be duplicated in different JAR files.</li>
-     *   <li>{@code META-INF/services} files which were merged in a single file.</li>
-     * </ul>
-     *
-     * @see #isMergeAllowed(String)
-     */
-    private final Set<String> entriesDone = new HashSet<>();
-
-    /**
-     * Returns {@code true} if entries of the given name are allowed to be concatenated
-     * when they appear in more than one input JAR files.
-     *
-     * @see #entriesDone
-     */
-    private static boolean isMergeAllowed(final String name) {
-        return name.startsWith(PackInput.SERVICES);
-    }
-
-    /**
-     * Creates an output jar.
-     *
-     * @param  inputJARs  the input JAR filenames together with their {@code PackInput} helpers.
-     * @param  outputJAR  the output JAR filename.
-     */
-    PackOutput(final Map<File,PackInput> inputJARs, final File outputJAR) {
-        this.inputJARs = inputJARs;
-        this.outputJAR = outputJAR;
-        for (final PackInput in : inputJARs.values()) {
-            if (in.mainClass != null) {
-                mainClass = in.mainClass;
-            }
-            if (in.splashScreen != null) {
-                splashScreen = in.splashScreen;
-            }
-        }
-    }
-
-    /**
-     * Opens the given JAR file for writing and creates its manifest.
-     *
-     * @param  projectName  the project name, or {@code null} if none.
-     * @param  version      the project version, or {@code null} if none.
-     * @throws IOException if the file can't be open.
-     */
-    void open(final String projectName, final String version) throws IOException {
-        final Manifest manifest = new Manifest();
-        Attributes attributes = manifest.getMainAttributes();
-        attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
-        if (projectName != null) {
-            attributes.put(Attributes.Name.SPECIFICATION_TITLE,    projectName);
-            attributes.put(Attributes.Name.SPECIFICATION_VENDOR,   projectName);
-            attributes.put(Attributes.Name.IMPLEMENTATION_TITLE,   projectName);
-            attributes.put(Attributes.Name.IMPLEMENTATION_VENDOR,  projectName);
-        }
-        if (version != null) {
-            attributes.put(Attributes.Name.SPECIFICATION_VERSION,  version);
-            attributes.put(Attributes.Name.IMPLEMENTATION_VERSION, version);
-        }
-        if (mainClass != null) {
-            attributes.put(Attributes.Name.MAIN_CLASS, mainClass);
-        }
-        if (splashScreen != null) {
-            attributes.put(PackInput.SPLASH_SCREEN, splashScreen);
-        }
-        /*
-         * Add the package-level manifest of every dependencies.
-         */
-        for (final File input : inputJARs.keySet()) {
-            if (!input.getName().startsWith("sis-")) {
-                String packageName = null;
-                try (JarFile jar = new JarFile(input, false)) {
-                    final Enumeration<JarEntry> entries = jar.entries();
-                    while (entries.hasMoreElements()) {
-                        final JarEntry entry = entries.nextElement();
-                        final String classname = entry.getName();
-                        if (classname.endsWith(CLASS)) {
-                            int length = classname.length() - CLASS.length();
-                            if (packageName == null) {
-                                packageName = classname.substring(0, length);
-                            } else {
-                                length = Math.min(packageName.length(), length);
-                                int i; for (i=0; i<length; i++) {
-                                    if (packageName.charAt(i) != classname.charAt(i)) {
-                                        break;
-                                    }
-                                }
-                                i = packageName.lastIndexOf('/', i) + 1;
-                                packageName = packageName.substring(0, i);
-                            }
-                        }
-                    }
-                    if (packageName != null && packageName.length() != 0) {
-                        packageName = packageName.substring(0, packageName.length()-1).replace('/', '.');
-                        final Attributes src = jar.getManifest().getMainAttributes();
-                        attributes = new Attributes();
-                        if (copy(src, attributes, Attributes.Name.SPECIFICATION_TITLE)    |
-                            copy(src, attributes, Attributes.Name.SPECIFICATION_VENDOR)   |
-                            copy(src, attributes, Attributes.Name.SPECIFICATION_VERSION)  |
-                            copy(src, attributes, Attributes.Name.IMPLEMENTATION_TITLE)   |
-                            copy(src, attributes, Attributes.Name.IMPLEMENTATION_VENDOR)  |
-                            copy(src, attributes, Attributes.Name.IMPLEMENTATION_VERSION))
-                        {
-                            manifest.getEntries().put(packageName, attributes);
-                        }
-                    }
-                }
-            }
-        }
-        /*
-         * Open the output stream for the big JAR file.
-         */
-        outputStream = new JarOutputStream(new FileOutputStream(outputJAR), manifest);
-        outputStream.setLevel(1); // Use a cheap compression level since this JAR file is temporary.
-    }
-
-    /**
-     * Copies the value of the given attribute from a source {@code Attributes} to a target
-     * {@code Attributes} object. This is used for copying the package-level attributes.
-     *
-     * @return {@code true} if the attribute has been copied.
-     */
-    private static boolean copy(final Attributes src, final Attributes dst, final Attributes.Name name) {
-        String value = (String) src.get(name);
-        if (value != null && ((value = value.trim()).length()) != 0) {
-            dst.put(name, value);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Iterates through the individual jars and merge them in single, bigger JAR file.
-     * This method closes the input JAR files as they are done.
-     */
-    final void writeContent() throws IOException {
-        final byte[] buffer = new byte[64 * 1024];
-        for (final Iterator<Map.Entry<File,PackInput>> it = inputJARs.entrySet().iterator(); it.hasNext();) {
-            final Map.Entry<File,PackInput> inputJAR = it.next();
-            it.remove();                                  // Needs to be removed before the inner loop below.
-            try (PackInput input = inputJAR.getValue()) {
-                for (JarEntry entry; (entry = input.nextEntry()) != null;) {
-                    final String name = entry.getName();
-                    boolean isMergeAllowed = false;
-                    if (entry.isDirectory() || (isMergeAllowed = isMergeAllowed(name))) {
-                        if (!entriesDone.add(name)) {
-                            continue;
-                        }
-                    }
-                    outputStream.putNextEntry(entry);
-                    copy(input.getInputStream(), buffer);
-                    /*
-                     * From that points, the entry has been copied to the target JAR. Now look in
-                     * following input JARs to see if there is some META-INF/services files to merge.
-                     */
-                    if (isMergeAllowed) {
-                        for (final Map.Entry<File,PackInput> continuing : inputJARs.entrySet()) {
-                            final InputStream in = continuing.getValue().getInputStream(name);
-                            if (in != null) {
-                                copy(in, buffer);
-                            }
-                        }
-                    }
-                    outputStream.closeEntry();
-                }
-            }
-        }
-    }
-
-    /**
-     * Copies fully the given input stream to the given destination.
-     * The given input stream is closed after the copy.
-     *
-     * @param  in      the input stream from which to get the the content to copy.
-     * @param  buffer  temporary buffer to reuse at each method call.
-     * @throws IOException if an error occurred during the copy.
-     */
-    private void copy(final InputStream in, final byte[] buffer) throws IOException {
-        int n;
-        while ((n = in.read(buffer)) >= 0) {
-            outputStream.write(buffer, 0, n);
-        }
-        in.close();
-    }
-
-    /**
-     * Closes this output.
-     *
-     * @throws IOException if an error occurred while closing the file.
-     */
-    @Override
-    public void close() throws IOException {
-        for (final PackInput input : inputJARs.values()) {
-            /*
-             * The code in this loop is never executed in normal execution, since the map shall be empty after
-             * successful completion of 'writeContent()'. However the map may be non-empty if the above method
-             * threw an exception, in which case this 'close()' method will be invoked in a 'finally' block.
-             */
-            input.close();
-        }
-        inputJARs.clear();
-        if (outputStream != null) {
-            outputStream.close();
-        }
-        outputStream = null;
-    }
-
-    /**
-     * Creates a Pack200 file from the output JAR, then delete the JAR.
-     *
-     * @throws IOException if an error occurred while packing the JAR.
-     */
-    void pack() throws IOException {
-        if (outputStream != null) {
-            throw new IllegalStateException("JAR output stream not closed.");
-        }
-        final File inputFile = outputJAR;
-        String filename = inputFile.getName();
-        final int ext = filename.lastIndexOf('.');
-        if (ext > 0) {
-            filename = filename.substring(0, ext);
-        }
-        filename += PACK_EXTENSION;
-        final File outputFile = new File(inputFile.getParent(), filename);
-        if (outputFile.equals(inputFile)) {
-            throw new IOException("Input file is already packed: " + inputFile);
-        }
-        pack(new FileOutputStream(outputFile));
-    }
-
-    /**
-     * Creates a Pack200 file from the output JAR, then delete the JAR.
-     *
-     * @param  out  where to write the Pack200. This stream will be closed by this method.
-     * @throws IOException if an error occurred while packing the JAR.
-     */
-    void pack(final OutputStream out) throws IOException {
-        if (outputStream != null) {
-            throw new IllegalStateException("JAR output stream not closed.");
-        }
-        final File inputFile = outputJAR;
-        final Pack200.Packer packer = Pack200.newPacker();
-        final Map<String,String> p = packer.properties();
-        p.put(EFFORT, String.valueOf(9));           // Maximum compression level.
-        p.put(SEGMENT_LIMIT,     "-1");             // use largest-possible archive segments (>10% better compression).
-        p.put(KEEP_FILE_ORDER,    FALSE);           // Reorder files for better compression.
-        p.put(MODIFICATION_TIME,  LATEST);          // Smear modification times to a single value.
-        p.put(DEFLATE_HINT,       TRUE);            // Ignore all JAR deflation requests.
-        p.put(UNKNOWN_ATTRIBUTE,  ERROR);           // Throw an error if an attribute is unrecognized
-        p.put(CODE_ATTRIBUTE_PFX+"LocalVariableTable", STRIP);        // discard debug attributes.
-        try (JarFile jarFile = new JarFile(inputFile)) {
-            try (OutputStream deflater = new GZIPOutputStream(out)) {
-                packer.pack(jarFile, deflater);
-            }
-        }
-        if (!inputFile.delete()) {
-            throw new IOException("Can't delete temporary file: " + inputFile);
-        }
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Packer.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Packer.java
deleted file mode 100644
index a8288f3..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/Packer.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.
- */
-package org.apache.sis.internal.maven;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.LinkedHashMap;
-import java.io.File;
-import java.io.IOException;
-
-import static org.apache.sis.internal.maven.Filenames.*;
-
-
-/**
- * Creates a PACK200 files from the JAR in the {@code target/binaries} directory.
- * This tools needs the JAR files to be either copied or linked in the {@code target/binaries} directory,
- * or listed in the {@code target/binaries/content.txt} file.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.3
- * @module
- */
-final class Packer {
-    /**
-     * The project name and version to declare in the manifest file, or {@code null} if none.
-     */
-    private final String projectName, version;
-
-    /**
-     * JAR files of the main project together with its dependencies.
-     */
-    private final Set<File> files;
-
-    /**
-     * The Maven target directory. Shall contain the {@code "binaries"} sub-directory,
-     * which shall contain all JAR files collected by {@code sis-build-helper} plugin.
-     */
-    private final File targetDirectory;
-
-    /**
-     * The map where to store native files found during iteration over the JAR entries.
-     * Keys are filename without the {@value #NATIVE} prefix. Values are the actual data.
-     * If null, then no native files filtering is done.
-     */
-    private final Map<String,byte[]> nativeFiles;
-
-    /**
-     * Creates a packer.
-     *
-     * @param  projectName      the project name to declare in the manifest file, or {@code null} if none.
-     * @param  version          the project version to declare in the manifest file, or {@code null} if none.
-     * @param  files            the JAR files of the main project together with its dependencies.
-     * @param  targetDirectory  the Maven target directory.
-     * @param  nativeFiles      if non-null, where to store native files found during iteration over the JAR entries.
-     */
-    Packer(final String projectName, final String version, final Set<File> files, final File targetDirectory,
-            final Map<String,byte[]> nativeFiles)
-    {
-        this.projectName     = projectName;
-        this.version         = version;
-        this.files           = files;
-        this.targetDirectory = targetDirectory;
-        this.nativeFiles     = nativeFiles;
-    }
-
-    /**
-     * Returns the list of input JAR files, together with a helper class for copying the data in the Pack200 file.
-     * All input JAR files are opened by this method. They will need to be closed by {@link PackInput#close()}.
-     */
-    private Map<File,PackInput> getInputJARs() throws IOException {
-        final Map<File,PackInput> inputJARs = new LinkedHashMap<>(files.size() * 4/3);
-        for (final File file : files) {
-            if (!file.isFile() || !file.canRead()) {
-                throw new IllegalArgumentException("Not a file or can not read: " + file);
-            }
-            if (inputJARs.put(file, new PackInput(file, nativeFiles)) != null) {
-                throw new IllegalArgumentException("Duplicated JAR: " + file);
-            }
-        }
-        return inputJARs;
-    }
-
-    /**
-     * Prepares the Pack 200 file which will contain every JAR files in the {@code target/binaries} directory.
-     * The given {@code outputJAR} name is the name of the JAR file to create before to be packed.
-     * This filename shall end with the "{@code .jar}" suffix.
-     *
-     * <p>Callers needs to invoke one of the {@code PackOutput.pack(…)} methods on the returned object.</p>
-     *
-     * @param  outputJAR  the name of the JAR file to create before the Pack200 creation.
-     * @throws IOException if an error occurred while collecting the target directory content.
-     */
-    PackOutput preparePack200(final String outputJAR) throws IOException {
-        /*
-         * Creates the output directory. We do that first in order to avoid the
-         * costly opening of all JAR files if we can't create this directory.
-         */
-        final File outDirectory = distributionDirectory(targetDirectory);
-        final PackOutput output = new PackOutput(getInputJARs(), new File(outDirectory, outputJAR));
-        try {
-            output.open(projectName, version);
-            output.writeContent();
-        } finally {
-            output.close();
-        }
-        return output;
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/package-info.java b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/package-info.java
index 89d48e5..8c5af5a 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/package-info.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/maven/package-info.java
@@ -18,10 +18,16 @@
 
 /**
  * Maven plugins (others than {@link org.apache.sis.util.resources.ResourceCompilerMojo}) used
- * for building Apache SIS. See the Maven-generated module description for more information.
+ * for building Apache SIS.
+ *
+ * <ul>
+ *   <li>{@link org.apache.sis.internal.maven.JarCollector} collects all JAR files and their dependencies
+ *     in a single {@code target/binaries} directory, using hard links instead than copying the files.</li>
+ *   <li>{@link org.apache.sis.internal.maven.Assembler} builds the Apache SIS distribution file.</li>
+ * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.3
  * @module
  */


Mime
View raw message