It also removes a number of small errors in zip task. Deprecated <prefixedfileset> element of war in favour of normal <fileset> element in zip Submitted By: "Rosen, Alex" <arosen@silverstream.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268344 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -2725,6 +2725,11 @@ You should not include <samp>META-INF/MANIFEST.MF</samp> in your set of files. | |||||
| If <code>create</code> (the default), the JAR is created anyway with only a manifest. | If <code>create</code> (the default), the JAR is created anyway with only a manifest. | ||||
| If <code>skip</code>, the JAR is not created and a warning is issued. | If <code>skip</code>, the JAR is not created and a warning is issued. | ||||
| If <code>fail</code>, the JAR is not created and the build is halted with an error. | If <code>fail</code>, the JAR is not created and the build is halted with an error. | ||||
| <p>(The Jar task is a shortcut for specifying the manifest file of a JAR file. | |||||
| The same thing can be accomplished by using the <i>fullpath</i> | |||||
| attribute of the filesets in a Zip task. The one difference is that if the | |||||
| <i>manifest</i> attribute is not specified, the Jar task will | |||||
| include an empty one for you.)</p> | |||||
| </p> | </p> | ||||
| <h3>Parameters</h3> | <h3>Parameters</h3> | ||||
| <table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
| @@ -2791,13 +2796,13 @@ If <code>fail</code>, the JAR is not created and the build is halted with an err | |||||
| </table> | </table> | ||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| <pre> <jar jarfile="${dist}/lib/app.jar" basedir="${build}/classes" /></pre> | <pre> <jar jarfile="${dist}/lib/app.jar" basedir="${build}/classes" /></pre> | ||||
| <p>jars all files in the <code>${build}/classes</code> directory in a file | |||||
| <p>jars all files in the <code>${build}/classes</code> directory into a file | |||||
| called <code>app.jar</code> in the <code>${dist}/lib</code> directory.</p> | called <code>app.jar</code> in the <code>${dist}/lib</code> directory.</p> | ||||
| <pre> <jar jarfile="${dist}/lib/app.jar" | <pre> <jar jarfile="${dist}/lib/app.jar" | ||||
| basedir="${build}/classes" | basedir="${build}/classes" | ||||
| excludes="**/Test.class" | excludes="**/Test.class" | ||||
| /></pre> | /></pre> | ||||
| <p>jars all files in the <code>${build}/classes</code> directory in a file | |||||
| <p>jars all files in the <code>${build}/classes</code> directory into a file | |||||
| called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Files | called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Files | ||||
| with the name <code>Test.class</code> are excluded.</p> | with the name <code>Test.class</code> are excluded.</p> | ||||
| <pre> <jar jarfile="${dist}/lib/app.jar" | <pre> <jar jarfile="${dist}/lib/app.jar" | ||||
| @@ -2805,7 +2810,7 @@ with the name <code>Test.class</code> are excluded.</p> | |||||
| includes="mypackage/test/**" | includes="mypackage/test/**" | ||||
| excludes="**/Test.class" | excludes="**/Test.class" | ||||
| /></pre> | /></pre> | ||||
| <p>jars all files in the <code>${build}/classes</code> directory in a file | |||||
| <p>jars all files in the <code>${build}/classes</code> directory into a file | |||||
| called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Only | called <code>app.jar</code> in the <code>${dist}/lib</code> directory. Only | ||||
| files under the directory <code>mypackage/test</code> are used, and files with | files under the directory <code>mypackage/test</code> are used, and files with | ||||
| the name <code>Test.class</code> are excluded.</p> | the name <code>Test.class</code> are excluded.</p> | ||||
| @@ -2816,7 +2821,7 @@ the name <code>Test.class</code> are excluded.</p> | |||||
| <fileset dir="${src}/resources"/> | <fileset dir="${src}/resources"/> | ||||
| </jar></pre> | </jar></pre> | ||||
| <p>jars all files in the <code>${build}/classes</code> directory and also | <p>jars all files in the <code>${build}/classes</code> directory and also | ||||
| in the <code>${src}/resources</code> directory together in a file | |||||
| in the <code>${src}/resources</code> directory together into a file | |||||
| called <code>app.jar</code> in the <code>${dist}/lib</code> directory. | called <code>app.jar</code> in the <code>${dist}/lib</code> directory. | ||||
| Files with the name <code>Test.class</code> are excluded. | Files with the name <code>Test.class</code> are excluded. | ||||
| If there are files such as <code>${build}/classes/mypackage/MyClass.class</code> | If there are files such as <code>${build}/classes/mypackage/MyClass.class</code> | ||||
| @@ -4434,14 +4439,14 @@ task to come up with a .tar.gz package.</p> | |||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| <pre> <tar tarfile="${dist}/manual.tar" basedir="htdocs/manual" /> | <pre> <tar tarfile="${dist}/manual.tar" basedir="htdocs/manual" /> | ||||
| <gzip zipfile="${dist}/manual.tar.gz" src="${dist}/manual.tar" /></pre> | <gzip zipfile="${dist}/manual.tar.gz" src="${dist}/manual.tar" /></pre> | ||||
| <p>tars all files in the <code>htdocs/manual</code> directory in a file called <code>manual.tar</code> | |||||
| <p>tars all files in the <code>htdocs/manual</code> directory into a file called <code>manual.tar</code> | |||||
| in the <code>${dist}</code> directory, then applies the gzip task to compress | in the <code>${dist}</code> directory, then applies the gzip task to compress | ||||
| it.</p> | it.</p> | ||||
| <pre> <tar tarfile="${dist}/manual.tar" | <pre> <tar tarfile="${dist}/manual.tar" | ||||
| basedir="htdocs/manual" | basedir="htdocs/manual" | ||||
| excludes="mydocs/**, **/todo.html" | excludes="mydocs/**, **/todo.html" | ||||
| /></pre> | /></pre> | ||||
| <p>tars all files in the <code>htdocs/manual</code> directory in a file called <code>manual.tar</code> | |||||
| <p>tars all files in the <code>htdocs/manual</code> directory into a file called <code>manual.tar</code> | |||||
| in the <code>${dist}</code> directory. Files in the directory <code>mydocs</code>, | in the <code>${dist}</code> directory. Files in the directory <code>mydocs</code>, | ||||
| or files with the name <code>todo.html</code> are excluded.</p> | or files with the name <code>todo.html</code> are excluded.</p> | ||||
| <hr> | <hr> | ||||
| @@ -4779,10 +4784,10 @@ carried from tarfile.</p> | |||||
| <p>An extension of the <a href="#jar">Jar</a> task with special | <p>An extension of the <a href="#jar">Jar</a> task with special | ||||
| treatment for files that should end up in the | treatment for files that should end up in the | ||||
| <code>WEB-INF/lib</code>, <code>WEB-INF/classes</code> or | <code>WEB-INF/lib</code>, <code>WEB-INF/classes</code> or | ||||
| <code>WEB-INF</code> directories of the Web Application Archive. It | |||||
| also gives you more control over where your files end up in the | |||||
| archive by means of its nested <code>prefixedfileset</code> | |||||
| element.</p> | |||||
| <code>WEB-INF</code> directories of the Web Application Archive. | |||||
| <p>(The War task is a shortcut for specifying the particular layout of a WAR file. | |||||
| The same thing can be accomplished by using the <i>prefix</i> and <i>fullpath</i> | |||||
| attributes of the filesets in a Zip or Jar task.)</p> | |||||
| <h3>Parameters</h3> | <h3>Parameters</h3> | ||||
| <table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
| <tr> | <tr> | ||||
| @@ -4866,60 +4871,6 @@ href="#fileset">FileSet</a>. All files included in this fileset will | |||||
| end up in the <code>WEB-INF</code> directory of the war file. If this | end up in the <code>WEB-INF</code> directory of the war file. If this | ||||
| fileset includes a file named <code>web.xml</code>, the file is | fileset includes a file named <code>web.xml</code>, the file is | ||||
| ignored and you will get a warning.</p> | ignored and you will get a warning.</p> | ||||
| <h4>prefixedfileset</h4> | |||||
| <p>The nested <code>prefixedfileset</code> element specifies a <a | |||||
| href="#fileset">FileSet</a> with an additional prefix attribute. All | |||||
| files included in this fileset will end up in the <em>prefix</em> | |||||
| directory of the war file, where <em>prefix</em> is the value of the | |||||
| <code>prefix</code> attribute.</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">prefix</td> | |||||
| <td valign="top">The prefix directory to add to each filename when | |||||
| adding it to the archive. Default is none.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">dir</td> | |||||
| <td valign="top">The root of the directory tree of this FileSet.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">defaultexcludes</td> | |||||
| <td valign="top">indicates whether default excludes should be used or not | |||||
| ("yes"/"no"). Default excludes are used when omitted.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">includes</td> | |||||
| <td valign="top">comma separated list of patterns of files that must be | |||||
| included. All files are included when omitted.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">includesfile</td> | |||||
| <td valign="top">the name of a file. Each line of this file is | |||||
| taken to be an include pattern</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">excludes</td> | |||||
| <td valign="top">comma separated list of patterns of files that must be | |||||
| excluded. No files (except default excludes) are excluded when omitted.</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">excludesfile</td> | |||||
| <td valign="top">the name of a file. Each line of this file is | |||||
| taken to be an exclude pattern</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| <p>Assume the following structure in the project's base directory: | <p>Assume the following structure in the project's base directory: | ||||
| <pre> | <pre> | ||||
| @@ -4941,7 +4892,7 @@ then the war file <code>myapp.war</code> created with | |||||
| <exclude name="jdbc1.jar" /> | <exclude name="jdbc1.jar" /> | ||||
| </lib> | </lib> | ||||
| <classes dir="build/main" /> | <classes dir="build/main" /> | ||||
| <prefixedfileset dir="src/graphics/images/gifs" | |||||
| <fileset dir="src/graphics/images/gifs" | |||||
| prefix="images"/> | prefix="images"/> | ||||
| </war> | </war> | ||||
| </pre> | </pre> | ||||
| @@ -4986,6 +4937,13 @@ if <code>basedir</code> is set. You may use any mixture of the implicit file set | |||||
| and optional subelements like <code><include></code>); explicit nested | and optional subelements like <code><include></code>); explicit nested | ||||
| <code><fileset></code> elements so long as at least one fileset total is specified. The ZIP file will | <code><fileset></code> elements so long as at least one fileset total is specified. The ZIP file will | ||||
| only reflect the relative paths of files <em>within</em> each fileset.</p> | only reflect the relative paths of files <em>within</em> each fileset.</p> | ||||
| <p>Inside of <code><zip></code> elements, nested filesets may include one of two special attributes: | |||||
| <i>prefix</i> or <i>fullpath</i>. These attributes modify the location of the files when they are placed | |||||
| inside the archive. If the <i>prefix</i> attribute is set, all the files in the fileset are prefixed | |||||
| with that path in the archive. If the <i>fullpath</i> attribute is set, the file described by the filset is placed at that | |||||
| exact location in the archive. (The <i>fullpath</i> attribute can only be set for filesets that | |||||
| represent a single file. The <i>prefix</i> and <i>fullpath</i> attributes cannot both be set on the | |||||
| same fileset.)</p> | |||||
| <p>The <code>whenempty</code> parameter controls what happens when no files match. | <p>The <code>whenempty</code> parameter controls what happens when no files match. | ||||
| If <code>skip</code> (the default), the ZIP is not created and a warning is issued. | If <code>skip</code> (the default), the ZIP is not created and a warning is issued. | ||||
| If <code>fail</code>, the ZIP is not created and the build is halted with an error. | If <code>fail</code>, the ZIP is not created and the build is halted with an error. | ||||
| @@ -5053,31 +5011,36 @@ which should be recognized as such by compliant ZIP manipulation tools.</p> | |||||
| <pre> <zip zipfile="${dist}/manual.zip" | <pre> <zip zipfile="${dist}/manual.zip" | ||||
| basedir="htdocs/manual" | basedir="htdocs/manual" | ||||
| /></pre> | /></pre> | ||||
| <p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | |||||
| <p>zips all files in the <code>htdocs/manual</code> directory into a file called <code>manual.zip</code> | |||||
| in the <code>${dist}</code> directory.</p> | in the <code>${dist}</code> directory.</p> | ||||
| <pre> <zip zipfile="${dist}/manual.zip" | <pre> <zip zipfile="${dist}/manual.zip" | ||||
| basedir="htdocs/manual" | basedir="htdocs/manual" | ||||
| excludes="mydocs/**, **/todo.html" | excludes="mydocs/**, **/todo.html" | ||||
| /></pre> | /></pre> | ||||
| <p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | |||||
| in the <code>${dist}</code> directory. Files in the directory <code>mydocs</code>, | |||||
| <p>zips all files in the <code>htdocs/manual</code> directory. Files in the directory <code>mydocs</code>, | |||||
| or files with the name <code>todo.html</code> are excluded.</p> | or files with the name <code>todo.html</code> are excluded.</p> | ||||
| <pre> <zip zipfile="${dist}/manual.zip" | <pre> <zip zipfile="${dist}/manual.zip" | ||||
| basedir="htdocs/manual" | basedir="htdocs/manual" | ||||
| includes="api/**/*.html" | includes="api/**/*.html" | ||||
| excludes="**/todo.html" | excludes="**/todo.html" | ||||
| /></pre> | /></pre> | ||||
| <p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | |||||
| in the <code>${dist}</code> directory. Only html files under the directory <code>api</code> | |||||
| <p>zips all files in the <code>htdocs/manual</code> directory. Only html files under the directory <code>api</code> | |||||
| are zipped, and files with the name <code>todo.html</code> are excluded.</p> | are zipped, and files with the name <code>todo.html</code> are excluded.</p> | ||||
| <pre> <zip zipfile="${dist}/manual.zip"> | <pre> <zip zipfile="${dist}/manual.zip"> | ||||
| <fileset dir="htdocs/manual"/> | <fileset dir="htdocs/manual"/> | ||||
| <fileset dir="." includes="ChangeLog.txt"/> | <fileset dir="." includes="ChangeLog.txt"/> | ||||
| </zip></pre> | </zip></pre> | ||||
| <p>zips all files in the <code>htdocs/manual</code> directory in a file called <code>manual.zip</code> | |||||
| in the <code>${dist}</code> directory, and also adds the file <code>ChangeLog.txt</code> in the | |||||
| <p>zips all files in the <code>htdocs/manual</code> directory, and also adds the file <code>ChangeLog.txt</code> in the | |||||
| current directory. <code>ChangeLog.txt</code> will be added to the top of the ZIP file, just as if | current directory. <code>ChangeLog.txt</code> will be added to the top of the ZIP file, just as if | ||||
| it had been located at <code>htdocs/manual/ChangeLog.txt</code>.</p> | it had been located at <code>htdocs/manual/ChangeLog.txt</code>.</p> | ||||
| <pre> <zip zipfile="${dist}/manual.zip"> | |||||
| <fileset dir="htdocs/manual" prefix="docs/user-guide"/> | |||||
| <fileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/> | |||||
| </zip></pre> | |||||
| <p>zips all files in the <code>htdocs/manual</code> directory into the <code>docs/user-guide</code> directory | |||||
| in the archive, and also adds the file <code>ChangeLog27.txt</code> in the | |||||
| current directory as <code>docs/ChangeLog.txt</code>. For example, the archive might end up containing two files: | |||||
| <code>docs/user-guide/html/index.html</code> and <code>docs/ChangeLog.txt</code></p> | |||||
| <hr> | <hr> | ||||
| <h2><a name="optionaltasks">Optional tasks</a></h2> | <h2><a name="optionaltasks">Optional tasks</a></h2> | ||||
| @@ -5188,7 +5151,7 @@ supports all attributes of <code><fileset></code> | |||||
| basedir="htdocs/manual" | basedir="htdocs/manual" | ||||
| /> | /> | ||||
| </pre></blockquote> | </pre></blockquote> | ||||
| <p>cabs all files in the htdocs/manual directory in a file called | |||||
| <p>cabs all files in the htdocs/manual directory into a file called | |||||
| manual.cab in the ${dist} directory.</p> | manual.cab in the ${dist} directory.</p> | ||||
| <blockquote><pre> | <blockquote><pre> | ||||
| <cab cabfile="${dist}/manual.cab" | <cab cabfile="${dist}/manual.cab" | ||||
| @@ -5196,7 +5159,7 @@ manual.cab in the ${dist} directory.</p> | |||||
| excludes="mydocs/**, **/todo.html" | excludes="mydocs/**, **/todo.html" | ||||
| /> | /> | ||||
| </pre></blockquote> | </pre></blockquote> | ||||
| <p>cabs all files in the htdocs/manual directory in a file called | |||||
| <p>cabs all files in the htdocs/manual directory into a file called | |||||
| manual.cab in the ${dist} directory. Files in the directory mydocs, | manual.cab in the ${dist} directory. Files in the directory mydocs, | ||||
| or files with the name todo.html are excluded.</p> | or files with the name todo.html are excluded.</p> | ||||
| <blockquote><pre> | <blockquote><pre> | ||||
| @@ -5207,7 +5170,7 @@ or files with the name todo.html are excluded.</p> | |||||
| verbose="yes" | verbose="yes" | ||||
| /> | /> | ||||
| </pre></blockquote> | </pre></blockquote> | ||||
| <p>cab all files in the htdocs/manual directory in a file called | |||||
| <p>cab all files in the htdocs/manual directory into a file called | |||||
| manual.cab in the ${dist} directory. Only html files under the | manual.cab in the ${dist} directory. Only html files under the | ||||
| directory api are archived, and files with the name todo.html are | directory api are archived, and files with the name todo.html are | ||||
| excluded. Output from the cabarc tool is displayed in the build | excluded. Output from the cabarc tool is displayed in the build | ||||
| @@ -68,35 +68,45 @@ import java.util.zip.*; | |||||
| public class Jar extends Zip { | public class Jar extends Zip { | ||||
| private File manifest; | private File manifest; | ||||
| private boolean manifestAdded; | |||||
| public Jar() { | public Jar() { | ||||
| super(); | super(); | ||||
| archiveType = "jar"; | archiveType = "jar"; | ||||
| emptyBehavior = "create"; | emptyBehavior = "create"; | ||||
| } | } | ||||
| public void execute() { | |||||
| if (manifest != null && !manifest.exists()) | |||||
| throw new BuildException("Manifest file: " + manifest + " does not exists."); | |||||
| super.execute(); | |||||
| } | |||||
| public void setJarfile(File jarFile) { | public void setJarfile(File jarFile) { | ||||
| super.setZipfile(jarFile); | super.setZipfile(jarFile); | ||||
| } | } | ||||
| /** | |||||
| * Adds a set of files (nested fileset attribute). | |||||
| */ | |||||
| public void addPrefixedfileset(PrefixedFileSet set) { | |||||
| log("Warning: Prefixfileset is a deprecated feature. The fileset subelement can be used in it's place", Project.MSG_WARN); | |||||
| addFileset(set); | |||||
| } | |||||
| public void setManifest(File manifestFile) { | public void setManifest(File manifestFile) { | ||||
| manifest = manifestFile; | manifest = manifestFile; | ||||
| if (!manifest.exists()) | |||||
| throw new BuildException("Manifest file: " + manifest + " does not exist."); | |||||
| // Create a PrefixedFileSet for this file, and pass it up. | |||||
| PrefixedFileSet fs = new PrefixedFileSet(); | |||||
| fs.setDir(new File(manifest.getParent())); | |||||
| fs.setIncludes(manifest.getName()); | |||||
| fs.setFullpath("META-INF/MANIFEST.MF"); | |||||
| super.addFileset(fs); | |||||
| } | } | ||||
| protected void initZipOutputStream(ZipOutputStream zOut) | protected void initZipOutputStream(ZipOutputStream zOut) | ||||
| throws IOException, BuildException | throws IOException, BuildException | ||||
| { | { | ||||
| // add manifest first | |||||
| if (manifest != null) { | |||||
| zipDir(new File(manifest.getParent()), zOut, "META-INF/"); | |||||
| super.zipFile(manifest, zOut, "META-INF/MANIFEST.MF"); | |||||
| } else { | |||||
| // If no manifest is specified, add the default one. | |||||
| if (manifest == null) { | |||||
| String s = "/org/apache/tools/ant/defaultManifest.mf"; | String s = "/org/apache/tools/ant/defaultManifest.mf"; | ||||
| InputStream in = this.getClass().getResourceAsStream(s); | InputStream in = this.getClass().getResourceAsStream(s); | ||||
| if ( in == null ) | if ( in == null ) | ||||
| @@ -104,53 +114,27 @@ public class Jar extends Zip { | |||||
| zipDir(null, zOut, "META-INF/"); | zipDir(null, zOut, "META-INF/"); | ||||
| zipFile(in, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | zipFile(in, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | ||||
| } | } | ||||
| } | |||||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException | |||||
| { | |||||
| File[] files = grabFiles(scanners); | |||||
| if (manifest != null) { | |||||
| // just add the manifest file to the mix | |||||
| DirectoryScanner ds = new DirectoryScanner(); | |||||
| ds.setBasedir(new File(manifest.getParent())); | |||||
| ds.setIncludes(new String[] {manifest.getName()}); | |||||
| ds.scan(); | |||||
| FileScanner[] myScanners = new FileScanner[scanners.length+1]; | |||||
| System.arraycopy(scanners, 0, myScanners, 0, scanners.length); | |||||
| myScanners[scanners.length] = ds; | |||||
| boolean retval = super.isUpToDate(myScanners, zipFile); | |||||
| if (!retval && files.length == 0) { | |||||
| log("Note: creating empty "+archiveType+" archive " + zipFile, | |||||
| Project.MSG_INFO); | |||||
| } | |||||
| return retval; | |||||
| } else if (emptyBehavior.equals("create") && files.length == 0) { | |||||
| log("Note: creating empty "+archiveType+" archive " + zipFile, | |||||
| Project.MSG_INFO); | |||||
| return false; | |||||
| } else { | |||||
| // all other cases are handled correctly by Zip's method | |||||
| return super.isUpToDate(scanners, zipFile); | |||||
| } | |||||
| super.initZipOutputStream(zOut); | |||||
| } | } | ||||
| protected void zipFile(File file, ZipOutputStream zOut, String vPath) | protected void zipFile(File file, ZipOutputStream zOut, String vPath) | ||||
| throws IOException | throws IOException | ||||
| { | { | ||||
| // We already added a META-INF/MANIFEST.MF | |||||
| if (!vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| // If the file being added is META-INF/MANIFEST.MF, we warn if it's not the | |||||
| // one specified in the "manifest" attribute - or if it's being added twice, | |||||
| // meaning the same file is specified by the "manifeset" attribute and in | |||||
| // a <fileset> element. | |||||
| if (vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) { | |||||
| if (manifest == null || !manifest.equals(file) || manifestAdded) { | |||||
| log("Warning: selected "+archiveType+" files include a META-INF/MANIFEST.MF which will be ignored " + | |||||
| "(please use manifest attribute to "+archiveType+" task)", Project.MSG_WARN); | |||||
| } else { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| manifestAdded = true; | |||||
| } | |||||
| } else { | } else { | ||||
| log("Warning: selected "+archiveType+" files include a META-INF/MANIFEST.MF which will be ignored " + | |||||
| "(please use manifest attribute to "+archiveType+" task)", Project.MSG_WARN); | |||||
| super.zipFile(file, zOut, vPath); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -69,10 +69,7 @@ import java.util.zip.*; | |||||
| public class War extends Jar { | public class War extends Jar { | ||||
| private File deploymentDescriptor; | private File deploymentDescriptor; | ||||
| private Vector libFileSets = new Vector(); | |||||
| private Vector classesFileSets = new Vector(); | |||||
| private Vector webInfFileSets = new Vector(); | |||||
| private boolean descriptorAdded; | |||||
| public War() { | public War() { | ||||
| super(); | super(); | ||||
| @@ -85,85 +82,64 @@ public class War extends Jar { | |||||
| } | } | ||||
| public void setWebxml(File descr) { | public void setWebxml(File descr) { | ||||
| deploymentDescriptor = descr; | |||||
| deploymentDescriptor = descr; | |||||
| if (!deploymentDescriptor.exists()) | |||||
| throw new BuildException("Deployment descriptor: " + deploymentDescriptor + " does not exist."); | |||||
| // Create a PrefixedFileSet for this file, and pass it up. | |||||
| PrefixedFileSet fs = new PrefixedFileSet(); | |||||
| fs.setDir(new File(deploymentDescriptor.getParent())); | |||||
| fs.setIncludes(deploymentDescriptor.getName()); | |||||
| fs.setFullpath("WEB-INF/web.xml"); | |||||
| super.addFileset(fs); | |||||
| } | } | ||||
| public void addLib(FileSet fs) { | |||||
| libFileSets.addElement(fs); | |||||
| public void addLib(PrefixedFileSet fs) { | |||||
| // We just set the prefix for this fileset, and pass it up. | |||||
| fs.setPrefix("WEB-INF/lib/"); | |||||
| super.addFileset(fs); | |||||
| } | } | ||||
| public void addClasses(FileSet fs) { | |||||
| classesFileSets.addElement(fs); | |||||
| public void addClasses(PrefixedFileSet fs) { | |||||
| // We just set the prefix for this fileset, and pass it up. | |||||
| fs.setPrefix("WEB-INF/classes/"); | |||||
| super.addFileset(fs); | |||||
| } | } | ||||
| public void addWebinf(FileSet fs) { | |||||
| webInfFileSets.addElement(fs); | |||||
| public void addWebinf(PrefixedFileSet fs) { | |||||
| // We just set the prefix for this fileset, and pass it up. | |||||
| fs.setPrefix("WEB-INF/"); | |||||
| super.addFileset(fs); | |||||
| } | } | ||||
| /** | |||||
| * Add the deployment descriptor as well as all files added the | |||||
| * special way of nested lib, classes or webinf filesets. | |||||
| */ | |||||
| protected void initZipOutputStream(ZipOutputStream zOut) | protected void initZipOutputStream(ZipOutputStream zOut) | ||||
| throws IOException, BuildException | throws IOException, BuildException | ||||
| { | { | ||||
| // add deployment descriptor first | |||||
| if (deploymentDescriptor != null) { | |||||
| zipDir(new File(deploymentDescriptor.getParent()), zOut, | |||||
| "WEB-INF/"); | |||||
| super.zipFile(deploymentDescriptor, zOut, "WEB-INF/web.xml"); | |||||
| } else { | |||||
| throw new BuildException("webxml attribute is required", location); | |||||
| } | |||||
| addFiles(libFileSets, zOut, "WEB-INF/lib/"); | |||||
| addFiles(classesFileSets, zOut, "WEB-INF/classes/"); | |||||
| addFiles(webInfFileSets, zOut, "WEB-INF/"); | |||||
| super.initZipOutputStream(zOut); | |||||
| } | |||||
| protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException | |||||
| { | |||||
| // If no webxml file is specified, it's an error. | |||||
| if (deploymentDescriptor == null) { | if (deploymentDescriptor == null) { | ||||
| throw new BuildException("webxml attribute is required", location); | throw new BuildException("webxml attribute is required", location); | ||||
| } | } | ||||
| // just add some Scanners for our filesets and web.xml and let | |||||
| // Jar/Zip do the rest of the work | |||||
| FileScanner[] myScanners = new FileScanner[scanners.length | |||||
| + 1 // web.xml | |||||
| + libFileSets.size() | |||||
| + classesFileSets.size() | |||||
| + webInfFileSets.size()]; | |||||
| System.arraycopy(scanners, 0, myScanners, 0, scanners.length); | |||||
| DirectoryScanner ds = new DirectoryScanner(); | |||||
| ds.setBasedir(new File(deploymentDescriptor.getParent())); | |||||
| ds.setIncludes(new String[] {deploymentDescriptor.getName()}); | |||||
| ds.scan(); | |||||
| myScanners[scanners.length] = ds; | |||||
| addScanners(myScanners, scanners.length+1, libFileSets); | |||||
| addScanners(myScanners, scanners.length+1+libFileSets.size(), | |||||
| classesFileSets); | |||||
| addScanners(myScanners, scanners.length+1+libFileSets.size()+classesFileSets.size(), | |||||
| webInfFileSets); | |||||
| return super.isUpToDate(myScanners, zipFile); | |||||
| super.initZipOutputStream(zOut); | |||||
| } | } | ||||
| protected void zipFile(File file, ZipOutputStream zOut, String vPath) | protected void zipFile(File file, ZipOutputStream zOut, String vPath) | ||||
| throws IOException | throws IOException | ||||
| { | { | ||||
| // We already added a WEB-INF/web.xml | |||||
| if (!vPath.equalsIgnoreCase("WEB-INF/web.xml")) { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| // If the file being added is WEB-INF/web.xml, we warn if it's not the | |||||
| // one specified in the "webxml" attribute - or if it's being added twice, | |||||
| // meaning the same file is specified by the "webxml" attribute and in | |||||
| // a <fileset> element. | |||||
| if (vPath.equalsIgnoreCase("WEB-INF/web.xml")) { | |||||
| if (deploymentDescriptor == null || !deploymentDescriptor.equals(file) || descriptorAdded) { | |||||
| log("Warning: selected "+archiveType+" files include a WEB-INF/web.xml which will be ignored " + | |||||
| "(please use webxml attribute to "+archiveType+" task)", Project.MSG_WARN); | |||||
| } else { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| descriptorAdded = true; | |||||
| } | |||||
| } else { | } else { | ||||
| log("Warning: selected "+archiveType+" files include a WEB-INF/web.xml which will be ignored " + | |||||
| "(please use webxml attribute to "+archiveType+" task)", Project.MSG_WARN); | |||||
| super.zipFile(file, zOut, vPath); | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -82,8 +82,7 @@ public class Zip extends MatchingTask { | |||||
| protected String emptyBehavior = "skip"; | protected String emptyBehavior = "skip"; | ||||
| private Vector filesets = new Vector (); | private Vector filesets = new Vector (); | ||||
| private Hashtable addedDirs = new Hashtable(); | private Hashtable addedDirs = new Hashtable(); | ||||
| private Vector locFileSets = new Vector(); | |||||
| /** | /** | ||||
| * This is the name/location of where to | * This is the name/location of where to | ||||
| * create the .zip file. | * create the .zip file. | ||||
| @@ -110,26 +109,32 @@ public class Zip extends MatchingTask { | |||||
| /** | /** | ||||
| * Adds a set of files (nested fileset attribute). | * Adds a set of files (nested fileset attribute). | ||||
| */ | */ | ||||
| public void addFileset(FileSet set) { | |||||
| public void addFileset(PrefixedFileSet set) { | |||||
| filesets.addElement(set); | filesets.addElement(set); | ||||
| } | } | ||||
| /** | /** | ||||
| * FileSet with an additional prefix attribute to specify the | * FileSet with an additional prefix attribute to specify the | ||||
| * location we want to move the files to (inside the archive). | * location we want to move the files to (inside the archive). | ||||
| * Or, if this FileSet represents only a single file, then the | |||||
| * fullpath attribute can be set, which specifies the full path | |||||
| * that the file should have when it is placed in the archive. | |||||
| */ | */ | ||||
| public static class PrefixedFileSet extends FileSet { | public static class PrefixedFileSet extends FileSet { | ||||
| private String prefix = ""; | private String prefix = ""; | ||||
| private String fullpath = ""; | |||||
| public void setPrefix(String loc) { | public void setPrefix(String loc) { | ||||
| prefix = loc; | prefix = loc; | ||||
| } | } | ||||
| public String getPrefix() {return prefix;} | public String getPrefix() {return prefix;} | ||||
| } | |||||
| public void addPrefixedFileSet(PrefixedFileSet fs) { | |||||
| locFileSets.addElement(fs); | |||||
| public void setFullpath(String loc) { | |||||
| fullpath = loc; | |||||
| } | |||||
| public String getFullpath() {return fullpath;} | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -150,8 +155,7 @@ public class Zip extends MatchingTask { | |||||
| } | } | ||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| if (baseDir == null && filesets.size() == 0 && | |||||
| locFileSets.size() == 0 && "zip".equals(archiveType)) { | |||||
| if (baseDir == null && filesets.size() == 0 && "zip".equals(archiveType)) { | |||||
| throw new BuildException( "basedir attribute must be set, or at least " + | throw new BuildException( "basedir attribute must be set, or at least " + | ||||
| "one fileset or prefixedfileset must be given!" ); | "one fileset or prefixedfileset must be given!" ); | ||||
| } | } | ||||
| @@ -160,6 +164,7 @@ public class Zip extends MatchingTask { | |||||
| throw new BuildException("You must specify the " + archiveType + " file to create!"); | throw new BuildException("You must specify the " + archiveType + " file to create!"); | ||||
| } | } | ||||
| // Create the scanners to pass to isUpToDate(). | |||||
| Vector dss = new Vector (); | Vector dss = new Vector (); | ||||
| if (baseDir != null) | if (baseDir != null) | ||||
| dss.addElement(getDirectoryScanner(baseDir)); | dss.addElement(getDirectoryScanner(baseDir)); | ||||
| @@ -168,11 +173,9 @@ public class Zip extends MatchingTask { | |||||
| dss.addElement (fs.getDirectoryScanner(project)); | dss.addElement (fs.getDirectoryScanner(project)); | ||||
| } | } | ||||
| int dssSize = dss.size(); | int dssSize = dss.size(); | ||||
| FileScanner[] scanners = new FileScanner[dssSize + locFileSets.size()]; | |||||
| FileScanner[] scanners = new FileScanner[dssSize]; | |||||
| dss.copyInto(scanners); | dss.copyInto(scanners); | ||||
| addScanners(scanners, dssSize, locFileSets); | |||||
| // quick exit if the target is up to date | // quick exit if the target is up to date | ||||
| // can also handle empty archives | // can also handle empty archives | ||||
| if (isUpToDate(scanners, zipFile)) return; | if (isUpToDate(scanners, zipFile)) return; | ||||
| @@ -190,13 +193,12 @@ public class Zip extends MatchingTask { | |||||
| } | } | ||||
| initZipOutputStream(zOut); | initZipOutputStream(zOut); | ||||
| addPrefixedFiles(locFileSets, zOut); | |||||
| for (int j = 0; j < dssSize; j++) { | |||||
| addFiles(scanners[j], zOut, ""); | |||||
| // Add the implicit fileset to the archive. | |||||
| if (baseDir != null) | |||||
| addFiles(getDirectoryScanner(baseDir), zOut, "", ""); | |||||
| // Add the explicit filesets to the archive. | |||||
| addFiles(filesets, zOut); | |||||
| success = true; | success = true; | ||||
| } | |||||
| } finally { | } finally { | ||||
| // Close the output stream. | // Close the output stream. | ||||
| try { | try { | ||||
| @@ -225,18 +227,6 @@ public class Zip extends MatchingTask { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Add a DirectoryScanner for each FileSet included in fileSets to scanners | |||||
| * starting with index startIndex. | |||||
| */ | |||||
| protected void addScanners(FileScanner[] scanners, int startIndex, | |||||
| Vector fileSets) { | |||||
| for (int i=0; i<fileSets.size(); i++) { | |||||
| FileSet fs = (FileSet) fileSets.elementAt(i); | |||||
| scanners[startIndex+i] = fs.getDirectoryScanner(project); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Add all files of the given FileScanner to the ZipOutputStream | * Add all files of the given FileScanner to the ZipOutputStream | ||||
| * prependig the given prefix to each filename. | * prependig the given prefix to each filename. | ||||
| @@ -244,11 +234,16 @@ public class Zip extends MatchingTask { | |||||
| * <p>Ensure parent directories have been added as well. | * <p>Ensure parent directories have been added as well. | ||||
| */ | */ | ||||
| protected void addFiles(FileScanner scanner, ZipOutputStream zOut, | protected void addFiles(FileScanner scanner, ZipOutputStream zOut, | ||||
| String prefix) throws IOException { | |||||
| String prefix, String fullpath) throws IOException { | |||||
| if (prefix.length() > 0 && fullpath.length() > 0) | |||||
| throw new BuildException("Both prefix and fullpath attributes may not be set on the same fileset."); | |||||
| File thisBaseDir = scanner.getBasedir(); | File thisBaseDir = scanner.getBasedir(); | ||||
| // directories that matched include patterns | // directories that matched include patterns | ||||
| String[] dirs = scanner.getIncludedDirectories(); | String[] dirs = scanner.getIncludedDirectories(); | ||||
| if (dirs.length > 0 && fullpath.length() > 0) | |||||
| throw new BuildException("fullpath attribute may only be specified for filesets that specify a single file."); | |||||
| for (int i = 0; i < dirs.length; i++) { | for (int i = 0; i < dirs.length; i++) { | ||||
| String name = dirs[i].replace(File.separatorChar,'/'); | String name = dirs[i].replace(File.separatorChar,'/'); | ||||
| if (!name.endsWith("/")) { | if (!name.endsWith("/")) { | ||||
| @@ -259,11 +254,23 @@ public class Zip extends MatchingTask { | |||||
| // files that matched include patterns | // files that matched include patterns | ||||
| String[] files = scanner.getIncludedFiles(); | String[] files = scanner.getIncludedFiles(); | ||||
| if (files.length > 1 && fullpath.length() > 0) | |||||
| throw new BuildException("fullpath attribute may only be specified for filesets that specify a single file."); | |||||
| for (int i = 0; i < files.length; i++) { | for (int i = 0; i < files.length; i++) { | ||||
| File f = new File(thisBaseDir, files[i]); | File f = new File(thisBaseDir, files[i]); | ||||
| String name = files[i].replace(File.separatorChar,'/'); | |||||
| addParentDirs(thisBaseDir, name, zOut, prefix); | |||||
| zipFile(f, zOut, prefix+name); | |||||
| if (fullpath.length() > 0) | |||||
| { | |||||
| // Add this file at the specified location. | |||||
| addParentDirs(null, fullpath, zOut, ""); | |||||
| zipFile(f, zOut, fullpath); | |||||
| } | |||||
| else | |||||
| { | |||||
| // Add this file with the specified prefix. | |||||
| String name = files[i].replace(File.separatorChar,'/'); | |||||
| addParentDirs(thisBaseDir, name, zOut, prefix); | |||||
| zipFile(f, zOut, prefix+name); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -477,27 +484,15 @@ public class Zip extends MatchingTask { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Iterate over the given Vector of filesets and add all files to the | |||||
| * ZipOutputStream using the given prefix. | |||||
| */ | |||||
| protected void addFiles(Vector v, ZipOutputStream zOut, String prefix) | |||||
| throws IOException { | |||||
| for (int i=0; i<v.size(); i++) { | |||||
| FileSet fs = (FileSet) v.elementAt(i); | |||||
| DirectoryScanner ds = fs.getDirectoryScanner(project); | |||||
| addFiles(ds, zOut, prefix); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Iterate over the given Vector of prefixedfilesets and add | * Iterate over the given Vector of prefixedfilesets and add | ||||
| * all files to the ZipOutputStream using the given prefix. | * all files to the ZipOutputStream using the given prefix. | ||||
| */ | */ | ||||
| protected void addPrefixedFiles(Vector v, ZipOutputStream zOut) | |||||
| protected void addFiles(Vector filesets, ZipOutputStream zOut) | |||||
| throws IOException { | throws IOException { | ||||
| for (int i=0; i<v.size(); i++) { | |||||
| PrefixedFileSet fs = (PrefixedFileSet) v.elementAt(i); | |||||
| // Add each fileset in the Vector. | |||||
| for (int i = 0; i<filesets.size(); i++) { | |||||
| PrefixedFileSet fs = (PrefixedFileSet) filesets.elementAt(i); | |||||
| DirectoryScanner ds = fs.getDirectoryScanner(project); | DirectoryScanner ds = fs.getDirectoryScanner(project); | ||||
| String prefix = fs.getPrefix(); | String prefix = fs.getPrefix(); | ||||
| if (prefix.length() > 0 | if (prefix.length() > 0 | ||||
| @@ -505,11 +500,17 @@ public class Zip extends MatchingTask { | |||||
| && !prefix.endsWith("\\")) { | && !prefix.endsWith("\\")) { | ||||
| prefix += "/"; | prefix += "/"; | ||||
| } | } | ||||
| String fullpath = fs.getFullpath(); | |||||
| // Need to manually add either fullpath's parent directory, or | |||||
| // the prefix directory, to the archive. | |||||
| if (prefix.length() > 0) { | if (prefix.length() > 0) { | ||||
| addParentDirs(null, prefix, zOut, ""); | addParentDirs(null, prefix, zOut, ""); | ||||
| zipDir(null, zOut, prefix); | zipDir(null, zOut, prefix); | ||||
| } | |||||
| addFiles(ds, zOut, prefix); | |||||
| } else if (fullpath.length() > 0) { | |||||
| addParentDirs(null, fullpath, zOut, ""); | |||||
| } | |||||
| // Add the fileset. | |||||
| addFiles(ds, zOut, prefix, fullpath); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||