Browse Source

allow Class-Path attributes to be merged and optionally be flattened. PR 39655

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@806174 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 16 years ago
parent
commit
77024a43a2
9 changed files with 307 additions and 20 deletions
  1. +8
    -0
      WHATSNEW
  2. +19
    -0
      docs/manual/CoreTasks/ear.html
  3. +19
    -0
      docs/manual/CoreTasks/jar.html
  4. +19
    -0
      docs/manual/CoreTasks/manifest.html
  5. +19
    -0
      docs/manual/CoreTasks/war.html
  6. +37
    -7
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  7. +109
    -10
      src/main/org/apache/tools/ant/taskdefs/Manifest.java
  8. +32
    -3
      src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
  9. +45
    -0
      src/tests/antunit/taskdefs/manifest-test.xml

+ 8
- 0
WHATSNEW View File

@@ -439,6 +439,14 @@ Fixed bugs:
* The update attribute of the modified selector was ignored.
Bugzilla Report 32597.

* <manifest> and <jar> can now merge Class-Path attributes from
multiple sources and optionally flatten them into a single
attribute.
The default behaviour still is to keep multiple Class-Path
attributes if they have been specified and to only include the
attributes of the last merged manifest.
Bugzilla Report 39655.

Other changes:
--------------
* The get task now also follows redirects from http to https


+ 19
- 0
docs/manual/CoreTasks/ear.html View File

@@ -245,6 +245,25 @@ to a value other than its default, <code>&quot;add&quot;</code>.</b></p>
zip task page</a></td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">mergeClassPathAttributes</td>
<td valign="top">Whether to merge the Class-Path attributes found
in different manifests (if merging manifests). If false, only
the attribute of the last merged manifest will be preserved.
<em>Since Ant 1.8.0</em>.
<br/>unless you also set flattenAttributes to true this may
result in manifests containing multiple Class-Path attributes
which violates the manifest specification.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">flattenAttributes</td>
<td valign="top">Whether to merge attributes occuring more than
once in a section (this can only happen for the Class-Path
attribute) into a single attribute.
<em>Since Ant 1.8.0</em>.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
</table>

<h3>Nested elements</h3>


+ 19
- 0
docs/manual/CoreTasks/jar.html View File

@@ -301,6 +301,25 @@ to a value other than its default, <code>"add"</code>.</b></p>
zip task page</a></td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">mergeClassPathAttributes</td>
<td valign="top">Whether to merge the Class-Path attributes found
in different manifests (if merging manifests). If false, only
the attribute of the last merged manifest will be preserved.
<em>Since Ant 1.8.0</em>.
<br/>unless you also set flattenAttributes to true this may
result in manifests containing multiple Class-Path attributes
which violates the manifest specification.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">flattenAttributes</td>
<td valign="top">Whether to merge attributes occuring more than
once in a section (this can only happen for the Class-Path
attribute) into a single attribute.
<em>Since Ant 1.8.0</em>.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
</table>

<h3>Nested elements</h3>


+ 19
- 0
docs/manual/CoreTasks/manifest.html View File

@@ -82,6 +82,25 @@ line.</p>
manifest.</td>
<td valign="top" align="center">No, defaults to UTF-8 encoding.</td>
</tr>
<tr>
<td valign="top">mergeClassPathAttributes</td>
<td valign="top">Whether to merge the Class-Path attributes found
in different manifests (if updating). If false, only the
attribute of the most recent manifest will be preserved.
<em>Since Ant 1.8.0</em>.
<br/>unless you also set flattenAttributes to true this may
result in manifests containing multiple Class-Path attributes
which violates the manifest specification.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">flattenAttributes</td>
<td valign="top">Whether to merge attributes occuring more than
once in a section (this can only happen for the Class-Path
attribute) into a single attribute.
<em>Since Ant 1.8.0</em>.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
</table>

<h3>Nested elements</h3>


+ 19
- 0
docs/manual/CoreTasks/war.html View File

@@ -248,6 +248,25 @@ to a value other than its default, <code>&quot;add&quot;</code>.</b></p>
zip task page</a></td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">mergeClassPathAttributes</td>
<td valign="top">Whether to merge the Class-Path attributes found
in different manifests (if merging manifests). If false, only
the attribute of the last merged manifest will be preserved.
<em>Since Ant 1.8.0</em>.
<br/>unless you also set flattenAttributes to true this may
result in manifests containing multiple Class-Path attributes
which violates the manifest specification.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
<tr>
<td valign="top">flattenAttributes</td>
<td valign="top">Whether to merge attributes occuring more than
once in a section (this can only happen for the Class-Path
attribute) into a single attribute.
<em>Since Ant 1.8.0</em>.</td>
<td align="center" valign="top">No, default is false</td>
</tr>
</table>

