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"/> | <jar file="mftest5.jar" manifest="manifests/test5.mf"/> | ||||
</target> | </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"> | <target name="clean"> | ||||
<delete> | <delete> | ||||
<fileset dir="." includes="mftest*.jar"/> | <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 */ | /** The Name Attribute is the first in a named section */ | ||||
public final static String ATTRIBUTE_NAME = "Name"; | 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"; | 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 */ | /** Default Manifest version if one is not specified */ | ||||
public final static String DEFAULT_MANIFEST_VERSION = "1.0"; | public final static String DEFAULT_MANIFEST_VERSION = "1.0"; | ||||
@@ -321,8 +324,19 @@ public class Manifest { | |||||
for (Enumeration e = section.attributes.keys(); e.hasMoreElements();) { | for (Enumeration e = section.attributes.keys(); e.hasMoreElements();) { | ||||
String attributeName = (String)e.nextElement(); | 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 | // add in the warnings | ||||
@@ -344,8 +358,18 @@ public class Manifest { | |||||
nameAttr.write(writer); | nameAttr.write(writer); | ||||
} | } | ||||
for (Enumeration e = attributes.elements(); e.hasMoreElements();) { | 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(); | writer.println(); | ||||
} | } | ||||
@@ -359,11 +383,21 @@ public class Manifest { | |||||
* in the section | * in the section | ||||
*/ | */ | ||||
public String getAttributeValue(String attributeName) { | public String getAttributeValue(String attributeName) { | ||||
Attribute attribute = (Attribute)attributes.get(attributeName.toLowerCase()); | |||||
Object attribute = attributes.get(attributeName.toLowerCase()); | |||||
if (attribute == null) { | if (attribute == null) { | ||||
return 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 \"" + | warnings.addElement("Manifest attributes should not start with \"" + | ||||
ATTRIBUTE_FROM + "\" in \"" +attribute.getName() + ": " + attribute.getValue() + "\""); | 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 { | 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; | return null; | ||||
} | } | ||||
@@ -213,7 +213,7 @@ public abstract class BuildFileTest extends TestCase { | |||||
executeTarget(target); | executeTarget(target); | ||||
} catch (org.apache.tools.ant.BuildException ex) { | } catch (org.apache.tools.ant.BuildException ex) { | ||||
if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) { | 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; | return; | ||||
} | } | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* The Apache Software License, Version 1.1 | * 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. | * reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
@@ -105,7 +105,7 @@ public class ManifestTest extends BuildFileTest { | |||||
public void test4() { | public void test4() { | ||||
expectBuildExceptionContaining("test4", "Manifest is invalid - section starts with continuation line", | expectBuildExceptionContaining("test4", "Manifest is invalid - section starts with continuation line", | ||||
"Invalid Manifest"); | "Invalid Manifest"); | ||||
} | |||||
} | |||||
/** | /** | ||||
* Malformed manifest - Name attribute in main section | * 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; | 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); | 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"); | |||||
} | |||||
} | } |