You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by ma...@apache.org on 2020/09/08 07:13:51 UTC

[ant] branch master updated: Add the possibility to specify a custom filename mapper when creating an INDEX.LIST (#134)

This is an automated email from the ASF dual-hosted git repository.

maartenc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e6cc33  Add the possibility to specify a custom filename mapper when creating an INDEX.LIST (#134)
7e6cc33 is described below

commit 7e6cc33e04ecf6fae6f51d24f67c21bd321d13ee
Author: Maarten Coene <ma...@apache.org>
AuthorDate: Tue Sep 8 09:13:37 2020 +0200

    Add the possibility to specify a custom filename mapper when creating an INDEX.LIST (#134)
---
 manual/Tasks/jar.html                              |   8 ++
 src/etc/testcases/taskdefs/jar.xml                 |  17 ++-
 src/main/org/apache/tools/ant/taskdefs/Jar.java    | 115 ++++++++++++++++---
 .../org/apache/tools/ant/taskdefs/JarTest.java     | 125 ++++++++++++++++++++-
 4 files changed, 248 insertions(+), 17 deletions(-)

diff --git a/manual/Tasks/jar.html b/manual/Tasks/jar.html
index 581ae4b..9db18f3 100644
--- a/manual/Tasks/jar.html
+++ b/manual/Tasks/jar.html
@@ -349,6 +349,14 @@ names used for the archives depend on your manifest:</p>
 inside the <samp>META-INF</samp> directory unless the <var>indexmetainf</var> attribute has been set
 to <q>true</q>.</p>
 
+<h4 id="indexjarsmapper">indexjarsmapper</h4>
+
+<p><em>Since Ant 1.10.9</em></p>
+
+<p>The nested <code>indexjarsmapper</code> element can be used to perform custom filename
+transformations for the archives specified by <code>indexjars</code> if the
+<a href="#indexjars">default filename transformation</a> doesn't suffice.
+
 <h4 id="service">service</h4>
 
 <p><em>Since Ant 1.7.0</em></p>
diff --git a/src/etc/testcases/taskdefs/jar.xml b/src/etc/testcases/taskdefs/jar.xml
index c191ed2..0aaeeef 100644
--- a/src/etc/testcases/taskdefs/jar.xml
+++ b/src/etc/testcases/taskdefs/jar.xml
@@ -248,7 +248,22 @@
       </indexjars>
     </jar>
   </target>
-    
+
+  <target name="testIndexJarsPlusJarMarkerWithMapping">
+    <mkdir dir="${tmp.dir}/a/b/c"/>
+    <jar destfile="${tmp.jar}" basedir="${tmp.dir}"/>
+    <delete dir="${tmp.dir}/a" quiet="true"/>
+    <mkdir dir="${tmp.dir}/d/e/f"/>
+    <jar destfile="${tmp.jar}2" basedir="${tmp.dir}" index="true">
+      <indexjars>
+        <fileset file="${tmp.jar}"/>
+      </indexjars>
+      <indexjarsmapper>
+        <globmapper from="${output}/*" to="foo/*" handledirsep="true"/>
+      </indexjarsmapper>
+    </jar>
+  </target>
+
   <target name="testNoVersionInfoNoStrict">
     <mkdir dir="${tmp.dir}"/>
     <jar destfile="${tmp.jar}" basedir="${tmp.dir}"/>
diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java
index 42f19fb..0c7bff9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Jar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java
@@ -50,11 +50,13 @@ import org.apache.tools.ant.taskdefs.Manifest.Section;
 import org.apache.tools.ant.types.ArchiveFileSet;
 import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Mapper;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.ZipFileSet;
 import org.apache.tools.ant.types.spi.Service;
+import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.StreamUtils;
 import org.apache.tools.zip.JarMarker;
@@ -151,6 +153,14 @@ public class Jar extends Zip {
      */
     private Path indexJars;
 
+    /**
+     * A mapper used to convert the jars to entries in the index.
+     *
+     * @since Ant 1.10.9
+     */
+    private FileNameMapper indexJarsMapper = null;
+
+
     // CheckStyle:LineLength OFF - Link is too long.
     /**
      * Strict mode for checking rules of the JAR-Specification.
@@ -406,6 +416,30 @@ public class Jar extends Zip {
     }
 
     /**
+     * Add a mapper used to convert the jars to entries in the index.
+     *
+     * @param mapper a mapper
+     * @since Ant 1.10.9
+     */
+    public void addConfiguredIndexJarsMapper(Mapper mapper) {
+        if (indexJarsMapper != null) {
+            throw new BuildException("Cannot define more than one indexjar-mapper",
+                    getLocation());
+        }
+        indexJarsMapper = mapper.getImplementation();
+    }
+
+    /**
+     * Returns the mapper used to convert the jars to entries in the index. May be null.
+     *
+     * @since Ant 1.10.9
+     */
+    public FileNameMapper getIndexJarsMapper() {
+        return indexJarsMapper;
+    }
+
+
+    /**
      * A nested SPI service element.
      * @param service the nested element.
      * @since Ant 1.7
@@ -597,27 +631,18 @@ public class Jar extends Zip {
         writer.println();
 
         if (indexJars != null) {
-            Manifest mf = createManifest();
-            Manifest.Attribute classpath =
-                mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
-            String[] cpEntries = null;
-            if (classpath != null && classpath.getValue() != null) {
-                StringTokenizer tok = new StringTokenizer(classpath.getValue(),
-                                                          " ");
-                cpEntries = new String[tok.countTokens()];
-                int c = 0;
-                while (tok.hasMoreTokens()) {
-                    cpEntries[c++] = tok.nextToken();
-                }
+            FileNameMapper mapper = indexJarsMapper;
+            if (mapper == null) {
+                mapper = createDefaultIndexJarsMapper();
             }
             for (String indexJarEntry : indexJars.list()) {
-                String name = findJarName(indexJarEntry, cpEntries);
-                if (name != null) {
+                String[] names = mapper.mapFileName(indexJarEntry);
+                if (names != null && names.length > 0) {
                     ArrayList<String> dirs = new ArrayList<>();
                     ArrayList<String> files = new ArrayList<>();
                     grabFilesAndDirs(indexJarEntry, dirs, files);
                     if (dirs.size() + files.size() > 0) {
-                        writer.println(name);
+                        writer.println(names[0]);
                         writeIndexLikeList(dirs, files, writer);
                         writer.println();
                     }
@@ -637,6 +662,31 @@ public class Jar extends Zip {
     }
 
     /**
+     * Creates a mapper for the index based on the classpath attribute in the manifest.
+     * See {@link #findJarName(String, String[])} for more details.
+     *
+     * @return a mapper
+     * @since Ant 1.10.9
+     */
+    private FileNameMapper createDefaultIndexJarsMapper() {
+        Manifest mf = createManifest();
+        Manifest.Attribute classpath =
+                mf.getMainSection().getAttribute(Manifest.ATTRIBUTE_CLASSPATH);
+        String[] cpEntries = null;
+        if (classpath != null && classpath.getValue() != null) {
+            StringTokenizer tok = new StringTokenizer(classpath.getValue(),
+                    " ");
+            cpEntries = new String[tok.countTokens()];
+            int c = 0;
+            while (tok.hasMoreTokens()) {
+                cpEntries[c++] = tok.nextToken();
+            }
+        }
+
+        return new IndexJarsFilenameMapper(cpEntries);
+    }
+
+    /**
      * Overridden from Zip class to deal with manifests and index lists.
      * @param is the stream to read data for the entry from.  The
      * caller of the method is responsible for closing the stream.
@@ -1162,4 +1212,39 @@ public class Jar extends Zip {
             return "ignore".equals(getValue()) ? Project.MSG_VERBOSE : Project.MSG_WARN;
         }
     }
+
+    /**
+     * A mapper for the index based on the classpath attribute in the manifest.
+     * See {@link #findJarName(String, String[])} for more details.
+     *
+     * @since Ant 1.10.9
+     */
+    private static class IndexJarsFilenameMapper implements FileNameMapper {
+
+        private String[] classpath;
+
+        IndexJarsFilenameMapper(String[] classpath) {
+            this.classpath = classpath;
+        }
+
+        /**
+         * Empty implementation.
+         */
+        @Override
+        public void setFrom(String from) {
+        }
+
+        /**
+         * Empty implementation.
+         */
+        @Override
+        public void setTo(String to) {
+        }
+
+        @Override
+        public String[] mapFileName(String sourceFileName) {
+            String result = findJarName(sourceFileName, classpath);
+            return result == null ? null : new String[] {result};
+        }
+    }
 }
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
index d4e9cd7..21cdd68 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java
@@ -253,6 +253,7 @@ public class JarTest {
             ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
             InputStream is = archive.getInputStream(ze);
             BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            boolean foundArchive = false;
             boolean foundSub = false;
             boolean foundSubFoo = false;
             boolean foundFoo = false;
@@ -260,6 +261,9 @@ public class JarTest {
             String line = r.readLine();
             while (line != null) {
                 switch (line) {
+                    case "tmp.jar":
+                        foundArchive = true;
+                        break;
                     case "foo":
                         foundFoo = true;
                         break;
@@ -273,6 +277,7 @@ public class JarTest {
                 line = r.readLine();
             }
 
+            assertTrue(foundArchive);
             assertTrue(foundSub);
             assertFalse(foundSubFoo);
             assertTrue(foundFoo);
@@ -287,8 +292,126 @@ public class JarTest {
     }
 
     @Test
-    public void testIndexJarsPlusJarMarker() {
+    public void testIndexJarsPlusJarMarker() throws IOException {
         buildRule.executeTarget("testIndexJarsPlusJarMarker");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar + "2"))) {
+            ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
+            InputStream is = archive.getInputStream(ze);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            // tmp.jar
+            boolean foundTmp = false;
+            boolean foundA = false;
+            boolean foundAB = false;
+            boolean foundABC = false;
+
+            // tmp2.jar
+            boolean foundTmp2 = false;
+            boolean foundD = false;
+            boolean foundDE = false;
+            boolean foundDEF = false;
+
+            String line = r.readLine();
+            while (line != null) {
+                switch (line) {
+                    case "tmp.jar":
+                        foundTmp = true;
+                        break;
+                    case "a":
+                        foundA = true;
+                        break;
+                    case "a/b":
+                        foundAB = true;
+                        break;
+                    case "a/b/c":
+                        foundABC = true;
+                        break;
+                    case "tmp.jar2":
+                        foundTmp2 = true;
+                        break;
+                    case "d":
+                        foundD = true;
+                        break;
+                    case "d/e":
+                        foundDE = true;
+                        break;
+                    case "d/e/f":
+                        foundDEF = true;
+                        break;
+                }
+                line = r.readLine();
+            }
+
+            assertTrue(foundTmp);
+            assertTrue(foundA);
+            assertTrue(foundAB);
+            assertTrue(foundABC);
+            assertTrue(foundTmp2);
+            assertTrue(foundD);
+            assertTrue(foundDE);
+            assertTrue(foundDEF);
+        }
+    }
+
+    @Test
+    public void testIndexJarsPlusJarMarkerWithMapping() throws IOException {
+        buildRule.executeTarget("testIndexJarsPlusJarMarkerWithMapping");
+        try (ZipFile archive = new ZipFile(new File(getOutputDir(), tempJar + "2"))) {
+            ZipEntry ze = archive.getEntry("META-INF/INDEX.LIST");
+            InputStream is = archive.getInputStream(ze);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
+            // tmp.jar
+            boolean foundTmp = false;
+            boolean foundA = false;
+            boolean foundAB = false;
+            boolean foundABC = false;
+
+            // tmp2.jar
+            boolean foundTmp2 = false;
+            boolean foundD = false;
+            boolean foundDE = false;
+            boolean foundDEF = false;
+
+            String line = r.readLine();
+            while (line != null) {
+                System.out.println("line = " + line);
+                switch (line) {
+                    case "foo/tmp.jar":
+                        foundTmp = true;
+                        break;
+                    case "a":
+                        foundA = true;
+                        break;
+                    case "a/b":
+                        foundAB = true;
+                        break;
+                    case "a/b/c":
+                        foundABC = true;
+                        break;
+                    case "tmp.jar2":
+                        foundTmp2 = true;
+                        break;
+                    case "d":
+                        foundD = true;
+                        break;
+                    case "d/e":
+                        foundDE = true;
+                        break;
+                    case "d/e/f":
+                        foundDEF = true;
+                        break;
+                }
+                line = r.readLine();
+            }
+
+            assertTrue(foundTmp);
+            assertTrue(foundA);
+            assertTrue(foundAB);
+            assertTrue(foundABC);
+            assertTrue(foundTmp2);
+            assertTrue(foundD);
+            assertTrue(foundDE);
+            assertTrue(foundDEF);
+        }
     }
 
     @Test