<h3>Nested elements</h3>


+ 37
- 7
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -157,6 +157,16 @@ public class Jar extends Zip {

// CheckStyle:LineLength ON

/**
* whether to merge Class-Path attributes.
*/
private boolean mergeClassPaths = false;

/**
* whether to flatten Class-Path attributes into a single one.
*/
private boolean flattenClassPaths = false;

/**
* Extra fields needed to make Solaris recognize the archive as a jar file.
*
@@ -268,7 +278,7 @@ public class Jar extends Zip {
if (configuredManifest == null) {
configuredManifest = newManifest;
} else {
configuredManifest.merge(newManifest);
configuredManifest.merge(newManifest, false, mergeClassPaths);
}
savedConfiguredManifest = configuredManifest;
}
@@ -473,6 +483,24 @@ public class Jar extends Zip {
}
}

/**
* Whether to merge Class-Path attributes.
*
* @since Ant 1.8.0
*/
public void setMergeClassPathAttributes(boolean b) {
mergeClassPaths = b;
}

/**
* Whether to flatten multi-valued attributes (i.e. Class-Path)
* into a single one.
*
* @since Ant 1.8.0
*/
public void setFlattenAttributes(boolean b) {
flattenClassPaths = b;
}

/**
* Initialize the zip output stream.
@@ -512,11 +540,13 @@ public class Jar extends Zip {
*/

if (isInUpdateMode()) {
finalManifest.merge(originalManifest);
finalManifest.merge(originalManifest, false, mergeClassPaths);
}
finalManifest.merge(filesetManifest);
finalManifest.merge(configuredManifest, !mergeManifestsMain);
finalManifest.merge(manifest, !mergeManifestsMain);
finalManifest.merge(filesetManifest, false, mergeClassPaths);
finalManifest.merge(configuredManifest, !mergeManifestsMain,
mergeClassPaths);
finalManifest.merge(manifest, !mergeManifestsMain,
mergeClassPaths);

return finalManifest;

@@ -540,7 +570,7 @@ public class Jar extends Zip {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(baos, Manifest.JAR_ENCODING);
PrintWriter writer = new PrintWriter(osw);
manifest.write(writer);
manifest.write(writer, flattenClassPaths);
if (writer.checkError()) {
throw new IOException("Encountered an error writing the manifest");
}
@@ -724,7 +754,7 @@ public class Jar extends Zip {
if (filesetManifest == null) {
filesetManifest = newManifest;
} else {
filesetManifest.merge(newManifest);
filesetManifest.merge(newManifest, false, mergeClassPaths);
}
} catch (UnsupportedEncodingException e) {
throw new BuildException("Unsupported encoding while reading "


+ 109
- 10
src/main/org/apache/tools/ant/taskdefs/Manifest.java View File

@@ -304,16 +304,37 @@ public class Manifest {
}

/**
* Write the attribute out to a print writer.
* Write the attribute out to a print writer without
* flattening multi-values attributes (i.e. Class-Path).
*
* @param writer the Writer to which the attribute is written
*
* @throws IOException if the attribute value cannot be written
*/
public void write(PrintWriter writer) throws IOException {
write(writer, false);
}

/**
* Write the attribute out to a print writer.
*
* @param writer the Writer to which the attribute is written
* @param flatten whether to collapse multi-valued attributes
* (i.e. potentially Class-Path) Class-Path into a
* single attribute.
*
* @throws IOException if the attribute value cannot be written
* @since Ant 1.8.0
*/
public void write(PrintWriter writer, boolean flatten)
throws IOException {
if (!flatten) {
for (Enumeration e = getValues(); e.hasMoreElements();) {
writeValue(writer, (String) e.nextElement());
}
} else {
writeValue(writer, getValue());
}
}

/**
@@ -448,13 +469,27 @@ public class Manifest {
}

/**
* Merge in another section
* Merge in another section without merging Class-Path attributes.
*
* @param section the section to be merged with this one.
*
* @throws ManifestException if the sections cannot be merged.
*/
public void merge(Section section) throws ManifestException {
merge(section, false);
}

/**
* Merge in another section
*
* @param section the section to be merged with this one.
* @param mergeClassPaths whether Class-Path attributes should
* be merged.
*
* @throws ManifestException if the sections cannot be merged.
*/
public void merge(Section section, boolean mergeClassPaths)
throws ManifestException {
if (name == null && section.getName() != null
|| name != null
&& !(name.equalsIgnoreCase(section.getName()))) {
@@ -484,7 +519,16 @@ public class Manifest {
}

if (classpathAttribute != null) {
// the merge file *always* wins, even for Class-Path
if (mergeClassPaths) {
Attribute currentCp = getAttribute(ATTRIBUTE_CLASSPATH);
if (currentCp != null) {
for (Enumeration attribEnum = currentCp.getValues();
attribEnum.hasMoreElements(); ) {
String value = (String) attribEnum.nextElement();
classpathAttribute.addValue(value);
}
}
}
storeAttribute(classpathAttribute);
}

@@ -496,13 +540,30 @@ public class Manifest {
}

/**
* Write the section out to a print writer.
* Write the section out to a print writer without flattening
* multi-values attributes (i.e. Class-Path).
*
* @param writer the Writer to which the section is written
*
* @throws IOException if the section cannot be written
*/
public void write(PrintWriter writer) throws IOException {
write(writer, false);
}

/**
* Write the section out to a print writer.
*
* @param writer the Writer to which the section is written
* @param flatten whether to collapse multi-valued attributes
* (i.e. potentially Class-Path) Class-Path into a
* single attribute.
*
* @throws IOException if the section cannot be written
* @since Ant 1.8.0
*/
public void write(PrintWriter writer, boolean flatten)
throws IOException {
if (name != null) {
Attribute nameAttr = new Attribute(ATTRIBUTE_NAME, name);
nameAttr.write(writer);
@@ -511,7 +572,7 @@ public class Manifest {
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
Attribute attribute = getAttribute(key);
attribute.write(writer);
attribute.write(writer, flatten);
}
writer.print(EOL);
}
@@ -863,6 +924,7 @@ public class Manifest {

/**
* Merge the contents of the given manifest into this manifest
* without merging Class-Path attributes.
*
* @param other the Manifest to be merged with this one.
*
@@ -875,6 +937,7 @@ public class Manifest {

/**
* Merge the contents of the given manifest into this manifest
* without merging Class-Path attributes.
*
* @param other the Manifest to be merged with this one.
* @param overwriteMain whether to overwrite the main section
@@ -885,11 +948,31 @@ public class Manifest {
*/
public void merge(Manifest other, boolean overwriteMain)
throws ManifestException {
merge(other, overwriteMain, false);
}

/**
* Merge the contents of the given manifest into this manifest
*
* @param other the Manifest to be merged with this one.
* @param overwriteMain whether to overwrite the main section
* of the current manifest
* @param mergeClassPaths whether Class-Path attributes should be
* merged.
*
* @throws ManifestException if there is a problem merging the
* manifest according to the Manifest spec.
*
* @since Ant 1.8.0
*/
public void merge(Manifest other, boolean overwriteMain,
boolean mergeClassPaths)
throws ManifestException {
if (other != null) {
if (overwriteMain) {
mainSection = (Section) other.mainSection.clone();
} else {
mainSection.merge(other.mainSection);
mainSection.merge(other.mainSection, mergeClassPaths);
}

if (other.manifestVersion != null) {
@@ -907,20 +990,36 @@ public class Manifest {
addConfiguredSection((Section) otherSection.clone());
}
} else {
ourSection.merge(otherSection);
ourSection.merge(otherSection, mergeClassPaths);
}
}
}
}

/**
* Write the manifest out to a print writer without flattening
* multi-values attributes (i.e. Class-Path).
*
* @param writer the Writer to which the manifest is written
*
* @throws IOException if the manifest cannot be written
*/
public void write(PrintWriter writer) throws IOException {
write(writer, false);
}

/**
* Write the manifest out to a print writer.
*
* @param writer the Writer to which the manifest is written
* @param flatten whether to collapse multi-valued attributes
* (i.e. potentially Class-Path) Class-Path into a single
* attribute.
*
* @throws IOException if the manifest cannot be written
* @since Ant 1.8.0
*/
public void write(PrintWriter writer) throws IOException {
public void write(PrintWriter writer, boolean flatten) throws IOException {
writer.print(ATTRIBUTE_MANIFEST_VERSION + ": " + manifestVersion + EOL);
String signatureVersion
= mainSection.getAttributeValue(ATTRIBUTE_SIGNATURE_VERSION);
@@ -929,7 +1028,7 @@ public class Manifest {
+ signatureVersion + EOL);
mainSection.removeAttribute(ATTRIBUTE_SIGNATURE_VERSION);
}
mainSection.write(writer);
mainSection.write(writer, flatten);

// add it back
if (signatureVersion != null) {
@@ -946,7 +1045,7 @@ public class Manifest {
while (e.hasMoreElements()) {
String sectionName = (String) e.nextElement();
Section section = getSection(sectionName);
section.write(writer);
section.write(writer, flatten);
}
}



+ 32
- 3
src/main/org/apache/tools/ant/taskdefs/ManifestTask.java View File

@@ -72,6 +72,16 @@ public class ManifestTask extends Task {
*/
private String encoding;

/**
* whether to merge Class-Path attributes.
*/
private boolean mergeClassPaths = false;

/**
* whether to flatten Class-Path attributes into a single one.
*/
private boolean flattenClassPaths = false;

/**
* Helper class for Manifest's mode attribute.
*/
@@ -183,6 +193,25 @@ public class ManifestTask extends Task {
mode = m;
}

/**
* Whether to merge Class-Path attributes.
*
* @since Ant 1.8.0
*/
public void setMergeClassPathAttributes(boolean b) {
mergeClassPaths = b;
}

/**
* Whether to flatten multi-valued attributes (i.e. Class-Path)
* into a single one.
*
* @since Ant 1.8.0
*/
public void setFlattenAttributes(boolean b) {
flattenClassPaths = b;
}

/**
* Create or update the Manifest when used as a task.
*
@@ -228,13 +257,13 @@ public class ManifestTask extends Task {
try {
if (mode.getValue().equals("update") && manifestFile.exists()) {
if (current != null) {
toWrite.merge(current);
toWrite.merge(current, false, mergeClassPaths);
} else if (error != null) {
throw error;
}
}

toWrite.merge(nestedManifest);
toWrite.merge(nestedManifest, false, mergeClassPaths);
} catch (ManifestException m) {
throw new BuildException("Manifest is invalid", m, getLocation());
}
@@ -250,7 +279,7 @@ public class ManifestTask extends Task {
FileOutputStream fos = new FileOutputStream(manifestFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, Manifest.JAR_ENCODING);
w = new PrintWriter(osw);
toWrite.write(w);
toWrite.write(w, flattenClassPaths);
if (w.checkError()) {
throw new IOException("Encountered an error writing manifest");
}


+ 45
- 0
src/tests/antunit/taskdefs/manifest-test.xml View File

@@ -91,4 +91,49 @@
resource="${file}"
value="Class-Path: bar&#13;&#10;"/>
</target>

<target name="testMergeClassPathAttributes" depends="setUp">
<manifest file="${file}">
<attribute name="Class-Path" value="foo"/>
<attribute name="Class-Path" value="bar"/>
</manifest>
<manifest file="${file}" mergeClassPathAttributes="true" mode="update">
<attribute name="Class-Path" value="baz"/>
</manifest>
<au:assertResourceContains
resource="${file}"
value="Class-Path: foo&#13;&#10;"/>
<au:assertResourceContains
resource="${file}"
value="Class-Path: bar&#13;&#10;"/>
<au:assertResourceContains
resource="${file}"
value="Class-Path: baz&#13;&#10;"/>
</target>

<target name="testFlattenMultipleClassPathAttributes" depends="setUp">
<manifest file="${file}" flattenAttributes="true">
<attribute name="Class-Path" value="foo"/>
<attribute name="Class-Path" value="bar"/>
</manifest>
<au:assertResourceContains
resource="${file}"
value="Class-Path: foo bar&#13;&#10;"/>
</target>

<target name="testMergeAndFlattenClassPathAttributes" depends="setUp">
<manifest file="${file}">
<attribute name="Class-Path" value="foo"/>
<attribute name="Class-Path" value="bar"/>
</manifest>
<manifest file="${file}"
mergeClassPathAttributes="true"
flattenAttributes="true"
mode="update">
<attribute name="Class-Path" value="baz"/>
</manifest>
<au:assertResourceContains
resource="${file}"
value="Class-Path: baz foo bar&#13;&#10;"/>
</target>
</project>

Loading…
Cancel
Save