diff --git a/src/etc/testcases/taskdefs/manifest.xml b/src/etc/testcases/taskdefs/manifest.xml
index 844766698..148f05804 100644
--- a/src/etc/testcases/taskdefs/manifest.xml
+++ b/src/etc/testcases/taskdefs/manifest.xml
@@ -24,6 +24,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/etc/testcases/taskdefs/manifests/test6.mf b/src/etc/testcases/taskdefs/manifests/test6.mf
new file mode 100644
index 000000000..97988c698
--- /dev/null
+++ b/src/etc/testcases/taskdefs/manifests/test6.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+
+Test: test6
+Class-Path: fubar
+
diff --git a/src/etc/testcases/taskdefs/manifests/test7.mf b/src/etc/testcases/taskdefs/manifests/test7.mf
new file mode 100644
index 000000000..72aace0ba
--- /dev/null
+++ b/src/etc/testcases/taskdefs/manifests/test7.mf
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Class-Path: fubar
+From: Jack
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/Manifest.java b/src/main/org/apache/tools/ant/taskdefs/Manifest.java
index 697724390..06fc8e563 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Manifest.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Manifest.java
@@ -81,9 +81,12 @@ public class Manifest {
/** The Name Attribute is the first in a named section */
public final static String ATTRIBUTE_NAME = "Name";
- /** THe From Header is disallowed in a Manifest */
+ /** The From Header is disallowed in a Manifest */
public final static String ATTRIBUTE_FROM = "From";
+ /** The Class-Path Header is special - it can be duplicated */
+ public final static String ATTRIBUTE_CLASSPATH = "class-path";
+
/** Default Manifest version if one is not specified */
public final static String DEFAULT_MANIFEST_VERSION = "1.0";
@@ -321,8 +324,19 @@ public class Manifest {
for (Enumeration e = section.attributes.keys(); e.hasMoreElements();) {
String attributeName = (String)e.nextElement();
- // the merge file always wins
- attributes.put(attributeName, section.attributes.get(attributeName));
+ if (attributeName.equals(ATTRIBUTE_CLASSPATH) &&
+ attributes.containsKey(attributeName)) {
+ // classpath entries are vetors which are merged
+ Vector classpathAttrs = (Vector)section.attributes.get(attributeName);
+ Vector ourClasspathAttrs = (Vector)attributes.get(attributeName);
+ for (Enumeration e2 = classpathAttrs.elements(); e2.hasMoreElements();) {
+ ourClasspathAttrs.addElement(e2.nextElement());
+ }
+ }
+ else {
+ // the merge file always wins
+ attributes.put(attributeName, section.attributes.get(attributeName));
+ }
}
// add in the warnings
@@ -344,8 +358,18 @@ public class Manifest {
nameAttr.write(writer);
}
for (Enumeration e = attributes.elements(); e.hasMoreElements();) {
- Attribute attribute = (Attribute)e.nextElement();
- attribute.write(writer);
+ Object object = e.nextElement();
+ if (object instanceof Attribute) {
+ Attribute attribute = (Attribute)object;
+ attribute.write(writer);
+ }
+ else {
+ Vector attrList = (Vector)object;
+ for (Enumeration e2 = attrList.elements(); e2.hasMoreElements();) {
+ Attribute attribute = (Attribute)e2.nextElement();
+ attribute.write(writer);
+ }
+ }
}
writer.println();
}
@@ -359,11 +383,21 @@ public class Manifest {
* in the section
*/
public String getAttributeValue(String attributeName) {
- Attribute attribute = (Attribute)attributes.get(attributeName.toLowerCase());
+ Object attribute = attributes.get(attributeName.toLowerCase());
if (attribute == null) {
return null;
}
- return attribute.getValue();
+ if (attribute instanceof Attribute) {
+ return ((Attribute)attribute).getValue();
+ }
+ else {
+ String value = "";
+ for (Enumeration e = ((Vector)attribute).elements(); e.hasMoreElements();) {
+ Attribute classpathAttribute = (Attribute)e.nextElement();
+ value += classpathAttribute.getValue() + " ";
+ }
+ return value.trim();
+ }
}
/**
@@ -407,12 +441,24 @@ public class Manifest {
warnings.addElement("Manifest attributes should not start with \"" +
ATTRIBUTE_FROM + "\" in \"" +attribute.getName() + ": " + attribute.getValue() + "\"");
}
- else if (attributes.containsKey(attribute.getName().toLowerCase())) {
- throw new ManifestException("The attribute \"" + attribute.getName() + "\" may not " +
- "occur more than once in the same section");
- }
else {
- attributes.put(attribute.getName().toLowerCase(), attribute);
+ // classpath attributes go into a vector
+ String attributeName = attribute.getName().toLowerCase();
+ if (attributeName.equals(ATTRIBUTE_CLASSPATH)) {
+ Vector classpathAttrs = (Vector)attributes.get(attributeName);
+ if (classpathAttrs == null) {
+ classpathAttrs = new Vector();
+ attributes.put(attributeName, classpathAttrs);
+ }
+ classpathAttrs.addElement(attribute);
+ }
+ else if (attributes.containsKey(attributeName)) {
+ throw new ManifestException("The attribute \"" + attribute.getName() + "\" may not " +
+ "occur more than once in the same section");
+ }
+ else {
+ attributes.put(attributeName, attribute);
+ }
}
return null;
}
diff --git a/src/testcases/org/apache/tools/ant/BuildFileTest.java b/src/testcases/org/apache/tools/ant/BuildFileTest.java
index 26d89989e..47ea8dbdb 100644
--- a/src/testcases/org/apache/tools/ant/BuildFileTest.java
+++ b/src/testcases/org/apache/tools/ant/BuildFileTest.java
@@ -213,7 +213,7 @@ public abstract class BuildFileTest extends TestCase {
executeTarget(target);
} catch (org.apache.tools.ant.BuildException ex) {
if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) {
- fail("Should throw BuildException because '" + cause + "' with message containing'" + contains + "' (actual message '" + ex.getMessage() + "' instead)");
+ fail("Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + ex.getMessage() + "' instead)");
}
return;
}
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java b/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java
index ec96fb481..1eadbbe92 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -105,7 +105,7 @@ public class ManifestTest extends BuildFileTest {
public void test4() {
expectBuildExceptionContaining("test4", "Manifest is invalid - section starts with continuation line",
"Invalid Manifest");
- }
+ }
/**
* Malformed manifest - Name attribute in main section
@@ -116,4 +116,81 @@ public class ManifestTest extends BuildFileTest {
boolean hasWarning = output.indexOf("Manifest warning: \"Name\" attributes should not occur in the main section") != -1;
assertEquals("Expected warning about Name in main section", true, hasWarning);
}
+
+ /**
+ * New Section not starting with Name attribute.
+ */
+ public void test6() {
+ expectBuildExceptionContaining("test6", "Manifest is invalid - section starts with incorrect attribute",
+ "Invalid Manifest");
+ String output = getLog();
+ boolean hasWarning = output.indexOf("Manifest sections should start with a \"Name\" attribute") != -1;
+ assertEquals("Expected warning about section not starting with Name: attribute", true, hasWarning);
+ }
+
+ /**
+ * From attribute is illegal
+ */
+ public void test7() {
+ executeTarget("test7");
+
+ boolean hasWarning = getLog().indexOf("Manifest attributes should not start with \"From\"") != -1;
+ assertEquals("Expected warning about From: attribute", true, hasWarning);
+ }
+
+ /**
+ * Inline manifest - OK
+ */
+ public void test8() {
+ executeTarget("test8");
+ }
+
+ /**
+ * Inline manifest - Invalid since has a Name attribute in the section element
+ */
+ public void test9() {
+ expectBuildExceptionContaining("test9", "Construction is invalid - Name attribute should not be used",
+ "Specify the section name using the \"name\" attribute of the element");
+ }
+
+ /**
+ * Inline manifest - Invalid attribute without name
+ */
+ public void test10() {
+ expectBuildExceptionContaining("test10", "Attribute has no name",
+ "Attributes must have name and value");
+ }
+
+ /**
+ * Inline manifest - Invalid attribute without value
+ */
+ public void test11() {
+ expectBuildExceptionContaining("test11", "Attribute has no value",
+ "Attributes must have name and value");
+ }
+
+ /**
+ * Inline manifest - Invalid attribute without value
+ */
+ public void test12() {
+ expectBuildExceptionContaining("test12", "Section with no name",
+ "Sections must have a name");
+ }
+
+ /**
+ * Inline manifest - Duplicate attribute
+ */
+ public void test13() {
+ expectBuildExceptionContaining("test13", "Duplicate Attribute",
+ "The attribute \"Test\" may not occur more than once in the same section");
+ }
+
+ /**
+ * Inline manifest - OK since classpath entries can be duplicated.
+ */
+ public void test14() {
+ executeTarget("test14");
+ }
+
+
}