sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 02/02: Remove usage of PACK200 in OpenOffice add-in (https://issues.apache.org/jira/browse/SIS-430).
Date Sat, 10 Nov 2018 16:19:57 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

commit c52bfcf31af776de27a2193c68e413e8ab92ceb8
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat Nov 10 17:19:16 2018 +0100

    Remove usage of PACK200 in OpenOffice add-in (https://issues.apache.org/jira/browse/SIS-430).
---
 application/pom.xml                                |  12 +-
 application/sis-openoffice/pom.xml                 |   6 +-
 .../org/apache/sis/openoffice/Registration.java    | 130 +-------------
 .../sis-openoffice/src/main/unopkg/description.xml |   2 +-
 .../sis/internal/unopkg/FilteredJarFile.java       | 120 -------------
 .../org/apache/sis/internal/unopkg/JavaMaker.java  |  89 ++++++---
 .../org/apache/sis/internal/unopkg/UnoPkg.java     | 198 ++++++++++-----------
 .../apache/sis/internal/unopkg/package-info.java   |   9 +-
 8 files changed, 178 insertions(+), 388 deletions(-)

diff --git a/application/pom.xml b/application/pom.xml
index 1862415..9c9b7e0 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -118,16 +118,6 @@
     <module>sis-console</module>
     <module>sis-javafx</module>
     <module>sis-webapp</module>
+    <module>sis-openoffice</module>
   </modules>
-
-  <!-- Following module is omitted for now (unless doing a release)
-       because of the numerous warnings emitted by Pack200. -->
-  <profiles>
-    <profile>
-      <id>apache-release</id>
-      <modules>
-        <module>sis-openoffice</module>
-      </modules>
-    </profile>
-  </profiles>
 </project>
diff --git a/application/sis-openoffice/pom.xml b/application/sis-openoffice/pom.xml
index 35dd9b1..d70338f 100644
--- a/application/sis-openoffice/pom.xml
+++ b/application/sis-openoffice/pom.xml
@@ -149,6 +149,11 @@
             </exclusion>
           </exclusions>
         </dependency>
+        <dependency>
+          <groupId>org.apache.derby</groupId>
+          <artifactId>derby</artifactId>
+          <scope>runtime</scope>
+        </dependency>
       </dependencies>
     </profile>
   </profiles>
@@ -181,7 +186,6 @@
         <version>${project.version}</version>
         <configuration>
           <oxtName>apache-sis-${project.version}</oxtName>
-          <pack200>true</pack200>
         </configuration>
         <executions>
           <execution>
diff --git a/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Registration.java
b/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Registration.java
index 24173c0..760b3e0 100644
--- a/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Registration.java
+++ b/application/sis-openoffice/src/main/java/org/apache/sis/openoffice/Registration.java
@@ -16,20 +16,11 @@
  */
 package org.apache.sis.openoffice;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.FilenameFilter;
-import java.io.FileOutputStream;
-import java.net.URI;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.net.URISyntaxException;
-import java.util.jar.Pack200;
-import java.util.jar.JarOutputStream;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
-import java.lang.reflect.InvocationTargetException;
 
 import com.sun.star.lang.XSingleComponentFactory;
 import com.sun.star.lib.uno.helper.Factory;
@@ -39,124 +30,24 @@ import com.sun.star.registry.XRegistryKey;
 /**
  * The registration of all formulas provided in this package.
  *
- * <div class="section">Implementation note</div>
- * No GeoAPI or Apache SIS classes should appear in method signature. For example no method
- * should contain {@link org.opengis.util.FactoryException} in their {@code throws} declaration.
- * This is because those classes can be loaded only after the Pack200 files have been unpacked,
- * which is the work of this {@code Registration} class.
- *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */
-public final class Registration implements FilenameFilter {
-    /**
-     * Filename extension of Pack200 files.
-     */
-    private static final String PACK = "pack";
-
+public final class Registration {
     /**
      * Name of the logger to use for the add-ins.
      */
     static final String LOGGER = "org.apache.sis.openoffice";
 
     /**
-     * Whether to force EPSG database startup early, for example in order to force database
creation from SQL scripts.
-     * The SQL scripts may be used if this module depends on {@code sis-epsg} module, or
if {@code SIS_DATA} directory
-     * contains a {@code "Databases/ExternalSources"} sub-directory. When such database creation
is necessary, it may
-     * be less surprising for users to perform this lengthy task at add-in installation time
instead than when the
-     * formulas are first used. However if the add-in depend on {@code sis-embedded-data}
instead, then early startup
-     * is less useful since there is no database to create.
-     *
-     * @deprecated See <a href="https://issues.apache.org/jira/browse/SIS-430">SIS-430</a>
-     */
-    private static final boolean FORCE_EPSG_STARTUP = false;
-
-    /**
-     * Do not allow instantiation of this class, except for internal use.
+     * Do not allow instantiation of this class.
      */
     private Registration() {
     }
 
     /**
-     * Returns the directory where the add-in is installed.
-     *
-     * @return the installation directory.
-     * @throws URISyntaxException if the path to the add-in JAR file does not have the expected
syntax.
-     */
-    private static File getInstallDirectory() throws URISyntaxException {
-        String path = Registration.class.getResource("Registration.class").toExternalForm();
-        int numParents = 5;                     // Number of calls to File.getParentFile()
needed for reaching the root.
-        if (path.startsWith("jar:")) {
-            path = path.substring(4, path.indexOf('!'));
-            numParents = 1;                     // The file should be the sis-openoffice.jar
file in the root.
-        }
-        File file = new File(new URI(path));
-        while (--numParents >= 0) {
-            file = file.getParentFile();
-        }
-        return file;
-    }
-
-    /**
-     * Ensures that the {@code sis.pack} files have been uncompressed.
-     *
-     * @param  caller the public caller method, for logging purpose only.
-     * @return {@code true} on success.
-     */
-    private static boolean ensureInstalled(final String caller) {
-        final File directory;
-        try {
-            directory = getInstallDirectory();
-        } catch (URISyntaxException e) {
-            fatalException(caller, "Can not locate the installation directory.", e);
-            return false;
-        }
-        final String[] content = directory.list(new Registration());
-        if (content == null) {
-            fatalException(caller, "Directory " + directory + " not found.", null);
-            return false;
-        }
-        if (content.length != 0) try {
-            final Pack200.Unpacker unpacker = Pack200.newUnpacker();
-            for (final String filename : content) {
-                final File packFile = new File(directory, filename);
-                final File jarFile  = new File(directory, filename.substring(0, filename.length()
- PACK.length()) + "jar");
-                try (JarOutputStream out = new JarOutputStream(new FileOutputStream(jarFile)))
{
-                    unpacker.unpack(packFile, out);
-                }
-                packFile.delete();
-            }
-        } catch (IOException e) {
-            fatalException(caller, "Can not uncompress the JAR files.", e);
-            return false;
-        }
-        /*
-         * Ensures that the EPSG database is installed. We force the EPSG installation at
add-in
-         * installation time rather than the first time a user ask for a referencing operations,
-         * because users may be less surprised by a delay at installation time than at use
time.
-         * However if the EPSG database is deleted after the installation, it will be recreated
-         * when first needed.
-         *
-         * Note: do not reach this code before all Pack200 files have been unpacked.
-         * Remainder: no GeoAPI or Apache SIS classes in any method signature of this class!
-         */
-        if (FORCE_EPSG_STARTUP) try {
-            Class.forName("org.apache.sis.referencing.CRS")
-                 .getMethod("forCode", String.class)
-                 .invoke(null, "EPSG:4326");
-        } catch (InvocationTargetException e) {
-            fatalException(caller, "Failed to install EPSG geodetic dataset.", e.getTargetException());
-            return false;
-        } catch (ReflectiveOperationException | LinkageError e) {
-            classpathException(caller, e);
-            return false;
-        }
-        return true;
-    }
-
-    /**
      * Logs the given exception before to abort installation. We use logging service instead
than
      * propagating the exception because OpenOffice does not report the exception message.
      */
@@ -187,17 +78,6 @@ public final class Registration implements FilenameFilter {
     }
 
     /**
-     * Filters a directory content in order to retain only the {@code "*.pack"} files.
-     *
-     * @param directory  the add-in installation directory.
-     * @param name       the name of a file in the given directory.
-     */
-    @Override
-    public boolean accept(final File directory, final String name) {
-        return name.endsWith('.' + PACK);
-    }
-
-    /**
      * Returns a factory for creating the service.
      * This method is called by the {@code com.sun.star.comp.loader.JavaLoader}; do not rename!
      *
@@ -206,7 +86,7 @@ public final class Registration implements FilenameFilter {
      */
     public static XSingleComponentFactory __getComponentFactory(final String implementation)
{
         if (implementation.equals(ReferencingFunctions.IMPLEMENTATION_NAME)) {
-            if (ensureInstalled("__getComponentFactory")) try {
+            try {
                 return Factory.createComponentFactory(ReferencingFunctions.class,
                         new String[] {ReferencingFunctions.SERVICE_NAME});
             } catch (LinkageError e) {
@@ -225,7 +105,7 @@ public final class Registration implements FilenameFilter {
      * @return {@code true} if the operation succeeded.
      */
     public static boolean __writeRegistryServiceInfo(final XRegistryKey registry) {
-        if (ensureInstalled("__writeRegistryServiceInfo")) try {
+        try {
             return Factory.writeRegistryServiceInfo(ReferencingFunctions.IMPLEMENTATION_NAME,
                     new String[] {ReferencingFunctions.SERVICE_NAME}, registry);
         } catch (LinkageError e) {
diff --git a/application/sis-openoffice/src/main/unopkg/description.xml b/application/sis-openoffice/src/main/unopkg/description.xml
index 5d61053..3a1dfc4 100644
--- a/application/sis-openoffice/src/main/unopkg/description.xml
+++ b/application/sis-openoffice/src/main/unopkg/description.xml
@@ -24,7 +24,7 @@
        xmlns:xlink="http://www.w3.org/1999/xlink">
 
   <identifier value="org.apache.sis.openoffice"/>
-  <version    value="0.8"/>
+  <version    value="${project.version}"/>
   <platform   value="all"/>
 
   <publisher>
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/FilteredJarFile.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/FilteredJarFile.java
deleted file mode 100644
index b62faa7..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/FilteredJarFile.java
+++ /dev/null
@@ -1,120 +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.unopkg;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.jar.JarFile;
-import java.util.jar.JarEntry;
-import java.util.zip.ZipEntry;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-
-
-/**
- * A JAR file which can exclude some file entries and some attributes from the {@code MANIFEST.MF}
file.
- * The main purpose of this class is to exclude the signature from JAR files before to compress
them
- * using the {@code pack200} tools, because {@code pack200} modifies the binary stream, thus
making
- * the signature invalid. If we don't remove the signature, attempts to use the JAR file
may result
- * in {@literal "SHA1 digest error for <JAR file>"} error messages.
- *
- * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
- * @since   0.8
- * @module
- */
-final class FilteredJarFile extends JarFile {
-    /**
-     * The manifest encoding in JAR files.
-     */
-    private static final String MANIFEST_ENCODING = "UTF-8";
-
-    /**
-     * Open the file specified by the given name.
-     */
-    FilteredJarFile(final File filename) throws IOException {
-        super(filename);
-    }
-
-    /**
-     * Returns the list of entries, excluding Maven files (which are of no interest for the
add-in)
-     * and the signature.
-     */
-    @Override
-    public Enumeration<JarEntry> entries() {
-        final List<JarEntry> entries = Collections.list(super.entries());
-        for (final Iterator<JarEntry> it=entries.iterator(); it.hasNext();) {
-            final String name = it.next().getName();
-            if (name.startsWith("META-INF/")) {
-                if (name.startsWith("META-INF/maven/") || name.endsWith(".SF") || name.endsWith(".RSA"))
{
-                    it.remove();
-                }
-            }
-        }
-        return Collections.enumeration(entries);
-    }
-
-    /**
-     * Returns the input stream for the given entry. If the given entry is the manifest,
-     * then this method will filter the manifest content in order to exclude the signature.
-     */
-    @Override
-    public InputStream getInputStream(final ZipEntry ze) throws IOException {
-        final InputStream in = super.getInputStream(ze);
-        if (!ze.getName().equals(JarFile.MANIFEST_NAME)) {
-            return in;
-        }
-        final List<String> lines = new ArrayList<>();
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, MANIFEST_ENCODING)))
{
-            String line;
-            while ((line = reader.readLine()) != null) {
-                if (line.trim().startsWith("SHA1-Digest:")) {
-                    final int n = lines.size();
-                    if (n == 0 || !lines.get(n-1).trim().startsWith("Name:")) {
-                        throw new IOException("Can not process the following line from "
+
-                                JarFile.MANIFEST_NAME + ":\n" + line);
-                    }
-                    lines.remove(n-1);
-                    continue;
-                }
-                lines.add(line);
-            }
-        }
-        /*
-         * 'in' has been closed at this point (indirectly, by closing the reader).
-         * Now remove trailing empty lines, and returns the new MANIFEST.MF content.
-         */
-        for (int i=lines.size(); --i>=0;) {
-            if (!lines.get(i).trim().isEmpty()) {
-                break;
-            }
-            lines.remove(i);
-        }
-        final StringBuilder buffer = new StringBuilder(lines.size() * 60);
-        for (final String line : lines) {
-            buffer.append(line).append('\n');
-        }
-        return new ByteArrayInputStream(buffer.toString().getBytes(MANIFEST_ENCODING));
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
index 89926aa..df72dea 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/JavaMaker.java
@@ -16,15 +16,20 @@
  */
 package org.apache.sis.internal.unopkg;
 
-import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+import java.nio.file.FileVisitResult;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
 
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.codehaus.plexus.util.FileUtils;
 
 
 /**
@@ -39,7 +44,7 @@ import org.codehaus.plexus.util.FileUtils;
  * by {@code javac}), which is why the usual Maven resources mechanism doesn't fit.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */
@@ -70,38 +75,76 @@ public final class JavaMaker extends AbstractMojo {
      */
     @Override
     public void execute() throws MojoExecutionException {
-        final int n;
+        final Copier c = new Copier(baseDirectory, outputDirectory);
         try {
-            n = copyClasses(new File(baseDirectory, UnoPkg.SOURCE_DIRECTORY), new File(outputDirectory));
+            c.run();
         } catch (IOException e) {
             throw new MojoExecutionException("Failed to copy *.class files.", e);
         }
-        getLog().info("[geotk-unopkg] Copied " + n + " pre-compiled class files.");
+        getLog().info("[geotk-unopkg] Copied " + c.count + " pre-compiled class files.");
     }
 
     /**
      * Copies {@code *.class} files from source directory to output directory.
-     * The output directory shall already exists. It should be the case if all
+     * The output directory should already exist. It should be the case if all
      * sources files have been compiled before this method is invoked.
-     *
-     * @return the number of files copied.
      */
-    private static int copyClasses(final File sourceDirectory,
-                                   final File outputDirectory) throws IOException
-    {
-        int n = 0;
-        final String[] filenames = sourceDirectory.list();
-        for (final String filename : filenames) {
-            final File file = new File(sourceDirectory, filename);
-            if (file.isFile()) {
-                if (filename.endsWith(".class") || filename.endsWith(".CLASS")) {
-                    FileUtils.copyFileToDirectory(file, outputDirectory);
-                    n++;
+    private static final class Copier extends SimpleFileVisitor<Path> {
+        /**
+         * The root of source and target directories. Files below {@code source} will be
copied
+         * with identical path (relative to {@code source}) under {@code target} directory.
+         */
+        private final Path source, target;
+
+        /**
+         * Number of files copied.
+         */
+        int count;
+
+        /**
+         * Creates a new copier.
+         *
+         * @param baseDirectory    base directory of the module to compile.
+         * @param outputDirectory  directory where the output Java files will be located.
+         */
+        Copier(final String baseDirectory, final String outputDirectory) {
+            source = Paths.get(baseDirectory).resolve(UnoPkg.SOURCE_DIRECTORY);
+            target = Paths.get(outputDirectory);
+        }
+
+        /**
+         * Executes the copy operation.
+         */
+        void run() throws IOException {
+            Files.walkFileTree(source, this);
+        }
+
+        /**
+         * Determines whether the given directory should be visited.
+         * This method skips hidden directories.
+         */
+        @Override
+        public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes
attrs) {
+            return dir.getFileName().toString().startsWith(".") ? FileVisitResult.SKIP_SUBTREE
: FileVisitResult.CONTINUE;
+        }
+
+        /**
+         * Invoked for a file in a directory. This method creates the directory if it does
not exist
+         * and performs the actual copy operation.
+         */
+        @Override
+        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
throws IOException {
+            final String filename = file.getFileName().toString();
+            if (filename.endsWith(".class") || filename.endsWith(".CLASS")) {
+                final Path dst = target.resolve(source.relativize(file)).normalize();
+                if (!dst.startsWith(target)) {
+                    throw new IOException("Unexpected target path: " + dst);
                 }
-            } else if (file.isDirectory()) {
-                n += copyClasses(file, new File(outputDirectory, filename));
+                Files.createDirectories(dst.getParent());
+                Files.copy(file, dst, StandardCopyOption.REPLACE_EXISTING);
+                count++;
             }
+            return FileVisitResult.CONTINUE;
         }
-        return n;
     }
 }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/UnoPkg.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/UnoPkg.java
index 2184c78..69b6b50 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/UnoPkg.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/UnoPkg.java
@@ -17,11 +17,10 @@
 package org.apache.sis.internal.unopkg;
 
 import java.io.*;
-import java.util.Map;
+import java.util.Enumeration;
 import java.util.zip.CRC32;
-import java.util.jar.JarFile;
-import java.util.jar.Pack200;
 import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 import java.util.zip.ZipOutputStream;
 
 import org.apache.maven.plugin.AbstractMojo;
@@ -33,14 +32,12 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 
-import static java.util.jar.Pack200.Packer;
-
 
 /**
  * Creates an {@code .oxt} package for <a href="http://www.openoffice.org">OpenOffice.org</a>
addins.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */
@@ -52,6 +49,14 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
     static final String SOURCE_DIRECTORY = "src/main/unopkg";
 
     /**
+     * Module to decompress. We inflate the {@value} module because Derby is much slower
+     * when using an embedded database in a compressed ZIP file compared to flat storage.
+     * Since the JAR files are distributed in a ZIP file anyway, inflating that file has
+     * little impact on the final ZIP file size.
+     */
+    private static final String TO_INFLATE = "sis-embedded-data";
+
+    /**
      * The encoding for text files to read and write.
      */
     private static final String ENCODING = "UTF-8";
@@ -59,7 +64,12 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
     /**
      * The string to replace by the final name.
      */
-    private static final String SUBSTITUTE = "${project.build.finalName}";
+    private static final String FILTERED_NAME = "${project.build.finalName}";
+
+    /**
+     * The string to replace by the version number.
+     */
+    private static final String FILTERED_VERSION = "${project.version}";
 
     /**
      * Base directory of the module to compile.
@@ -83,17 +93,17 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
     private String finalName;
 
     /**
-     * The name for the {@code .oxt} file to create, without the {@code ".oxt"} filename
extension.
+     * In {@code description.xml}, all occurrences of {@code ${project.version}}
+     * will be replaced by this value.
      */
-    @Parameter(property="project.build.finalName", required=true, readonly=true)
-    private String oxtName;
+    @Parameter(property="project.version", required=true, readonly=true)
+    private String version;
 
     /**
-     * {@code true} for using Pack200 compression. If {@code true}, then the add-in registration
-     * class needs to unpack the files itself before use. The default value is {@code false}.
+     * The name for the {@code .oxt} file to create, without the {@code ".oxt"} filename
extension.
      */
-    @Parameter(defaultValue="false")
-    private String pack200;
+    @Parameter(property="project.build.finalName", required=true, readonly=true)
+    private String oxtName;
 
     /**
      * The Maven project running this plugin.
@@ -102,17 +112,6 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
     private MavenProject project;
 
     /**
-     * The prefix to be added before JAR file names.
-     * To be determined by heuristic rule.
-     */
-    private transient String prefix;
-
-    /**
-     * Apply prefix only for dependencies of this group.
-     */
-    private transient String prefixGroup;
-
-    /**
      * Invoked by reflection for creating the MOJO.
      */
     public UnoPkg() {
@@ -144,20 +143,6 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
      */
     @Override
     public void execute() throws MojoExecutionException {
-        final int i = finalName.indexOf(project.getArtifactId());
-        prefix = (i >= 0) ? finalName.substring(0, i) : "";
-        prefixGroup = project.getGroupId();
-        try {
-            createPackage();
-        } catch (IOException e) {
-            throw new MojoExecutionException("Error creating the oxt file.", e);
-        }
-    }
-
-    /**
-     * Creates the {@code .oxt} file.
-     */
-    private void createPackage() throws IOException {
         final String  manifestName = "META-INF/manifest.xml";
         final File sourceDirectory = new File(baseDirectory, SOURCE_DIRECTORY);
         final File outputDirectory = new File(this.outputDirectory);
@@ -171,72 +156,54 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
                 copyFiltered(manifestFile, out, manifestName);
             }
             /*
-             * Copies the RDB files.
+             * Copies files from "unopkg" source directory. This include binary files like
RDB,
+             * but also XML file. We apply filtering on the "description.xml" file in order
to
+             * set the version number automatically.
              */
-            for (int i=0; i<rdbs.length; i++) {
-                copy(rdbs[i], out, null);
+            for (final File rdb : rdbs) {
+                final String name = rdb.getName();
+                if (name.endsWith(".xml")) {
+                    copyFiltered(rdb, out, name);
+                } else {
+                    copy(rdb, out);
+                }
             }
             /*
-             * Copies the JAR (and any additional JARs provided in the output directory).
-             * Do not pack this JAR, because it contains the code needed to inflate the
-             * PACK200 file.
+             * Copies the JAR for this module and any additional JARs provided in the output
directory.
              */
-            for (int i=0; i<jars.length; i++) {
-                copy(jars[i], out, null);
+            for (final File jar : jars) {
+                copy(jar, out);
             }
             /*
-             * Copies the dependencies, optionally in a single PACK200 entry.
-             * We discard most debug information because stack traces are not
-             * easy to get from an application running in OpenOffice anyway.
+             * Copies the dependencies.
              */
-            Pack200.Packer packer = null;
-            if (Boolean.parseBoolean(pack200)) {
-                packer = Pack200.newPacker();
-                final Map<String,String> p = packer.properties();
-                p.put(Packer.EFFORT,            "9");               // take more time choosing
codings for better compression.
-                p.put(Packer.SEGMENT_LIMIT,     "-1");              // use largest-possible
archive segments (>10% better compression).
-                p.put(Packer.KEEP_FILE_ORDER,   Packer.FALSE);      // reorder files for
better compression.
-                p.put(Packer.MODIFICATION_TIME, Packer.LATEST);     // smear modification
times to a single value.
-                p.put(Packer.CODE_ATTRIBUTE_PFX+"LineNumberTable",    Packer.STRIP);    
   // discard debug attributes.
-                p.put(Packer.CODE_ATTRIBUTE_PFX+"LocalVariableTable", Packer.STRIP);    
   // discard debug attributes.
-                p.put(Packer.CLASS_ATTRIBUTE_PFX+"SourceFile",        Packer.STRIP);    
   // discard debug attributes.
-                p.put(Packer.DEFLATE_HINT,      Packer.TRUE);       // transmitting a single
request to use "compress" mode.
-                p.put(Packer.UNKNOWN_ATTRIBUTE, Packer.ERROR);      // throw an error if
an attribute is unrecognized.
-            }
             for (final Artifact artifact : project.getArtifacts()) {
                 final String scope = artifact.getScope();
                 if (Artifact.SCOPE_COMPILE.equalsIgnoreCase(scope) ||
                     Artifact.SCOPE_RUNTIME.equalsIgnoreCase(scope))
                 {
                     final File file = artifact.getFile();
-                    String name = file.getName();
-                    if (artifact.getGroupId().startsWith(prefixGroup) && !name.startsWith(prefix))
{
-                        name = prefix + name;
-                    }
-                    if (packer != null && name.endsWith(".jar")) {
-                        name = name.substring(0, name.length() - 3) + "pack";
-                        try (JarFile jar = new FilteredJarFile(file)) {
-                            out.putNextEntry(new ZipEntry(name));
-                            packer.pack(jar, out);
-                            out.closeEntry();
-                        }
+                    final String name = file.getName();
+                    if (name.startsWith(TO_INFLATE)) {
+                        copyInflated(file, out);
                     } else {
-                        copy(file, out, name);
+                        copy(file, out);
                     }
                 }
             }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Error creating the oxt file.", e);
         }
     }
 
     /**
      * Copies the content of the specified binary file to the specified output stream.
      *
-     * @param  name  the ZIP entry name, or {@code null} for using the name of the given
file.
+     * @param  file    the regular file to copy inside the ZIP file.
+     * @param  bundle  the ZIP file where to copy the given regular file.
      */
-    private static void copy(final File file, final ZipOutputStream out, String name) throws
IOException {
-        if (name == null) {
-            name = file.getName();
-        }
+    private static void copy(final File file, final ZipOutputStream bundle) throws IOException
{
+        final String name = file.getName();
         final ZipEntry entry = new ZipEntry(name);
         if (name.endsWith(".png")) {
             final long size = file.length();
@@ -245,38 +212,71 @@ public final class UnoPkg extends AbstractMojo implements FilenameFilter
{
             entry.setCompressedSize(size);
             entry.setCrc(getCRC32(file));
         }
-        out.putNextEntry(entry);
+        bundle.putNextEntry(entry);
         try (InputStream in = new FileInputStream(file)) {
-            final byte[] buffer = new byte[4*1024];
-            int length;
-            while ((length = in.read(buffer)) >= 0) {
-                out.write(buffer, 0, length);
-            }
+            in.transferTo(bundle);
         }
-        out.closeEntry();
+        bundle.closeEntry();
     }
 
     /**
      * Copies the content of the specified ASCII file to the specified output stream.
+     *
+     * @param  file    the regular file to copy inside the ZIP file.
+     * @param  bundle  the ZIP file where to copy the given regular file.
+     * @param  name    the ZIP entry name.
      */
-    private void copyFiltered(final File file, final ZipOutputStream out, String name) throws
IOException {
-        if (name == null) {
-            name = file.getName();
-        }
+    private void copyFiltered(final File file, final ZipOutputStream bundle, final String
name) throws IOException {
         final ZipEntry entry = new ZipEntry(name);
-        out.putNextEntry(entry);
-        final Writer writer = new OutputStreamWriter(out, ENCODING);
+        bundle.putNextEntry(entry);
+        final Writer writer = new OutputStreamWriter(bundle, ENCODING);
         try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),
ENCODING))) {
-            String line; while ((line=in.readLine()) != null) {
-                int r=-1; while ((r=line.indexOf(SUBSTITUTE, r+1)) >= 0) {
-                    line = line.substring(0, r) + finalName + line.substring(r + SUBSTITUTE.length());
-                }
+            String line;
+            while ((line = in.readLine()) != null) {
+                line = line.replace(FILTERED_NAME, finalName);
+                line = line.replace(FILTERED_VERSION, version);
                 writer.write(line);
                 writer.write('\n');
             }
         }
         writer.flush();
-        out.closeEntry();
+        bundle.closeEntry();
+    }
+
+    /**
+     * Copies a JAR file in the given ZIP file, but without compression for the files
+     * in {@code SIS_DATA} directory.
+     *
+     * @param  file    the JAR file to copy.
+     * @param  bundle  destination where to copy the JAR file.
+     */
+    private static void copyInflated(final File file, final ZipOutputStream bundle) throws
IOException {
+        final ZipEntry entry = new ZipEntry(file.getName());
+        bundle.putNextEntry(entry);
+        final ZipOutputStream out = new ZipOutputStream(bundle);
+        out.setLevel(9);
+        try (ZipFile in = new ZipFile(file)) {
+            final Enumeration<? extends ZipEntry> entries = in.entries();
+            while (entries.hasMoreElements()) {
+                final ZipEntry   inEntry  = entries.nextElement();
+                final String     name     = inEntry.getName();
+                final ZipEntry   outEntry = new ZipEntry(name);
+                if (name.startsWith("SIS_DATA")) {
+                    final long size = inEntry.getSize();
+                    outEntry.setMethod(ZipOutputStream.STORED);
+                    outEntry.setSize(size);
+                    outEntry.setCompressedSize(size);
+                    outEntry.setCrc(inEntry.getCrc());
+                }
+                try (InputStream inStream = in.getInputStream(inEntry)) {
+                    out.putNextEntry(outEntry);
+                    inStream.transferTo(out);
+                    out.closeEntry();
+                }
+            }
+        }
+        out.finish();
+        bundle.closeEntry();
     }
 
     /**
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/package-info.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/package-info.java
index cffa45e..8ac5cc8 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/package-info.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/unopkg/package-info.java
@@ -35,14 +35,8 @@
  *       and {@code __writeRegistryServiceInfo(…)} public static methods.</li>
  *   <li>{@code myAddinFilename} —
  *       The final filename, without the {@code .oxt} extension.</li>
- *   <li>{@code usePack200} (optional) —
- *       Whether to use Pack200 compression rather than plain JAR files for all dependencies.
- *       The default value is {@code false} (store plain old JAR files).</li>
  * </ul>
  *
- * Note that if Pack200 files are generated, then it is implementor responsibility to unpack
them
- * inside OpenOffice.org add-in directory during the {@code __writeRegistryServiceInfo} execution
phase.
- *
  * <div class="section">Maven project file</div>
  * {@preformat xml
  *   <dependencies>
@@ -72,7 +66,6 @@
  *         <artifactId>sis-build-helper</artifactId>
  *         <configuration>
  *           <oxtName>myAddinFilename</oxtName>
- *           <pack200>usePack200</pack200>
  *         </configuration>
  *         <executions>
  *           <execution>
@@ -88,7 +81,7 @@
  * }
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */


Mime
View raw message