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 <maart...@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