Browse Source

Patch to unify handling of prefix filesets between war/jar/zip.

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-ffa450edef68
master
Peter Donald 24 years ago
parent
commit
8e955e3a2e
4 changed files with 165 additions and 241 deletions
  1. +38
    -75
      docs/index.html
  2. +36
    -52
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  3. +39
    -63
      src/main/org/apache/tools/ant/taskdefs/War.java
  4. +52
    -51
      src/main/org/apache/tools/ant/taskdefs/Zip.java

+ 38
- 75
docs/index.html View File

@@ -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> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot; basedir=&quot;${build}/classes&quot; /&gt;</pre> <pre> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot; basedir=&quot;${build}/classes&quot; /&gt;</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> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot; <pre> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot;
basedir=&quot;${build}/classes&quot; basedir=&quot;${build}/classes&quot;
excludes=&quot;**/Test.class&quot; excludes=&quot;**/Test.class&quot;
/&gt;</pre> /&gt;</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> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot; <pre> &lt;jar jarfile=&quot;${dist}/lib/app.jar&quot;
@@ -2805,7 +2810,7 @@ with the name <code>Test.class</code> are excluded.</p>
includes=&quot;mypackage/test/**&quot; includes=&quot;mypackage/test/**&quot;
excludes=&quot;**/Test.class&quot; excludes=&quot;**/Test.class&quot;
/&gt;</pre> /&gt;</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>
&lt;fileset dir=&quot;${src}/resources&quot;/&gt; &lt;fileset dir=&quot;${src}/resources&quot;/&gt;
&lt;/jar&gt;</pre> &lt;/jar&gt;</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> &lt;tar tarfile=&quot;${dist}/manual.tar&quot; basedir=&quot;htdocs/manual&quot; /&gt; <pre> &lt;tar tarfile=&quot;${dist}/manual.tar&quot; basedir=&quot;htdocs/manual&quot; /&gt;
&lt;gzip zipfile=&quot;${dist}/manual.tar.gz&quot; src=&quot;${dist}/manual.tar&quot; /&gt;</pre> &lt;gzip zipfile=&quot;${dist}/manual.tar.gz&quot; src=&quot;${dist}/manual.tar&quot; /&gt;</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> &lt;tar tarfile=&quot;${dist}/manual.tar&quot; <pre> &lt;tar tarfile=&quot;${dist}/manual.tar&quot;
basedir=&quot;htdocs/manual&quot; basedir=&quot;htdocs/manual&quot;
excludes=&quot;mydocs/**, **/todo.html&quot; excludes=&quot;mydocs/**, **/todo.html&quot;
/&gt;</pre> /&gt;</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
(&quot;yes&quot;/&quot;no&quot;). 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
&lt;exclude name=&quot;jdbc1.jar&quot; /&gt; &lt;exclude name=&quot;jdbc1.jar&quot; /&gt;
&lt;/lib&gt; &lt;/lib&gt;
&lt;classes dir=&quot;build/main&quot; /&gt; &lt;classes dir=&quot;build/main&quot; /&gt;
&lt;prefixedfileset dir=&quot;src/graphics/images/gifs&quot;
&lt;fileset dir=&quot;src/graphics/images/gifs&quot;
prefix="images"/&gt; prefix="images"/&gt;
&lt;/war&gt; &lt;/war&gt;
</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>&lt;include&gt;</code>); explicit nested and optional subelements like <code>&lt;include&gt;</code>); explicit nested
<code>&lt;fileset&gt;</code> elements so long as at least one fileset total is specified. The ZIP file will <code>&lt;fileset&gt;</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>&lt;zip&gt;</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> &lt;zip zipfile=&quot;${dist}/manual.zip&quot; <pre> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;
basedir=&quot;htdocs/manual&quot; basedir=&quot;htdocs/manual&quot;
/&gt;</pre> /&gt;</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> &lt;zip zipfile=&quot;${dist}/manual.zip&quot; <pre> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;
basedir=&quot;htdocs/manual&quot; basedir=&quot;htdocs/manual&quot;
excludes=&quot;mydocs/**, **/todo.html&quot; excludes=&quot;mydocs/**, **/todo.html&quot;
/&gt;</pre> /&gt;</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> &lt;zip zipfile=&quot;${dist}/manual.zip&quot; <pre> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;
basedir=&quot;htdocs/manual&quot; basedir=&quot;htdocs/manual&quot;
includes=&quot;api/**/*.html&quot; includes=&quot;api/**/*.html&quot;
excludes=&quot;**/todo.html&quot; excludes=&quot;**/todo.html&quot;
/&gt;</pre> /&gt;</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> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;&gt; <pre> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;&gt;
&lt;fileset dir=&quot;htdocs/manual&quot;/&gt; &lt;fileset dir=&quot;htdocs/manual&quot;/&gt;
&lt;fileset dir=&quot;.&quot; includes=&quot;ChangeLog.txt&quot;/&gt; &lt;fileset dir=&quot;.&quot; includes=&quot;ChangeLog.txt&quot;/&gt;
&lt;/zip&gt;</pre> &lt;/zip&gt;</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> &lt;zip zipfile=&quot;${dist}/manual.zip&quot;&gt;
&lt;fileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
&lt;fileset dir=&quot;.&quot; includes=&quot;ChangeLog27.txt&quot; fullpath=&quot;docs/ChangeLog.txt&quot;/&gt;
&lt;/zip&gt;</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>&lt;fileset&gt;</code>
basedir=&quot;htdocs/manual&quot; basedir=&quot;htdocs/manual&quot;
/&gt; /&gt;
</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>
&lt;cab cabfile=&quot;${dist}/manual.cab&quot; &lt;cab cabfile=&quot;${dist}/manual.cab&quot;
@@ -5196,7 +5159,7 @@ manual.cab in the ${dist} directory.</p>
excludes=&quot;mydocs/**, **/todo.html&quot; excludes=&quot;mydocs/**, **/todo.html&quot;
/&gt; /&gt;
</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=&quot;yes&quot; verbose=&quot;yes&quot;
/&gt; /&gt;
</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


+ 36
- 52
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -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);
} }
} }

} }

+ 39
- 63
src/main/org/apache/tools/ant/taskdefs/War.java View File

@@ -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);
} }
} }
}
}

+ 52
- 51
src/main/org/apache/tools/ant/taskdefs/Zip.java View File

@@ -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);
} }
} }
} }

Loading…
Cancel
Save