Browse Source

Add the possibility to specify a custom filename mapper when creating an INDEX.LIST (#134)

master
Maarten Coene GitHub 4 years ago
parent
commit
7e6cc33e04
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 248 additions and 17 deletions
  1. +8
    -0
      manual/Tasks/jar.html
  2. +16
    -1
      src/etc/testcases/taskdefs/jar.xml
  3. +100
    -15
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  4. +124
    -1
      src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java

+ 8
- 0
manual/Tasks/jar.html View File

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


+ 16
- 1
src/etc/testcases/taskdefs/jar.xml View File

@@ -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}"/>


+ 100
- 15
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -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.
@@ -405,6 +415,30 @@ public class Jar extends Zip {
indexJars.append(p);
}

/**
* 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.
@@ -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();
}
@@ -636,6 +661,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
@@ -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};
}
}
}

+ 124
- 1
src/tests/junit/org/apache/tools/ant/taskdefs/JarTest.java View File

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


Loading…
Cancel
Save