diff --git a/src/etc/testcases/taskdefs/manifest.xml b/src/etc/testcases/taskdefs/manifest.xml index d94db0822..33d7f995f 100644 --- a/src/etc/testcases/taskdefs/manifest.xml +++ b/src/etc/testcases/taskdefs/manifest.xml @@ -128,6 +128,42 @@ + + + +
+ + +
+
+ +
+
+
+ + + +
+ + + + +
+ +
+
+ + +
+
+
+ + + +
+ + + diff --git a/src/main/org/apache/tools/ant/taskdefs/Manifest.java b/src/main/org/apache/tools/ant/taskdefs/Manifest.java index dc56888a6..e8f6e0b31 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Manifest.java +++ b/src/main/org/apache/tools/ant/taskdefs/Manifest.java @@ -83,30 +83,37 @@ import org.apache.tools.ant.types.EnumeratedAttribute; */ public class Manifest extends Task { /** The standard manifest version header */ - public final static String ATTRIBUTE_MANIFEST_VERSION = "Manifest-Version"; + public static final String ATTRIBUTE_MANIFEST_VERSION + = "Manifest-Version"; /** The standard Signature Version header */ - public final static String ATTRIBUTE_SIGNATURE_VERSION = "Signature-Version"; + public static final String ATTRIBUTE_SIGNATURE_VERSION + = "Signature-Version"; /** The Name Attribute is the first in a named section */ - public final static String ATTRIBUTE_NAME = "Name"; + public static final String ATTRIBUTE_NAME = "Name"; /** The From Header is disallowed in a Manifest */ - public final static String ATTRIBUTE_FROM = "From"; + public static final String ATTRIBUTE_FROM = "From"; /** The Class-Path Header is special - it can be duplicated */ - public final static String ATTRIBUTE_CLASSPATH = "class-path"; + public static final String ATTRIBUTE_CLASSPATH = "class-path"; /** Default Manifest version if one is not specified */ - public final static String DEFAULT_MANIFEST_VERSION = "1.0"; + public static final String DEFAULT_MANIFEST_VERSION = "1.0"; /** The max length of a line in a Manifest */ - public final static int MAX_LINE_LENGTH = 72; + public static final int MAX_LINE_LENGTH = 72; /** * Helper class for Manifest's mode attribute. */ public static class Mode extends EnumeratedAttribute { + /** + * Get Allowed values for the mode attribute. + * + * @return a String array of the allowed values. + */ public String[] getValues() { return new String[] {"update", "replace"}; } @@ -120,8 +127,14 @@ public class Manifest extends Task { private String name = null; /** The attribute's value */ - private String value = null; + private Vector values = new Vector(); + /** + * For multivalued attributes, this is the index of the attribute + * currently being defined. + */ + private int currentIndex = 0; + /** * Construct an empty attribute */ public Attribute() { @@ -146,9 +159,12 @@ public class Manifest extends Task { */ public Attribute(String name, String value) { this.name = name; - this.value = value; + setValue(value); } + /** + * @see java.lang.Object#equals + */ public boolean equals(Object rhs) { if (!(rhs instanceof Attribute)) { return false; @@ -156,8 +172,8 @@ public class Manifest extends Task { Attribute rhsAttribute = (Attribute)rhs; return (name != null && rhsAttribute.name != null && - name.toLowerCase().equals(rhsAttribute.name.toLowerCase()) && - value != null && value.equals(rhsAttribute.value)); + getKey().equals(rhsAttribute.getKey()) && + values != null && values.equals(rhsAttribute.values)); } /** @@ -171,11 +187,12 @@ public class Manifest extends Task { public void parse(String line) throws ManifestException { int index = line.indexOf(": "); if (index == -1) { - throw new ManifestException("Manifest line \"" + line + "\" is not valid as it does not " + - "contain a name and a value separated by ': ' "); + throw new ManifestException("Manifest line \"" + line + + "\" is not valid as it does not " + + "contain a name and a value separated by ': ' "); } name = line.substring(0, index); - value = line.substring(index + 2); + setValue(line.substring(index + 2)); } /** @@ -196,13 +213,30 @@ public class Manifest extends Task { return name; } + /** + * Get the attribute's Key - its name in lower case. + * + * @return the attribute's key. + */ + public String getKey() { + if (name == null) { + return null; + } + return name.toLowerCase(); + } + /** * Set the Attribute's value * * @param value the attribute's value */ public void setValue(String value) { - this.value = value; + if (currentIndex >= values.size()) { + values.addElement(value); + currentIndex = values.size() - 1; + } else { + values.setElementAt(value, currentIndex); + } } /** @@ -211,18 +245,49 @@ public class Manifest extends Task { * @return the attribute's value. */ public String getValue() { - return value; + if (values.size() == 0) { + return null; + } + + String fullValue = ""; + for (Enumeration e = getValues(); e.hasMoreElements();) { + String value = (String)e.nextElement(); + fullValue += value + " "; + } + return fullValue.trim(); } + /** + * Add a new value to this attribute - making it multivalued + * + * @param value the attribute's additional value + */ + public void addValue(String value) { + currentIndex++; + setValue(value); + } + + /** + * Get all the attribute's values + * + * @return an enumeration of the attributes values + */ + public Enumeration getValues() { + return values.elements(); + } + /** * Add a continuation line from the Manifest file * * When lines are too long in a manifest, they are continued on the * next line by starting with a space. This method adds the continuation * data to the attribute value by skipping the first character. + * + * @param line the continuation line. */ public void addContinuation(String line) { - value += line.substring(1); + String currentValue = (String)values.elementAt(currentIndex); + setValue(currentValue + line.substring(1)); } /** @@ -233,17 +298,34 @@ public class Manifest extends Task { * @throws IOException if the attribte value cannot be written */ public void write(PrintWriter writer) throws IOException { + for (Enumeration e = getValues(); e.hasMoreElements();) { + writeValue(writer, (String)e.nextElement()); + } + } + + /** + * Write a single attribute value out + * + * @param writer the Writer to which the attribute is written + * @param value the attribute value + * + * @throws IOException if the attribte value cannot be written + */ + private void writeValue(PrintWriter writer, String value) + throws IOException { String line = name + ": " + value; while (line.getBytes().length > MAX_LINE_LENGTH) { // try to find a MAX_LINE_LENGTH byte section int breakIndex = MAX_LINE_LENGTH; String section = line.substring(0, breakIndex); - while (section.getBytes().length > MAX_LINE_LENGTH && breakIndex > 0) { + while (section.getBytes().length > MAX_LINE_LENGTH + && breakIndex > 0) { breakIndex--; section = line.substring(0, breakIndex); } if (breakIndex == 0) { - throw new IOException("Unable to write manifest line " + name + ": " + value); + throw new IOException("Unable to write manifest line " + + name + ": " + value); } writer.println(section); line = " " + line.substring(breakIndex); @@ -251,21 +333,28 @@ public class Manifest extends Task { writer.println(line); } } - + /** * Class to represent an individual section in the * Manifest. A section consists of a set of attribute values, * separated from other sections by a blank line. */ public static class Section { + /** Warnings for this section */ private Vector warnings = new Vector(); - /** The section's name if any. The main section in a manifest is unnamed.*/ + /** + * The section's name if any. The main section in a + * manifest is unnamed. + */ private String name = null; /** The section's attributes.*/ private Hashtable attributes = new Hashtable(); + /** Index used to retain the attribute ordering */ + private Vector attributeIndex = new Vector(); + /** * Set the Section's name * @@ -289,13 +378,16 @@ public class Manifest extends Task { * * @param reader the reader from which the section is read * - * @return the name of the next section if it has been read as part of this - * section - This only happens if the Manifest is malformed. + * @return the name of the next section if it has been read as + * part of this section - This only happens if the + * Manifest is malformed. * - * @throws ManifestException if the section is not valid according to the JAR spec + * @throws ManifestException if the section is not valid according + * to the JAR spec * @throws IOException if the section cannot be read from the reader. */ - public String read(BufferedReader reader) throws ManifestException, IOException { + public String read(BufferedReader reader) + throws ManifestException, IOException { Attribute attribute = null; while (true) { String line = reader.readLine(); @@ -306,19 +398,18 @@ public class Manifest extends Task { // continuation line if (attribute == null) { if (name != null) { - // a continuation on the first line is a continuation of the name - concatenate - // this line and the name + // a continuation on the first line is a + // continuation of the name - concatenate this + // line and the name name += line.substring(1); + } else { + throw new ManifestException("Can't start an " + + "attribute with a continuation line " + line); } - else { - throw new ManifestException("Can't start an attribute with a continuation line " + line); - } - } - else { + } else { attribute.addContinuation(line); } - } - else { + } else { attribute = new Attribute(line); String nameReadAhead = addAttributeAndCheck(attribute); if (nameReadAhead != null) { @@ -336,31 +427,35 @@ public class Manifest extends Task { * @throws ManifestException if the sections cannot be merged. */ public void merge(Section section) throws ManifestException { - if (name == null && section.getName() != null || - name != null && !(name.equalsIgnoreCase(section.getName()))) { - throw new ManifestException("Unable to merge sections with different names"); + if (name == null && section.getName() != null + || name != null + && !(name.equalsIgnoreCase(section.getName()))) { + throw new ManifestException("Unable to merge sections " + + "with different names"); } - for (Enumeration e = section.attributes.keys(); e.hasMoreElements();) { + Enumeration e = section.getAttributeKeys(); + while (e.hasMoreElements()) { String attributeName = (String)e.nextElement(); + Attribute attribute = section.getAttribute(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()); + Attribute ourClassPath = getAttribute(attributeName); + Enumeration cpe = attribute.getValues(); + while (cpe.hasMoreElements()) { + String value = (String)cpe.nextElement(); + ourClassPath.addValue(value); } - } - else { + } else { // the merge file always wins - attributes.put(attributeName, section.attributes.get(attributeName)); + storeAttribute(attribute); } } // add in the warnings - for (Enumeration e = section.warnings.elements(); e.hasMoreElements();) { - warnings.addElement(e.nextElement()); + Enumeration warnEnum = section.warnings.elements(); + while (warnEnum.hasMoreElements()) { + warnings.addElement(warnEnum.nextElement()); } } @@ -376,19 +471,11 @@ public class Manifest extends Task { Attribute nameAttr = new Attribute(ATTRIBUTE_NAME, name); nameAttr.write(writer); } - for (Enumeration e = attributes.elements(); e.hasMoreElements();) { - 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); - } - } + Enumeration e = getAttributeKeys(); + while (e.hasMoreElements()) { + String key = (String)e.nextElement(); + Attribute attribute = getAttribute(key); + attribute.write(writer); } writer.println(); } @@ -401,10 +488,20 @@ public class Manifest extends Task { * single-valued, otherwise a Vector of Manifest.Attribute * instances. */ - public Object getAttribute(String attributeName) { - return attributes.get(attributeName.toLowerCase()); + public Attribute getAttribute(String attributeName) { + return (Attribute)attributes.get(attributeName.toLowerCase()); } + /** + * Get the attribute keys. + * + * @return an Enumeration of Strings, each string being the lower case + * key of an attribute of the section. + */ + public Enumeration getAttributeKeys() { + return attributeIndex.elements(); + } + /** * Get the value of the attribute with the name given. * @@ -414,21 +511,11 @@ public class Manifest extends Task { * in the section */ public String getAttributeValue(String attributeName) { - Object attribute = attributes.get(attributeName.toLowerCase()); + Attribute attribute = getAttribute(attributeName.toLowerCase()); if (attribute == null) { return null; } - 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(); - } + return attribute.getValue(); } /** @@ -437,14 +524,25 @@ public class Manifest extends Task { * @param attributeName the name of the attribute to be removed. */ public void removeAttribute(String attributeName) { - attributes.remove(attributeName.toLowerCase()); + String key = attributeName.toLowerCase(); + attributes.remove(key); + attributeIndex.removeElement(key); } - public void addConfiguredAttribute(Attribute attribute) throws ManifestException { + /** + * Add an attribute to the section. + * + * @param attribute the attribute to be added to the section + * + * @exception ManifestException if the attribute is not valid. + */ + public void addConfiguredAttribute(Attribute attribute) + throws ManifestException { String check = addAttributeAndCheck(attribute); if (check != null) { - throw new BuildException("Specify the section name using the \"name\" attribute of the
element rather " + - "than using a \"Name\" manifest attribute"); + throw new BuildException("Specify the section name using " + + "the \"name\" attribute of the
element rather " + + "than using a \"Name\" manifest attribute"); } } @@ -453,51 +551,84 @@ public class Manifest extends Task { * * @param attribute the attribute to be added. * - * @return the value of the attribute if it is a name attribute - null other wise + * @return the value of the attribute if it is a name + * attribute - null other wise * - * @throws ManifestException if the attribute already exists in this section. + * @exception ManifestException if the attribute already + * exists in this section. */ - public String addAttributeAndCheck(Attribute attribute) throws ManifestException { + public String addAttributeAndCheck(Attribute attribute) + throws ManifestException { if (attribute.getName() == null || attribute.getValue() == null) { throw new BuildException("Attributes must have name and value"); } - if (attribute.getName().equalsIgnoreCase(ATTRIBUTE_NAME)) { - warnings.addElement("\"" + ATTRIBUTE_NAME + "\" attributes should not occur in the " + - "main section and must be the first element in all " + - "other sections: \"" +attribute.getName() + ": " + attribute.getValue() + "\""); + if (attribute.getKey().equalsIgnoreCase(ATTRIBUTE_NAME)) { + warnings.addElement("\"" + ATTRIBUTE_NAME + "\" attributes " + + "should not occur in the main section and must be the " + + "first element in all other sections: \"" + + attribute.getName() + ": " + attribute.getValue() + "\""); return attribute.getValue(); } - if (attribute.getName().toLowerCase().startsWith(ATTRIBUTE_FROM.toLowerCase())) { - warnings.addElement("Manifest attributes should not start with \"" + - ATTRIBUTE_FROM + "\" in \"" +attribute.getName() + ": " + attribute.getValue() + "\""); - } - else { + if (attribute.getKey().startsWith(ATTRIBUTE_FROM.toLowerCase())) { + warnings.addElement("Manifest attributes should not start " + + "with \"" + ATTRIBUTE_FROM + "\" in \"" + + attribute.getName() + ": " + attribute.getValue() + "\""); + } else { // 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); + String attributeKey = attribute.getKey(); + if (attributeKey.equals(ATTRIBUTE_CLASSPATH)) { + Attribute classpathAttribute = + (Attribute)attributes.get(attributeKey); + + if (classpathAttribute == null) { + storeAttribute(attribute); + } else { + Enumeration e = attribute.getValues(); + while (e.hasMoreElements()) { + String value = (String)e.nextElement(); + classpathAttribute.addValue(value); + } } - 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); + } else if (attributes.containsKey(attributeKey)) { + throw new ManifestException("The attribute \"" + + attribute.getName() + "\" may not occur more " + + "than once in the same section"); + } else { + storeAttribute(attribute); } } return null; } + + /** + * Store an attribute and update the index. + * + * @param attribute the attribute to be stored + */ + private void storeAttribute(Attribute attribute) { + if (attribute == null) { + return; + } + String attributeKey = attribute.getKey(); + attributes.put(attributeKey, attribute); + if (!attributeIndex.contains(attributeKey)) { + attributeIndex.addElement(attributeKey); + } + } + /** + * Get the warnings for this section. + * + * @return an Enumeration of warning strings. + */ public Enumeration getWarnings() { return warnings.elements(); } + /** + * @see java.lang.Object#equals + */ public boolean equals(Object rhs) { if (!(rhs instanceof Section)) { return false; @@ -511,7 +642,8 @@ public class Manifest extends Task { for (Enumeration e = attributes.keys(); e.hasMoreElements();) { String attributeName = (String)e.nextElement(); Object attributeValue = attributes.get(attributeName); - Object rshAttributeValue = rhsSection.attributes.get(attributeName); + Object rshAttributeValue + = rhsSection.attributes.get(attributeName); if (!attributeValue.equals(rshAttributeValue)) { return false; } @@ -531,26 +663,43 @@ public class Manifest extends Task { /** The named sections of this manifest */ private Hashtable sections = new Hashtable(); + /** Index of sections - used to retain order of sections in manifest */ + private Vector sectionIndex = new Vector(); + + /** + * The file to which the manifest should be written when used as a task + */ + private File manifestFile; + + /** + * The mode with which the manifest file is written + */ + private Mode mode; + /** * Construct a manifest from Ant's default manifest file. + * + * + * @return the default manifest. + * @exception BuildException if there is a problem loading the + * default manifest */ public static Manifest getDefaultManifest() throws BuildException { try { - String s = "/org/apache/tools/ant/defaultManifest.mf"; - InputStream in = Manifest.class.getResourceAsStream(s); + String defManifest = "/org/apache/tools/ant/defaultManifest.mf"; + InputStream in = Manifest.class.getResourceAsStream(defManifest); if (in == null) { - throw new BuildException("Could not find default manifest: " + s); + throw new BuildException("Could not find default manifest: " + + defManifest); } try { return new Manifest(new InputStreamReader(in, "ASCII")); } catch (UnsupportedEncodingException e) { return new Manifest(new InputStreamReader(in)); } - } - catch (ManifestException e) { + } catch (ManifestException e) { throw new BuildException("Default manifest is invalid !!", e); - } - catch (IOException e) { + } catch (IOException e) { throw new BuildException("Unable to read default manifest", e); } } @@ -565,16 +714,18 @@ public class Manifest extends Task { /** * Read a manifest file from the given reader * - * @param is the reader from which the Manifest is read + * @param r is the reader from which the Manifest is read * - * @throws ManifestException if the manifest is not valid according to the JAR spec + * @throws ManifestException if the manifest is not valid according + * to the JAR spec * @throws IOException if the manifest cannot be read from the reader. */ public Manifest(Reader r) throws ManifestException, IOException { BufferedReader reader = new BufferedReader(r); // This should be the manifest version String nextSectionName = mainSection.read(reader); - String readManifestVersion = mainSection.getAttributeValue(ATTRIBUTE_MANIFEST_VERSION); + String readManifestVersion + = mainSection.getAttributeValue(ATTRIBUTE_MANIFEST_VERSION); if (readManifestVersion != null) { manifestVersion = readManifestVersion; mainSection.removeAttribute(ATTRIBUTE_MANIFEST_VERSION); @@ -590,15 +741,16 @@ public class Manifest extends Task { if (nextSectionName == null) { Attribute sectionName = new Attribute(line); if (!sectionName.getName().equalsIgnoreCase(ATTRIBUTE_NAME)) { - throw new ManifestException("Manifest sections should start with a \"" + ATTRIBUTE_NAME + - "\" attribute and not \"" + sectionName.getName() + "\""); + throw new ManifestException("Manifest sections should " + + "start with a \"" + ATTRIBUTE_NAME + + "\" attribute and not \"" + + sectionName.getName() + "\""); } nextSectionName = sectionName.getValue(); - } - else { + } else { // we have already started reading this section - // this line is the first attribute. set it and then let the normal - // read handle the rest + // this line is the first attribute. set it and then + // let the normal read handle the rest Attribute firstAttribute = new Attribute(line); section.addAttributeAndCheck(firstAttribute); } @@ -609,14 +761,34 @@ public class Manifest extends Task { } } - public void addConfiguredSection(Section section) throws ManifestException { - if (section.getName() == null) { + /** + * Add a section to the manifest + * + * @param section the manifest section to be added + * + * @exception ManifestException if the secti0on is not valid. + */ + public void addConfiguredSection(Section section) + throws ManifestException { + String sectionName = section.getName(); + if (sectionName == null) { throw new BuildException("Sections must have a name"); } - sections.put(section.getName(), section); + sections.put(sectionName, section); + if (!sectionIndex.contains(sectionName)) { + sectionIndex.addElement(sectionName); + } } - public void addConfiguredAttribute(Attribute attribute) throws ManifestException { + /** + * Add an attribute to the manifest - it is added to the main section. + * + * @param attribute the attribute to be added. + * + * @exception ManifestException if the attribute is not valid. + */ + public void addConfiguredAttribute(Attribute attribute) + throws ManifestException { mainSection.addConfiguredAttribute(attribute); } @@ -625,8 +797,8 @@ public class Manifest extends Task { * * @param other the Manifest to be merged with this one. * - * @throws ManifestException if there is a problem merging the manfest according - * to the Manifest spec. + * @throws ManifestException if there is a problem merging the + * manfest according to the Manifest spec. */ public void merge(Manifest other) throws ManifestException { merge(other, false); @@ -636,17 +808,18 @@ public class Manifest extends Task { * 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 overwriteMain whether to overwrite the main section + * of the current manifest * - * @throws ManifestException if there is a problem merging the manfest according - * to the Manifest spec. + * @throws ManifestException if there is a problem merging the + * manfest according to the Manifest spec. */ - public void merge(Manifest other, boolean overwriteMain) throws ManifestException { + public void merge(Manifest other, boolean overwriteMain) + throws ManifestException { if (other != null) { if (overwriteMain) { mainSection = other.mainSection; - } - else { + } else { mainSection.merge(other.mainSection); } @@ -654,16 +827,17 @@ public class Manifest extends Task { manifestVersion = other.manifestVersion; } - for (Enumeration e = other.sections.keys(); e.hasMoreElements();) { + Enumeration e = other.getSectionNames(); + while (e.hasMoreElements()) { String sectionName = (String)e.nextElement(); Section ourSection = (Section)sections.get(sectionName); - Section otherSection = (Section)other.sections.get(sectionName); + Section otherSection + = (Section)other.sections.get(sectionName); if (ourSection == null) { if (otherSection != null) { - sections.put(sectionName.toLowerCase(), otherSection); + addConfiguredSection(otherSection); } - } - else { + } else { ourSection.merge(otherSection); } } @@ -679,23 +853,30 @@ public class Manifest extends Task { */ public void write(PrintWriter writer) throws IOException { writer.println(ATTRIBUTE_MANIFEST_VERSION + ": " + manifestVersion); - String signatureVersion = mainSection.getAttributeValue(ATTRIBUTE_SIGNATURE_VERSION); + String signatureVersion + = mainSection.getAttributeValue(ATTRIBUTE_SIGNATURE_VERSION); if (signatureVersion != null) { - writer.println(ATTRIBUTE_SIGNATURE_VERSION + ": " + signatureVersion); + writer.println(ATTRIBUTE_SIGNATURE_VERSION + ": " + + signatureVersion); mainSection.removeAttribute(ATTRIBUTE_SIGNATURE_VERSION); } mainSection.write(writer); + + // add it back if (signatureVersion != null) { try { - mainSection.addConfiguredAttribute(new Attribute(ATTRIBUTE_SIGNATURE_VERSION, signatureVersion)); - } - catch (ManifestException e) { + Attribute svAttr = new Attribute(ATTRIBUTE_SIGNATURE_VERSION, + signatureVersion); + mainSection.addConfiguredAttribute(svAttr); + } catch (ManifestException e) { // shouldn't happen - ignore } } - for (Enumeration e = sections.elements(); e.hasMoreElements();) { - Section section = (Section)e.nextElement(); + Enumeration e = sectionIndex.elements(); + while (e.hasMoreElements()) { + String sectionName = (String)e.nextElement(); + Section section = getSection(sectionName); section.write(writer); } } @@ -703,14 +884,14 @@ public class Manifest extends Task { /** * Convert the manifest to its string representation * - * @return a multiline string with the Manifest as it appears in a Manifest file. + * @return a multiline string with the Manifest as it + * appears in a Manifest file. */ public String toString() { StringWriter sw = new StringWriter(); try { write(new PrintWriter(sw)); - } - catch (IOException e) { + } catch (IOException e) { return null; } return sw.toString(); @@ -724,14 +905,17 @@ public class Manifest extends Task { public Enumeration getWarnings() { Vector warnings = new Vector(); - for (Enumeration e2 = mainSection.getWarnings(); e2.hasMoreElements();) { - warnings.addElement(e2.nextElement()); + Enumeration warnEnum = mainSection.getWarnings(); + while (warnEnum.hasMoreElements()) { + warnings.addElement(warnEnum.nextElement()); } // create a vector and add in the warnings for all the sections - for (Enumeration e = sections.elements(); e.hasMoreElements();) { + Enumeration e = sections.elements(); + while (e.hasMoreElements()) { Section section = (Section)e.nextElement(); - for (Enumeration e2 = section.getWarnings(); e2.hasMoreElements();) { + Enumeration e2 = section.getWarnings(); + while (e2.hasMoreElements()) { warnings.addElement(e2.nextElement()); } } @@ -739,6 +923,9 @@ public class Manifest extends Task { return warnings.elements(); } + /** + * @see java.lang.Object#equals + */ public boolean equals(Object rhs) { if (!(rhs instanceof Manifest)) { return false; @@ -760,9 +947,11 @@ public class Manifest extends Task { return false; } - for (Enumeration e = sections.elements(); e.hasMoreElements();) { + Enumeration e = sections.elements(); + while (e.hasMoreElements()) { Section section = (Section)e.nextElement(); - Section rhsSection = (Section)rhsManifest.sections.get(section.getName()); + Section rhsSection + = (Section)rhsManifest.sections.get(section.getName()); if (!section.equals(rhsSection)) { return false; } @@ -771,19 +960,19 @@ public class Manifest extends Task { return true; } - private File manifestFile; - /** * The name of the manifest file to write (if used as a task). + * + * @param f the Manifest file to be written */ public void setFile(File f) { manifestFile = f; } - private Mode mode; - /** * Shall we update or replace an existing manifest? + * + * @param m the mode value - update or replace. */ public void setMode(Mode m) { mode = m; @@ -824,11 +1013,13 @@ public class Manifest extends Task { * @return an Enumeration of section names */ public Enumeration getSectionNames() { - return sections.keys(); + return sectionIndex.elements(); } /** * Create or update the Manifest when used as a task. + * + * @throws BuildException if the manifst cannot be written. */ public void execute() throws BuildException { if (manifestFile == null) { @@ -843,10 +1034,10 @@ public class Manifest extends Task { f = new FileReader(manifestFile); toWrite.merge(new Manifest(f)); } catch (ManifestException m) { - throw new BuildException("Existing manifest "+manifestFile + throw new BuildException("Existing manifest " + manifestFile + " is invalid", m, location); } catch (IOException e) { - throw new BuildException("Failed to read "+manifestFile, + throw new BuildException("Failed to read " + manifestFile, e, location); } finally { if (f != null) { @@ -868,7 +1059,7 @@ public class Manifest extends Task { w = new PrintWriter(new FileWriter(manifestFile)); toWrite.write(w); } catch (IOException e) { - throw new BuildException("Failed to write "+manifestFile, + throw new BuildException("Failed to write " + manifestFile, e, location); } finally { if (w != null) { diff --git a/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java b/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java index b519bed86..24c7a7925 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/ManifestTest.java @@ -59,6 +59,7 @@ import java.io.FileReader; import java.io.IOException; import java.util.Date; import java.util.Vector; +import java.util.Enumeration; import org.apache.tools.ant.BuildFileTest; import org.apache.tools.ant.Project; @@ -222,8 +223,6 @@ public class ManifestTest extends BuildFileTest { String classpath = mainSection.getAttributeValue("class-path"); assertEquals("Class-Path attribute was not set correctly - ", "Test1 Test2 Test3 Test4", classpath); - Object classPathAttr = mainSection.getAttribute("class-PATH"); - assertTrue("Class path attribute should be a Vector", classPathAttr instanceof Vector); } /** @@ -241,6 +240,52 @@ public class ManifestTest extends BuildFileTest { LONG_LINE, classpath); } + /** + * Tests ordering of sections + */ + public void testOrder1() throws IOException, ManifestException { + executeTarget("testOrder1"); + + Manifest manifest = getManifest(EXPANDED_MANIFEST); + Enumeration e = manifest.getSectionNames(); + String section1 = (String)e.nextElement(); + String section2 = (String)e.nextElement(); + assertEquals("First section name unexpected", "Test1", section1); + assertEquals("Second section name unexpected", "Test2", section2); + + Manifest.Section section = manifest.getSection("Test1"); + e = section.getAttributeKeys(); + String attr1Key = (String)e.nextElement(); + String attr2Key = (String)e.nextElement(); + String attr1 = section.getAttribute(attr1Key).getName(); + String attr2 = section.getAttribute(attr2Key).getName(); + assertEquals("First attribute name unexpected", "TestAttr1", attr1); + assertEquals("Second attribute name unexpected", "TestAttr2", attr2); + } + + /** + * Tests ordering of sections + */ + public void testOrder2() throws IOException, ManifestException { + executeTarget("testOrder2"); + + Manifest manifest = getManifest(EXPANDED_MANIFEST); + Enumeration e = manifest.getSectionNames(); + String section1 = (String)e.nextElement(); + String section2 = (String)e.nextElement(); + assertEquals("First section name unexpected", "Test2", section1); + assertEquals("Second section name unexpected", "Test1", section2); + + Manifest.Section section = manifest.getSection("Test1"); + e = section.getAttributeKeys(); + String attr1Key = (String)e.nextElement(); + String attr2Key = (String)e.nextElement(); + String attr1 = section.getAttribute(attr1Key).getName(); + String attr2 = section.getAttribute(attr2Key).getName(); + assertEquals("First attribute name unexpected", "TestAttr2", attr1); + assertEquals("Second attribute name unexpected", "TestAttr1", attr2); + } + /** * file attribute for manifest task is required. */