diff --git a/build.xml b/build.xml
index 0e1602d5e..e55cc2671 100644
--- a/build.xml
+++ b/build.xml
@@ -83,6 +83,7 @@
+
diff --git a/docs/index.html b/docs/index.html
index df277669e..eb4a62bce 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -3302,6 +3302,7 @@ and todo.html
are excluded.
+
+Description:
+The cab task creates Microsoft cab archive files. It is invoked
+similar to the jar or zip tasks.
+This task will only work on Windows, and will be silently ignored on
+other platforms. You must have the Microsoft cabarc tool available in
+your executable path.
+See the section on directory based
+tasks, on how the inclusion/exclusion of files works, and how to
+write patterns. The patterns are relative to the basedir
+directory.
+Parameters:
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ cabfile |
+ the name of the cab file to create. |
+ Yes |
+
+
+ basedir |
+ the directory to start archiving files from. |
+ Yes |
+
+
+ verbose |
+ set to "yes" if you want to see the output from
+ the cabarc tool. defaults to "no". |
+ No |
+
+
+ compress |
+ set to "no" to store files without compressing.
+ defaults to "yes". |
+ No |
+
+
+ options |
+ use to set additional command-line options for
+ the cabarc tool. should not normally be necessary. |
+ No |
+
+
+Examples
+
+ None yet available
+
+
Description:
Compiles a NetRexx
diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
index 20cceef3e..66373b9d9 100644
--- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties
+++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties
@@ -53,6 +53,7 @@ vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET
ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar
mparse=org.apache.tools.ant.taskdefs.optional.metamata.MParse
junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask
+cab=org.apache.tools.ant.taskdefs.optional.Cab
# deprecated ant tasks (kept for back compatibility)
javadoc2=org.apache.tools.ant.taskdefs.Javadoc
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java b/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
new file mode 100644
index 000000000..3f0787e5a
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java
@@ -0,0 +1,349 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 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.optional;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.*;
+import org.apache.tools.ant.types.*;
+
+import java.io.*;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * Create a CAB archive.
+ *
+ * @author Roger Vaughn rvaughn@seaconinc.com
+ */
+
+public class Cab extends MatchingTask {
+
+ private File cabFile;
+ private File baseDir;
+ private Vector filesets = new Vector();
+ private boolean doCompress = true;
+ private boolean doVerbose = false;
+ private String cmdOptions;
+
+ protected String archiveType = "cab";
+
+ private static String myos;
+ private static boolean isWindows;
+
+ static {
+ myos = System.getProperty("os.name");
+ isWindows = myos.toLowerCase().indexOf("windows") >= 0;
+ }
+
+ /**
+ * This is the name/location of where to
+ * create the .cab file.
+ */
+ public void setCabfile(File cabFile) {
+ cabFile = cabFile;
+ }
+
+ /**
+ * This is the base directory to look in for
+ * things to cab.
+ */
+ public void setBasedir(File baseDir) {
+ this.baseDir = baseDir;
+ }
+
+ /**
+ * Sets whether we want to compress the files or only store them.
+ */
+ public void setCompress(boolean compress) {
+ doCompress = compress;
+ }
+
+ /**
+ * Sets whether we want to see or suppress cabarc output.
+ */
+ public void setVerbose(boolean verbose) {
+ doVerbose = verbose;
+ }
+
+ /**
+ * Sets additional cabarc options that aren't supported directly.
+ */
+ public void setOptions(String options) {
+ cmdOptions = options;
+ }
+
+ /**
+ * Adds a set of files (nested fileset attribute).
+ */
+ public void addFileset(FileSet set) {
+ filesets.addElement(set);
+ }
+
+ /**
+ * Adds a reference to a set of files (nested filesetref element).
+ */
+ public void addFilesetref(Reference ref) {
+ filesets.addElement(ref);
+ }
+
+ /*
+ * I'm not fond of this pattern: "sub-method expected to throw
+ * task-cancelling exceptions". It feels too much like programming
+ * for side-effects to me...
+ */
+ protected void checkConfiguration() throws BuildException {
+ if (baseDir == null) {
+ throw new BuildException("basedir attribute must be set!");
+ }
+ if (!baseDir.exists()) {
+ throw new BuildException("basedir does not exist!");
+ }
+ if (cabFile == null) {
+ throw new BuildException("cabfile attribute must be set!");
+ }
+ }
+
+ /**
+ * Create a new exec delegate. The delegate task is populated so that
+ * it appears in the logs to be the same task as this one.
+ */
+ protected ExecTask createExec() throws BuildException
+ {
+ ExecTask exec = (ExecTask)project.createTask("exec");
+ exec.setOwningTarget(this.getOwningTarget());
+ exec.setTaskName(this.getTaskName());
+ exec.setDescription(this.getDescription());
+
+ return exec;
+ }
+
+ /**
+ * Check to see if the target is up to date with respect to input files.
+ * @return true if the cab file is newer than its dependents.
+ */
+ protected boolean isUpToDate(Vector files)
+ {
+ boolean upToDate = true;
+ for (int i=0; i
+ cabFile.lastModified())
+ upToDate = false;
+ }
+ return upToDate;
+ }
+
+ /**
+ * Create the cabarc command line to use.
+ */
+ protected Commandline createCommand(File listFile)
+ {
+ Commandline command = new Commandline();
+ command.setExecutable("cabarc");
+ command.addValue("-r");
+ command.addValue("-p");
+
+ if (!doCompress)
+ {
+ command.addValue("-m");
+ command.addValue("none");
+ }
+
+ if (cmdOptions != null)
+ {
+ command.addValue(cmdOptions);
+ }
+
+ command.addValue("n");
+ command.addValue(cabFile.getAbsolutePath());
+ command.addValue("@" + listFile.getAbsolutePath());
+
+ return command;
+ }
+
+ /**
+ * Creates a list file. This temporary file contains a list of all files
+ * to be included in the cab, one file per line.
+ */
+ protected File createListFile(Vector files)
+ throws IOException
+ {
+ File listFile = File.createTempFile("ant", null);
+ listFile.deleteOnExit();
+ PrintWriter writer = new PrintWriter(new FileOutputStream(listFile));
+
+ for (int i = 0; i < files.size(); i++)
+ {
+ writer.println(files.elementAt(i).toString());
+ }
+ writer.close();
+
+ return listFile;
+ }
+
+ /**
+ * Append all files found by a directory scanner to a vector.
+ */
+ protected void appendFiles(Vector files, DirectoryScanner ds)
+ {
+ String[] dsfiles = ds.getIncludedFiles();
+
+ for (int i = 0; i < dsfiles.length; i++)
+ {
+ files.addElement(dsfiles[i]);
+ }
+ }
+
+ /**
+ * Get the complete list of files to be included in the cab. Filenames
+ * are gathered from filesets if any have been added, otherwise from the
+ * traditional include parameters.
+ */
+ protected Vector getFileList() throws BuildException
+ {
+ Vector files = new Vector();
+
+ if (filesets.size() == 0)
+ {
+ // get files from old methods - includes and nested include
+ appendFiles(files, super.getDirectoryScanner(baseDir));
+ }
+ else
+ {
+ // get files from filesets
+ for (int i = 0; i < filesets.size(); i++)
+ {
+ Object o = filesets.elementAt(i);
+ FileSet fs;
+ if (o instanceof FileSet)
+ {
+ fs = (FileSet)o;
+ }
+ else if (o instanceof Reference)
+ {
+ Reference r = (Reference)o;
+ o = r.getReferencedObject(project);
+
+ if (o instanceof FileSet)
+ {
+ fs = (FileSet)o;
+ }
+ else
+ {
+ throw new BuildException(
+ r.getRefId() + " does not denote a fileset",
+ location);
+ }
+ }
+ else
+ {
+ throw new BuildException(
+ "nested element is not a FileSet or Reference",
+ location);
+ }
+
+ if (fs != null)
+ {
+ appendFiles(files, fs.getDirectoryScanner(project));
+ }
+ }
+ }
+
+ return files;
+ }
+
+ public void execute() throws BuildException {
+ // we must be on Windows to continue
+ if (!isWindows)
+ {
+ log("cannot run on non-Windows platforms: " + myos,
+ Project.MSG_VERBOSE);
+ return;
+ }
+
+ checkConfiguration();
+
+ Vector files = getFileList();
+
+ // quick exit if the target is up to date
+ if (isUpToDate(files)) return;
+
+ log("Building "+ archiveType +": "+ cabFile.getAbsolutePath());
+
+ try {
+ File listFile = createListFile(files);
+ ExecTask exec = createExec();
+
+ // die if cabarc fails
+ exec.setFailonerror(true);
+ exec.setDir(baseDir);
+
+ if (!doVerbose)
+ {
+ File outFile = File.createTempFile("ant", null);
+ outFile.deleteOnExit();
+ exec.setOutput(outFile);
+ }
+
+ exec.setCommand(createCommand(listFile));
+ exec.execute();
+ } catch (IOException ioe) {
+ String msg = "Problem creating " + cabFile + " " + ioe.getMessage();
+ throw new BuildException(msg);
+ }
+ }
+}