From 20a1e91d17753399f8d18a5123f8e5e35e0409da Mon Sep 17 00:00:00 2001
From: Stefan Bodewig
Date: Fri, 15 Sep 2000 11:41:19 +0000
Subject: [PATCH] New tasks and .
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267998 13f79535-47bb-0310-9956-ffa450edef68
---
docs/index.html | 131 +++++++++++-
.../org/apache/tools/ant/taskdefs/Jar.java | 88 ++++----
.../org/apache/tools/ant/taskdefs/War.java | 194 ++++++++++++++++++
.../org/apache/tools/ant/taskdefs/Zip.java | 100 ++++++---
.../tools/ant/taskdefs/defaults.properties | 2 +
.../org/apache/tools/ant/types/FileSet.java | 29 +--
6 files changed, 445 insertions(+), 99 deletions(-)
create mode 100644 src/main/org/apache/tools/ant/taskdefs/War.java
diff --git a/docs/index.html b/docs/index.html
index 13cecbfa3..e6697a6ed 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -25,7 +25,7 @@
Dave Walend (dwalend@cs.tufts.edu)
-Version 1.2 - 2000/09/14
+Version 1.2 - 2000/09/15
Table of Contents
@@ -870,7 +870,9 @@ same patterns as the example before.
Tstamp
Unjar
Untar
+ Unwar
Unzip
+ War
Zip
@@ -3700,9 +3702,9 @@ initialization target.
Examples
<tstamp/>
-
+
Description
-Unzips a zip- or jarfile.
+Unzips a zip-, war- or jarfile.
For JDK 1.1 "last modified time" field is set to current time instead of being
carried from zipfile.
File permissions will not be restored on extracted files.
@@ -3762,6 +3764,129 @@ carried from tarfile.
+
+Description
+An extension of the Jar task with special
+treatment for files that should end up in the lib
,
+classes
or WEB-INF
directories of the Web
+Application Archive.
+Parameters
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ warfile |
+ the war-file to create. |
+ Yes |
+
+
+ webxml |
+ The deployment descriptor to use (WEB-INF/web.xml). |
+ Yes |
+
+
+ basedir |
+ the directory from which to jar the files. |
+ No |
+
+
+ compress |
+ Not only store data but also compress them, defaults to true |
+ No |
+
+
+ includes |
+ comma separated list of patterns of files that must be
+ included. All files are included when omitted. |
+ No |
+
+
+ includesfile |
+ the name of a file. Each line of this file is
+ taken to be an include pattern |
+ No |
+
+
+ excludes |
+ comma separated list of patterns of files that must be
+ excluded. No files (except default excludes) are excluded when omitted. |
+ No |
+
+
+ excludesfile |
+ the name of a file. Each line of this file is
+ taken to be an exclude pattern |
+ No |
+
+
+ defaultexcludes |
+ indicates whether default excludes should be used or not
+ ("yes"/"no"). Default excludes are used when omitted. |
+ No |
+
+
+ manifest |
+ the manifest file to use. |
+ No |
+
+
+ whenempty |
+ Behavior to use if no files match. |
+ No |
+
+
+Nested elements
+lib
+The nested lib
element specifies a FileSet. All files included in this fileset will
+end up in the lib
directory of the war file.
+classes
+The nested classes
element specifies a FileSet. All files included in this fileset will
+end up in the classes
directory of the war file.
+webinf
+The nested webinf
element specifies a FileSet. All files included in this fileset will
+end up in the WEB-INF
directory of the war file. If this
+fileset includes a file named web.xml
, the file is
+ignored and you will get a warning.
+Examples
+Assume the following structure in the project's base directory:
+
+thirdparty/libs/jdbc1.jar
+thirdparty/libs/jdbc2.jar
+build/main/com/myco/myapp/Servlet.class
+src/metadata/myapp.xml
+src/html/myapp/index.html
+src/jsp/myapp/front.jsp
+
+then the war file myapp.war
created with
+
+<war warfile="myapp.war" webxml="src/metadata/myapp.xml">
+ <fileset dir="src/html/myapp" />
+ <fileset dir="src/jsp/myapp" />
+ <lib dir="thirdparty/libs">
+ <exclude name="jdbc1.jar" />
+ </lib>
+ <classes dir="build/main" />
+</war>
+
+will consist of
+
+WEB-INF/web.xml
+lib/jdbc2.jar
+classes/com/myco/myapp/Servlet.class
+META-INF/MANIFEST.MF
+index.html
+front.jsp
+
+using Ant's default manifest file. The content of
+WEB-INF/web.xml
is identical to
+src/metadata/myapp.xml
.
+
Description
Creates a zipfile.
diff --git a/src/main/org/apache/tools/ant/taskdefs/Jar.java b/src/main/org/apache/tools/ant/taskdefs/Jar.java
index 7351b2ec3..29fdd7314 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Jar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Jar.java
@@ -69,13 +69,18 @@ public class Jar extends Zip {
private File manifest;
- public void setJarfile(String jarFilename) {
- super.setZipfile(jarFilename);
- super.archiveType = "jar";
+ public Jar() {
+ super();
+ archiveType = "jar";
+ emptyBehavior = "create";
+ }
+
+ public void setJarfile(File jarFile) {
+ super.setZipfile(jarFile);
}
- public void setManifest(String manifestFilename) {
- manifest = project.resolveFile(manifestFilename);
+ public void setManifest(File manifestFile) {
+ manifest = manifestFile;
}
protected void initZipOutputStream(ZipOutputStream zOut)
@@ -83,59 +88,51 @@ public class Jar extends Zip {
{
// add manifest first
if (manifest != null) {
- super.zipDir(new File(manifest.getParent()), zOut, "META-INF/");
+ zipDir(new File(manifest.getParent()), zOut, "META-INF/");
super.zipFile(manifest, zOut, "META-INF/MANIFEST.MF");
} else {
String s = "/org/apache/tools/ant/defaultManifest.mf";
InputStream in = this.getClass().getResourceAsStream(s);
if ( in == null )
throw new BuildException ( "Could not find: " + s );
- super.zipDir(null, zOut, "META-INF/");
+ zipDir(null, zOut, "META-INF/");
zipFile(in, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis());
}
}
- protected boolean isUpToDate(FileScanner[] scanners, File zipFile)
+ protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException
{
File[] files = grabFiles(scanners);
- if (emptyBehavior == null) emptyBehavior = "create";
- if (files.length == 0) {
- if (emptyBehavior.equals("skip")) {
- log("Warning: skipping JAR archive " + zipFile +
- " because no files were included.", Project.MSG_WARN);
- return true;
- } else if (emptyBehavior.equals("fail")) {
- throw new BuildException("Cannot create JAR archive " + zipFile +
- ": no files were included.", location);
- } else {
- // create
- if (!zipFile.exists() ||
- (manifest != null &&
- manifest.lastModified() > zipFile.lastModified()))
- log("Note: creating empty JAR archive " + zipFile, Project.MSG_INFO);
- // and continue below...
- }
- }
- if (!zipFile.exists()) return false;
- if (manifest != null && manifest.lastModified() > zipFile.lastModified())
- return false;
- for (int i=0; i zipFile.lastModified()) {
- return false;
+
+ 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 true;
- }
+ return retval;
- protected void zipDir(File dir, ZipOutputStream zOut, String vPath)
- throws IOException
- {
- // First add directory to zip entry
- if(!vPath.equalsIgnoreCase("META-INF/")) {
- // we already added a META-INF
- super.zipDir(dir, zOut, vPath);
+ } 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);
}
- // no warning if not, it is harmless in and of itself
}
protected void zipFile(File file, ZipOutputStream zOut, String vPath)
@@ -145,8 +142,9 @@ public class Jar extends Zip {
if (!vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) {
super.zipFile(file, zOut, vPath);
} else {
- log("Warning: selected JAR files include a META-INF/MANIFEST.MF which will be ignored " +
- "(please use manifest attribute to jar task)", Project.MSG_WARN);
+ 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);
}
}
+
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/War.java b/src/main/org/apache/tools/ant/taskdefs/War.java
new file mode 100644
index 000000000..953057965
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/War.java
@@ -0,0 +1,194 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.FileSet;
+
+import java.io.*;
+import java.util.Vector;
+import java.util.zip.*;
+
+/**
+ * Creates a WAR archive.
+ *
+ * @author Stefan Bodewig
+ */
+public class War extends Jar {
+
+ private File deploymentDescriptor;
+
+ private Vector libFileSets = new Vector();
+ private Vector classesFileSets = new Vector();
+ private Vector webInfFileSets = new Vector();
+
+ public War() {
+ super();
+ archiveType = "war";
+ emptyBehavior = "create";
+ }
+
+ public void setWarfile(File warFile) {
+ super.setZipfile(warFile);
+ }
+
+ public void setWebxml(File descr) {
+ deploymentDescriptor = descr;
+ }
+
+ public void addLib(FileSet fs) {
+ libFileSets.addElement(fs);
+ }
+
+ public void addClasses(FileSet fs) {
+ classesFileSets.addElement(fs);
+ }
+
+ public void addWebinf(FileSet fs) {
+ webInfFileSets.addElement(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)
+ 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, "lib/");
+ addFiles(classesFileSets, zOut, "classes/");
+ addFiles(webInfFileSets, zOut, "WEB-INF/");
+
+ super.initZipOutputStream(zOut);
+ }
+
+ protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException
+ {
+ if (deploymentDescriptor == null) {
+ 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);
+ }
+
+ protected void zipFile(File file, ZipOutputStream zOut, String vPath)
+ throws IOException
+ {
+ // We already added a WEB-INF/web.xml
+ if (!vPath.equalsIgnoreCase("WEB-INF/web.xml")) {
+ super.zipFile(file, zOut, vPath);
+ } 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);
+ }
+ }
+
+ /**
+ * 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; iEnsure parent directories have been added as well.
+ */
+ protected void addFiles(FileScanner scanner, ZipOutputStream zOut,
+ String prefix) throws IOException {
+ File thisBaseDir = scanner.getBasedir();
+
+ // directories that matched include patterns
+ String[] dirs = scanner.getIncludedDirectories();
+ for (int i = 0; i < dirs.length; i++) {
+ String name = dirs[i].replace(File.separatorChar,'/');
+ if (!name.endsWith("/")) {
+ name += "/";
+ }
+ addParentDirs(thisBaseDir, name, zOut, prefix);
+ }
+
+ // files that matched include patterns
+ String[] files = scanner.getIncludedFiles();
+ for (int i = 0; i < files.length; 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);
+ }
+ }
+
protected void initZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException
{
@@ -211,15 +224,14 @@ public class Zip extends MatchingTask {
*/
protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException
{
- if (emptyBehavior == null) emptyBehavior = "skip";
File[] files = grabFiles(scanners);
if (files.length == 0) {
if (emptyBehavior.equals("skip")) {
- log("Warning: skipping ZIP archive " + zipFile +
+ log("Warning: skipping "+archiveType+" archive " + zipFile +
" because no files were included.", Project.MSG_WARN);
return true;
} else if (emptyBehavior.equals("fail")) {
- throw new BuildException("Cannot create ZIP archive " + zipFile +
+ throw new BuildException("Cannot create "+archiveType+" archive " + zipFile +
": no files were included.", location);
} else {
// Create.
@@ -227,7 +239,7 @@ public class Zip extends MatchingTask {
// In this case using java.util.zip will not work
// because it does not permit a zero-entry archive.
// Must create it manually.
- log("Note: creating empty ZIP archive " + zipFile, Project.MSG_INFO);
+ log("Note: creating empty "+archiveType+" archive " + zipFile, Project.MSG_INFO);
try {
OutputStream os = new FileOutputStream(zipFile);
try {
@@ -275,6 +287,13 @@ public class Zip extends MatchingTask {
protected void zipDir(File dir, ZipOutputStream zOut, String vPath)
throws IOException
{
+ if (addedDirs.get(vPath) != null) {
+ // don't add directories we've already added.
+ // no warning if we try, it is harmless in and of itself
+ return;
+ }
+ addedDirs.put(vPath, vPath);
+
ZipEntry ze = new ZipEntry (vPath);
if (dir != null) ze.setTime (dir.lastModified ());
ze.setSize (0);
@@ -353,4 +372,29 @@ public class Zip extends MatchingTask {
fIn.close();
}
}
+
+ /**
+ * Ensure all parent dirs of a given entry have been added.
+ */
+ protected void addParentDirs(File baseDir, String entry,
+ ZipOutputStream zOut, String prefix)
+ throws IOException {
+
+ Stack directories = new Stack();
+ int slashPos = entry.length();
+
+ while ((slashPos = entry.lastIndexOf((int)'/', slashPos-1)) != -1) {
+ String dir = entry.substring(0, slashPos+1);
+ if (addedDirs.get(prefix+dir) != null) {
+ break;
+ }
+ directories.push(dir);
+ }
+
+ while (!directories.isEmpty()) {
+ String dir = (String) directories.pop();
+ File f = new File(baseDir, dir);
+ zipDir(f, zOut, prefix+dir);
+ }
+ }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index a8f381a52..dca236bf8 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -12,6 +12,7 @@ cvs=org.apache.tools.ant.taskdefs.Cvs
get=org.apache.tools.ant.taskdefs.Get
unzip=org.apache.tools.ant.taskdefs.Expand
unjar=org.apache.tools.ant.taskdefs.Expand
+unwar=org.apache.tools.ant.taskdefs.Expand
echo=org.apache.tools.ant.taskdefs.Echo
javadoc=org.apache.tools.ant.taskdefs.Javadoc
zip=org.apache.tools.ant.taskdefs.Zip
@@ -42,6 +43,7 @@ antcall=org.apache.tools.ant.taskdefs.CallTarget
sql=org.apache.tools.ant.taskdefs.SQLExec
mail=org.apache.tools.ant.taskdefs.SendEmail
fail=org.apache.tools.ant.taskdefs.Exit
+war=org.apache.tools.ant.taskdefs.War
# optional tasks
script=org.apache.tools.ant.taskdefs.optional.Script
diff --git a/src/main/org/apache/tools/ant/types/FileSet.java b/src/main/org/apache/tools/ant/types/FileSet.java
index e2461646e..716cfd09f 100644
--- a/src/main/org/apache/tools/ant/types/FileSet.java
+++ b/src/main/org/apache/tools/ant/types/FileSet.java
@@ -107,18 +107,12 @@ public class FileSet extends DataType {
throw tooManyAttributes();
}
- /*
- * XXX cannot check as long as tasks get configured at parse time.
- *
- * the build process might create the directory.
- */
-
-// if (!dir.exists()) {
-// throw new BuildException(dir.getAbsolutePath()+" not found.");
-// }
-// if (!dir.isDirectory()) {
-// throw new BuildException(dir.getAbsolutePath()+" is not a directory.");
-// }
+ if (!dir.exists()) {
+ throw new BuildException(dir.getAbsolutePath()+" not found.");
+ }
+ if (!dir.isDirectory()) {
+ throw new BuildException(dir.getAbsolutePath()+" is not a directory.");
+ }
this.dir = dir;
}
@@ -239,17 +233,6 @@ public class FileSet extends DataType {
throw new BuildException("No directory specified for fileset.");
}
- /*
- * XXX remove the check here and enable the one in setDir as soon
- * as we configure tasks at execution time.
- */
- if (!dir.exists()) {
- throw new BuildException(dir.getAbsolutePath()+" not found.");
- }
- if (!dir.isDirectory()) {
- throw new BuildException(dir.getAbsolutePath()+" is not a directory.");
- }
-
DirectoryScanner ds = new DirectoryScanner();
setupDirectoryScanner(ds, p);
ds.scan();