Fixed problem with multiple class-path attributes. Hopefully Sun will update their spec sometime. PR: 4683 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269921 13f79535-47bb-0310-9956-ffa450edef68master
@@ -24,6 +24,82 @@ | |||
<jar file="mftest5.jar" manifest="manifests/test5.mf"/> | |||
</target> | |||
<target name="test6"> | |||
<jar file="mftest6.jar" manifest="manifests/test6.mf"/> | |||
</target> | |||
<target name="test7"> | |||
<jar file="mftest7.jar" manifest="manifests/test7.mf"/> | |||
</target> | |||
<target name="test8"> | |||
<jar file="mftest8.jar"> | |||
<manifest> | |||
<attribute name="Class-Path" value="fubar"/> | |||
<section name="Test"> | |||
<attribute name="TestAttr" value="Test"/> | |||
</section> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test9"> | |||
<jar file="mftest9.jar"> | |||
<manifest> | |||
<attribute name="Class-Path" value="fubar"/> | |||
<section name="Test"> | |||
<attribute name="Name" value="Test"/> | |||
</section> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test10"> | |||
<jar file="mftest10.jar"> | |||
<manifest> | |||
<attribute value="fubar"/> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test11"> | |||
<jar file="mftest11.jar"> | |||
<manifest> | |||
<attribute name="Test"/> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test12"> | |||
<jar file="mftest12.jar"> | |||
<manifest> | |||
<section> | |||
<attribute name="TestAttr" value="Test"/> | |||
</section> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test13"> | |||
<jar file="mftest13.jar"> | |||
<manifest> | |||
<attribute name="Test" value="Test1"/> | |||
<attribute name="Test" value="Test2"/> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="test14"> | |||
<jar file="mftest14.jar"> | |||
<manifest> | |||
<attribute name="Class-path" value="Test1"/> | |||
<attribute name="Class-path" value="Test2"/> | |||
<attribute name="Class-Path" value="Test3"/> | |||
<attribute name="class-Path" value="Test4"/> | |||
</manifest> | |||
</jar> | |||
</target> | |||
<target name="clean"> | |||
<delete> | |||
<fileset dir="." includes="mftest*.jar"/> | |||
@@ -0,0 +1,5 @@ | |||
Manifest-Version: 1.0 | |||
Test: test6 | |||
Class-Path: fubar | |||
@@ -0,0 +1,4 @@ | |||
Manifest-Version: 1.0 | |||
Class-Path: fubar | |||
From: Jack | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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 <section> 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"); | |||
} | |||
} |