Author: bodewig
Date: Thu Aug 20 13:52:09 2009
New Revision: 806174
URL: http://svn.apache.org/viewvc?rev=806174&view=rev
Log:
allow Class-Path attributes to be merged and optionally be flattened. PR 39655
Modified:
ant/core/trunk/WHATSNEW
ant/core/trunk/docs/manual/CoreTasks/ear.html
ant/core/trunk/docs/manual/CoreTasks/jar.html
ant/core/trunk/docs/manual/CoreTasks/manifest.html
ant/core/trunk/docs/manual/CoreTasks/war.html
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Jar.java
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Manifest.java
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
ant/core/trunk/src/tests/antunit/taskdefs/manifest-test.xml
Modified: ant/core/trunk/WHATSNEW
URL:
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Thu Aug 20 13:52:09 2009
@@ -439,6 +439,14 @@
* 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
Modified: ant/core/trunk/docs/manual/CoreTasks/ear.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/ear.html?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/ear.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/ear.html Thu Aug 20 13:52:09 2009
@@ -245,6 +245,25 @@
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>
Modified: ant/core/trunk/docs/manual/CoreTasks/jar.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/jar.html?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/jar.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/jar.html Thu Aug 20 13:52:09 2009
@@ -301,6 +301,25 @@
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>
Modified: ant/core/trunk/docs/manual/CoreTasks/manifest.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/manifest.html?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/manifest.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/manifest.html Thu Aug 20 13:52:09 2009
@@ -82,6 +82,25 @@
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>
Modified: ant/core/trunk/docs/manual/CoreTasks/war.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/CoreTasks/war.html?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/CoreTasks/war.html (original)
+++ ant/core/trunk/docs/manual/CoreTasks/war.html Thu Aug 20 13:52:09 2009
@@ -248,6 +248,25 @@
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>
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Jar.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Jar.java?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Jar.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Jar.java Thu Aug 20
13:52:09 2009
@@ -158,6 +158,16 @@
// 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.
*
* @since Ant 1.6.3
@@ -268,7 +278,7 @@
if (configuredManifest == null) {
configuredManifest = newManifest;
} else {
- configuredManifest.merge(newManifest);
+ configuredManifest.merge(newManifest, false, mergeClassPaths);
}
savedConfiguredManifest = configuredManifest;
}
@@ -473,6 +483,24 @@
}
}
+ /**
+ * 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 @@
*/
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 @@
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 @@
if (filesetManifest == null) {
filesetManifest = newManifest;
} else {
- filesetManifest.merge(newManifest);
+ filesetManifest.merge(newManifest, false, mergeClassPaths);
}
} catch (UnsupportedEncodingException e) {
throw new BuildException("Unsupported encoding while reading "
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Manifest.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Manifest.java?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Manifest.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Manifest.java Thu Aug
20 13:52:09 2009
@@ -304,16 +304,37 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
}
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 @@
}
/**
- * 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 @@
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 @@
/**
* 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 @@
/**
* 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 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 @@
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 @@
+ signatureVersion + EOL);
mainSection.removeAttribute(ATTRIBUTE_SIGNATURE_VERSION);
}
- mainSection.write(writer);
+ mainSection.write(writer, flatten);
// add it back
if (signatureVersion != null) {
@@ -946,7 +1045,7 @@
while (e.hasMoreElements()) {
String sectionName = (String) e.nextElement();
Section section = getSection(sectionName);
- section.write(writer);
+ section.write(writer, flatten);
}
}
Modified:
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ManifestTask.java Thu
Aug 20 13:52:09 2009
@@ -73,6 +73,16 @@
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.
*/
public static class Mode extends EnumeratedAttribute {
@@ -184,6 +194,25 @@
}
/**
+ * 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.
*
* @throws BuildException if the manifest cannot be written.
@@ -228,13 +257,13 @@
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 @@
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");
}
Modified: ant/core/trunk/src/tests/antunit/taskdefs/manifest-test.xml
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/tests/antunit/taskdefs/manifest-test.xml?rev=806174&r1=806173&r2=806174&view=diff
==============================================================================
--- ant/core/trunk/src/tests/antunit/taskdefs/manifest-test.xml (original)
+++ ant/core/trunk/src/tests/antunit/taskdefs/manifest-test.xml Thu Aug 20
13:52:09 2009
@@ -91,4 +91,49 @@
resource="${file}"
value="Class-Path: bar "/>
</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 "/>
+ <au:assertResourceContains
+ resource="${file}"
+ value="Class-Path: bar "/>
+ <au:assertResourceContains
+ resource="${file}"
+ value="Class-Path: baz "/>
+ </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 "/>
+ </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 "/>
+ </target>
</project>