diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java index cef230304..c60fa9102 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Jar.java +++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java @@ -71,7 +71,8 @@ public class Jar extends Zip { private File manifestFile; private Manifest manifest; private Manifest execManifest; - + private boolean buildFileManifest = false; + public Jar() { super(); archiveType = "jar"; @@ -83,6 +84,14 @@ public class Jar extends Zip { super.setZipfile(jarFile); } + public void addConfiguredManifest(Manifest newManifest) throws ManifestException { + if (manifest == null) { + manifest = getDefaultManifest(); + } + manifest.merge(newManifest); + buildFileManifest = true; + } + public void setManifest(File manifestFile) { if (!manifestFile.exists()) { throw new BuildException("Manifest file: " + manifestFile + " does not exist.", @@ -264,7 +273,35 @@ public class Jar extends Zip { */ protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException { // need to handle manifest as a special check - if (manifestFile != null && manifestFile.lastModified() > zipFile.lastModified()) { + if (buildFileManifest || manifestFile == null) { + java.util.zip.ZipFile theZipFile = null; + try { + theZipFile = new java.util.zip.ZipFile(zipFile); + java.util.zip.ZipEntry entry = theZipFile.getEntry("META-INF/MANIFEST.MF"); + if (entry == null) { + return false; + } + Manifest currentManifest = new Manifest(theZipFile.getInputStream(entry)); + if (!currentManifest.equals(manifest)) { + return false; + } + } + catch (Exception e) { + // any problems and we will rebuild + return false; + } + finally { + if (theZipFile != null) { + try { + theZipFile.close(); + } + catch (IOException e) { + //ignore + } + } + } + } + else if (manifestFile.lastModified() > zipFile.lastModified()) { return false; } return super.isUpToDate(scanners, zipFile); diff --git a/src/main/org/apache/tools/ant/taskdefs/Manifest.java b/src/main/org/apache/tools/ant/taskdefs/Manifest.java index ef74a5a37..947aa97b3 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Manifest.java +++ b/src/main/org/apache/tools/ant/taskdefs/Manifest.java @@ -57,6 +57,8 @@ package org.apache.tools.ant.taskdefs; import java.util.*; import java.io.*; +import org.apache.tools.ant.BuildException; + /** * Class to manage Manifest information * @@ -84,7 +86,7 @@ public class Manifest { /** * Class to hold manifest attributes */ - private class Attribute { + static public class Attribute { /** The attribute's name */ private String name = null; @@ -118,6 +120,17 @@ public class Manifest { this.value = value; } + public boolean equals(Object rhs) { + if (!(rhs instanceof Attribute)) { + return false; + } + + Attribute rhsAttribute = (Attribute)rhs; + return (name != null && rhsAttribute.name != null && + name.toLowerCase().equals(rhsAttribute.name.toLowerCase()) && + value != null && value.equals(rhsAttribute.value)); + } + /** * Parse a line into name and value pairs * @@ -214,7 +227,9 @@ public class Manifest { * Manifest. A section consists of a set of attribute values, * separated from other sections by a blank line. */ - private class Section { + static public class Section { + private Vector warnings = new Vector(); + /** The section's name if any. The main section in a manifest is unnamed.*/ private String name = null; @@ -266,7 +281,7 @@ public class Manifest { } else { attribute = new Attribute(line); - String nameReadAhead = addAttribute(attribute); + String nameReadAhead = addAttributeAndCheck(attribute); if (nameReadAhead != null) { return nameReadAhead; } @@ -292,6 +307,11 @@ public class Manifest { // the merge file always wins attributes.put(attributeName, section.attributes.get(attributeName)); } + + // add in the warnings + for (Enumeration e = section.warnings.elements(); e.hasMoreElements();) { + warnings.addElement(e.nextElement()); + } } /** @@ -337,6 +357,14 @@ public class Manifest { public void removeAttribute(String attributeName) { attributes.remove(attributeName.toLowerCase()); } + + public void addConfiguredAttribute(Attribute attribute) throws ManifestException { + String check = addAttributeAndCheck(attribute); + if (check != null) { + throw new BuildException("Use the \"name\" attribute of the
element rather than using " + + "the \"Name\" attribute"); + } + } /** * Add an attribute to the section @@ -347,7 +375,10 @@ public class Manifest { * * @throws ManifestException if the attribute already exists in this section. */ - public String addAttribute(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 " + @@ -368,7 +399,33 @@ public class Manifest { } return null; } - } + + public Enumeration getWarnings() { + return warnings.elements(); + } + + public boolean equals(Object rhs) { + if (!(rhs instanceof Section)) { + return false; + } + + Section rhsSection = (Section)rhs; + if (attributes.size() != rhsSection.attributes.size()) { + return false; + } + + for (Enumeration e = attributes.elements(); e.hasMoreElements();) { + Attribute attribute = (Attribute)e.nextElement(); + Attribute rshAttribute = (Attribute)rhsSection.attributes.get(attribute.getName().toLowerCase()); + if (!attribute.equals(rshAttribute)) { + return false; + } + } + + return true; + } + } + /** The version of this manifest */ private String manifestVersion = DEFAULT_MANIFEST_VERSION; @@ -379,9 +436,6 @@ public class Manifest { /** The named sections of this manifest */ private Hashtable sections = new Hashtable(); - /** Warnings for this manifest file */ - private Vector warnings = new Vector(); - /** Construct an empty manifest */ public Manifest() { } @@ -428,15 +482,26 @@ public class Manifest { // this line is the first attribute. set it and then let the normal // read handle the rest Attribute firstAttribute = new Attribute(line); - section.addAttribute(firstAttribute); + section.addAttributeAndCheck(firstAttribute); } section.setName(nextSectionName); nextSectionName = section.read(reader); - sections.put(section.getName().toLowerCase(), section); + addConfiguredSection(section); } } + public void addConfiguredSection(Section section) throws ManifestException { + if (section.getName() == null) { + throw new BuildException("Sections must have a name"); + } + sections.put(section.getName().toLowerCase(), section); + } + + public void addConfiguredAttribute(Attribute attribute) throws ManifestException { + mainSection.addConfiguredAttribute(attribute); + } + /** * Merge the contents of the given manifest into this manifest * @@ -460,10 +525,6 @@ public class Manifest { } } - // add in the warnings - for (Enumeration e = other.warnings.elements(); e.hasMoreElements();) { - warnings.addElement(e.nextElement()); - } } /** @@ -483,7 +544,7 @@ public class Manifest { mainSection.write(writer); if (signatureVersion != null) { try { - mainSection.addAttribute(new Attribute(ATTRIBUTE_SIGNATURE_VERSION, signatureVersion)); + mainSection.addConfiguredAttribute(new Attribute(ATTRIBUTE_SIGNATURE_VERSION, signatureVersion)); } catch (ManifestException e) { // shouldn't happen - ignore @@ -518,6 +579,48 @@ public class Manifest { * @return an enumeration of warning strings */ public Enumeration getWarnings() { + Vector warnings = new Vector(); + + for (Enumeration e2 = mainSection.getWarnings(); e2.hasMoreElements();) { + warnings.addElement(e2.nextElement()); + } + + // create a vector and add in the warnings for all the sections + for (Enumeration e = sections.elements(); e.hasMoreElements();) { + Section section = (Section)e.nextElement(); + for (Enumeration e2 = section.getWarnings(); e2.hasMoreElements();) { + warnings.addElement(e2.nextElement()); + } + } + return warnings.elements(); } + + public boolean equals(Object rhs) { + if (!(rhs instanceof Manifest)) { + return false; + } + + Manifest rhsManifest = (Manifest)rhs; + if (!manifestVersion.equals(rhsManifest.manifestVersion)) { + return false; + } + if (sections.size() != rhsManifest.sections.size()) { + return false; + } + + if (!mainSection.equals(rhsManifest.mainSection)) { + return false; + } + + for (Enumeration e = sections.elements(); e.hasMoreElements();) { + Section section = (Section)e.nextElement(); + Section rhsSection = (Section)rhsManifest.sections.get(section.getName().toLowerCase()); + if (!section.equals(rhsSection)) { + return false; + } + } + + return true; + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/Zip.java b/src/main/org/apache/tools/ant/taskdefs/Zip.java index 3070d3380..7691db47a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Zip.java +++ b/src/main/org/apache/tools/ant/taskdefs/Zip.java @@ -295,8 +295,9 @@ public class Zip extends MatchingTask { } finally { // Close the output stream. try { - if (zOut != null) - zOut.close (); + if (zOut != null) { + zOut.close(); + } } catch(IOException ex) { // If we're in this finally clause because of an exception, we don't // really care if there's an exception when closing the stream. E.g. if it @@ -317,7 +318,7 @@ public class Zip extends MatchingTask { } if (reallyDoUpdate) { - if (!renamedFile.renameTo (zipFile)) { + if (!renamedFile.renameTo(zipFile)) { msg+=" (and I couldn't rename the temporary file "+ renamedFile.getName()+" back)"; } @@ -327,11 +328,14 @@ public class Zip extends MatchingTask { } finally { cleanUp(); } + // If we've been successful on an update, delete the temporary file - if (success && reallyDoUpdate) - if (!renamedFile.delete()) - log ("Warning: unable to delete temporary file "+ + if (success && reallyDoUpdate) { + if (!renamedFile.delete()) { + log ("Warning: unable to delete temporary file " + renamedFile.getName(), Project.MSG_WARN); + } + } } /**