manifest file. PR: 5190 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270131 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -89,7 +89,8 @@ Other changes: | |||||
| * Added support for specifying CVS_RSH in the <cvs/> task | * Added support for specifying CVS_RSH in the <cvs/> task | ||||
| * New tasks bzip2 and bunzip2 to pack and unpack files using the | * New tasks bzip2 and bunzip2 to pack and unpack files using the | ||||
| BZip2 alogrithm, replaceregexp, checksum, translate, waitfor, input | |||||
| BZip2 alogrithm, replaceregexp, checksum, translate, waitfor, input, | |||||
| manifest | |||||
| * The attributes zipfile, jarfile, warfile and earfile (from the Zip, | * The attributes zipfile, jarfile, warfile and earfile (from the Zip, | ||||
| Jar, War and Ear tasks) have been deprecated and superseded by a | Jar, War and Ear tasks) have been deprecated and superseded by a | ||||
| @@ -0,0 +1,78 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <title>Manifest Task</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="manifest">Manifest</a></h2> | |||||
| <h3>Description</h3> | |||||
| <p>Creates a manifest file.</p> | |||||
| <p>This task can be used to write a Manifest file, optionally | |||||
| replacing or updating an existing file.</p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">file</td> | |||||
| <td valign="top">the manifest-file to create/update.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">mode</td> | |||||
| <td valign="top">One of "update" or "replace", default is "update".</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Nested elements</h3> | |||||
| <h4><a name="attribute">attribute</h4></h4> | |||||
| <p>One attribute for the manifest file. Those attributes that are | |||||
| not nested into a section will be added to the "Main" section.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">the name of the attribute.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">value</td> | |||||
| <td valign="top">the name of the attribute.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4>section</h4> | |||||
| <p>A manifest section - you can nest <a | |||||
| href="#attribute">attribute</a> elements into sections.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">the name of the section.</td> | |||||
| <td valign="top" align="center">No, if ommitted it will be assumed | |||||
| to be the main section.</td> | |||||
| </tr> | |||||
| </table> | |||||
| </body> | |||||
| </html> | |||||
| @@ -57,6 +57,7 @@ | |||||
| <a href="CoreTasks/javac.html">Javac</a><br> | <a href="CoreTasks/javac.html">Javac</a><br> | ||||
| <a href="CoreTasks/javadoc.html">Javadoc/<i>Javadoc2</i></a><br> | <a href="CoreTasks/javadoc.html">Javadoc/<i>Javadoc2</i></a><br> | ||||
| <a href="CoreTasks/mail.html">Mail</a><br> | <a href="CoreTasks/mail.html">Mail</a><br> | ||||
| <a href="CoreTasks/manifest.html">Manifest</a><br> | |||||
| <a href="CoreTasks/mkdir.html">Mkdir</a><br> | <a href="CoreTasks/mkdir.html">Mkdir</a><br> | ||||
| <a href="CoreTasks/move.html">Move</a><br> | <a href="CoreTasks/move.html">Move</a><br> | ||||
| <a href="CoreTasks/parallel.html">Parallel</a><br> | <a href="CoreTasks/parallel.html">Parallel</a><br> | ||||
| @@ -114,7 +114,7 @@ public class Jar extends Zip { | |||||
| public void addConfiguredManifest(Manifest newManifest) throws ManifestException { | public void addConfiguredManifest(Manifest newManifest) throws ManifestException { | ||||
| if (manifest == null) { | if (manifest == null) { | ||||
| manifest = getDefaultManifest(); | |||||
| manifest = Manifest.getDefaultManifest(); | |||||
| } | } | ||||
| manifest.merge(newManifest); | manifest.merge(newManifest); | ||||
| buildFileManifest = true; | buildFileManifest = true; | ||||
| @@ -133,7 +133,7 @@ public class Jar extends Zip { | |||||
| r = new FileReader(manifestFile); | r = new FileReader(manifestFile); | ||||
| Manifest newManifest = new Manifest(r); | Manifest newManifest = new Manifest(r); | ||||
| if (manifest == null) { | if (manifest == null) { | ||||
| manifest = getDefaultManifest(); | |||||
| manifest = Manifest.getDefaultManifest(); | |||||
| } | } | ||||
| manifest.merge(newManifest); | manifest.merge(newManifest); | ||||
| } | } | ||||
| @@ -166,7 +166,7 @@ public class Jar extends Zip { | |||||
| throws IOException, BuildException | throws IOException, BuildException | ||||
| { | { | ||||
| try { | try { | ||||
| execManifest = getDefaultManifest(); | |||||
| execManifest = Manifest.getDefaultManifest(); | |||||
| if (manifest != null) { | if (manifest != null) { | ||||
| execManifest.merge(manifest); | execManifest.merge(manifest); | ||||
| @@ -252,29 +252,6 @@ public class Jar extends Zip { | |||||
| private Manifest getDefaultManifest() { | |||||
| try { | |||||
| String s = "/org/apache/tools/ant/defaultManifest.mf"; | |||||
| InputStream in = this.getClass().getResourceAsStream(s); | |||||
| if (in == null) { | |||||
| throw new BuildException("Could not find default manifest: " + s); | |||||
| } | |||||
| try { | |||||
| return new Manifest(new InputStreamReader(in, "ASCII")); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| // impossible with ASCII encoding | |||||
| log("ASCII encoding not supported by JVM", Project.MSG_ERR); | |||||
| return new Manifest(new InputStreamReader(in)); | |||||
| } | |||||
| } | |||||
| catch (ManifestException e) { | |||||
| throw new BuildException("Default manifest is invalid !!"); | |||||
| } | |||||
| catch (IOException e) { | |||||
| throw new BuildException("Unable to read default manifest", e); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Handle situation when we encounter a manifest file | * Handle situation when we encounter a manifest file | ||||
| * | * | ||||
| @@ -352,7 +329,7 @@ public class Jar extends Zip { | |||||
| } | } | ||||
| Manifest currentManifest = new Manifest(new InputStreamReader(theZipFile.getInputStream(entry))); | Manifest currentManifest = new Manifest(new InputStreamReader(theZipFile.getInputStream(entry))); | ||||
| if (manifest == null) { | if (manifest == null) { | ||||
| manifest = getDefaultManifest(); | |||||
| manifest = Manifest.getDefaultManifest(); | |||||
| } | } | ||||
| if (!currentManifest.equals(manifest)) { | if (!currentManifest.equals(manifest)) { | ||||
| log("Updating jar since jar manifest has changed", Project.MSG_VERBOSE); | log("Updating jar since jar manifest has changed", Project.MSG_VERBOSE); | ||||
| @@ -57,20 +57,29 @@ package org.apache.tools.ant.taskdefs; | |||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import java.util.Hashtable; | import java.util.Hashtable; | ||||
| import java.util.Enumeration; | import java.util.Enumeration; | ||||
| import java.io.BufferedReader; | |||||
| import java.io.File; | |||||
| import java.io.FileReader; | |||||
| import java.io.FileWriter; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | |||||
| import java.io.InputStreamReader; | |||||
| import java.io.PrintWriter; | import java.io.PrintWriter; | ||||
| import java.io.BufferedReader; | |||||
| import java.io.Reader; | import java.io.Reader; | ||||
| import java.io.StringWriter; | import java.io.StringWriter; | ||||
| import java.io.UnsupportedEncodingException; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Task; | |||||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||||
| /** | /** | ||||
| * Class to manage Manifest information | * Class to manage Manifest information | ||||
| * | * | ||||
| * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | * @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | ||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| */ | */ | ||||
| public class Manifest { | |||||
| public class Manifest extends Task { | |||||
| /** The standard manifest version header */ | /** The standard manifest version header */ | ||||
| public final static String ATTRIBUTE_MANIFEST_VERSION = "Manifest-Version"; | public final static String ATTRIBUTE_MANIFEST_VERSION = "Manifest-Version"; | ||||
| @@ -92,6 +101,15 @@ public class Manifest { | |||||
| /** The max length of a line in a Manifest */ | /** The max length of a line in a Manifest */ | ||||
| public final static int MAX_LINE_LENGTH = 70; | public final static int MAX_LINE_LENGTH = 70; | ||||
| /** | |||||
| * Helper class for Manifest's mode attribute. | |||||
| */ | |||||
| public static class Mode extends EnumeratedAttribute { | |||||
| public String[] getValues() { | |||||
| return new String[] {"update", "replace"}; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Class to hold manifest attributes | * Class to hold manifest attributes | ||||
| */ | */ | ||||
| @@ -498,8 +516,34 @@ public class Manifest { | |||||
| /** The named sections of this manifest */ | /** The named sections of this manifest */ | ||||
| private Hashtable sections = new Hashtable(); | private Hashtable sections = new Hashtable(); | ||||
| /** | |||||
| * Construct a manifest from Ant's default manifest file. | |||||
| */ | |||||
| public static Manifest getDefaultManifest() throws BuildException { | |||||
| try { | |||||
| String s = "/org/apache/tools/ant/defaultManifest.mf"; | |||||
| InputStream in = Manifest.class.getResourceAsStream(s); | |||||
| if (in == null) { | |||||
| throw new BuildException("Could not find default manifest: " + s); | |||||
| } | |||||
| try { | |||||
| return new Manifest(new InputStreamReader(in, "ASCII")); | |||||
| } catch (UnsupportedEncodingException e) { | |||||
| return new Manifest(new InputStreamReader(in)); | |||||
| } | |||||
| } | |||||
| catch (ManifestException e) { | |||||
| throw new BuildException("Default manifest is invalid !!"); | |||||
| } | |||||
| catch (IOException e) { | |||||
| throw new BuildException("Unable to read default manifest", e); | |||||
| } | |||||
| } | |||||
| /** Construct an empty manifest */ | /** Construct an empty manifest */ | ||||
| public Manifest() { | public Manifest() { | ||||
| mode = new Mode(); | |||||
| mode.setValue("replace"); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -681,4 +725,73 @@ public class Manifest { | |||||
| return true; | return true; | ||||
| } | } | ||||
| private File manifestFile; | |||||
| /** | |||||
| * The name of the manifest file to write (if used as a task). | |||||
| */ | |||||
| public void setFile(File f) { | |||||
| manifestFile = f; | |||||
| } | |||||
| private Mode mode; | |||||
| /** | |||||
| * Shall we update or replace an existing manifest? | |||||
| */ | |||||
| public void setMode(Mode m) { | |||||
| mode = m; | |||||
| } | |||||
| /** | |||||
| * Create or update the Manifest when used as a task. | |||||
| */ | |||||
| public void execute() throws BuildException { | |||||
| if (manifestFile == null) { | |||||
| throw new BuildException("the file attribute is required"); | |||||
| } | |||||
| Manifest toWrite = getDefaultManifest(); | |||||
| if (mode.getValue().equals("update") && manifestFile.exists()) { | |||||
| FileReader f = null; | |||||
| try { | |||||
| f = new FileReader(manifestFile); | |||||
| toWrite.merge(new Manifest(f)); | |||||
| } catch (ManifestException m) { | |||||
| throw new BuildException("Existing manifest "+manifestFile | |||||
| + " is invalid", m, location); | |||||
| } catch (IOException e) { | |||||
| throw new BuildException("Failed to read "+manifestFile, | |||||
| e, location); | |||||
| } finally { | |||||
| if (f != null) { | |||||
| try { | |||||
| f.close(); | |||||
| } catch (IOException e) {} | |||||
| } | |||||
| } | |||||
| } | |||||
| try { | |||||
| toWrite.merge(this); | |||||
| } catch (ManifestException m) { | |||||
| throw new BuildException("Manifest is invalid", m, location); | |||||
| } | |||||
| PrintWriter w = null; | |||||
| try { | |||||
| w = new PrintWriter(new FileWriter(manifestFile)); | |||||
| toWrite.write(w); | |||||
| } catch (IOException e) { | |||||
| throw new BuildException("Failed to write "+manifestFile, | |||||
| e, location); | |||||
| } finally { | |||||
| if (w != null) { | |||||
| w.close(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -58,6 +58,7 @@ bunzip2=org.apache.tools.ant.taskdefs.BUnzip2 | |||||
| checksum=org.apache.tools.ant.taskdefs.Checksum | checksum=org.apache.tools.ant.taskdefs.Checksum | ||||
| waitfor=org.apache.tools.ant.taskdefs.WaitFor | waitfor=org.apache.tools.ant.taskdefs.WaitFor | ||||
| input=org.apache.tools.ant.taskdefs.Input | input=org.apache.tools.ant.taskdefs.Input | ||||
| manifest=org.apache.tools.ant.taskdefs.Manifest | |||||
| # optional tasks | # optional tasks | ||||
| script=org.apache.tools.ant.taskdefs.optional.Script | script=org.apache.tools.ant.taskdefs.optional.Script | ||||