Ok, I did it again. The last version included a Random method available only
in 1.2+. This version corrects it. I suppose it's time to set up a 1.1
testing environment....
Roger Vaughn wrote:
> I see someone got to the docs before I did. In any case, I expanded what
> was there to include the matching params. I'm not going to attempt to add
> docs for the fileset support until Stefan gets the basics in there. I can
> revisit the docs when that happens. The diff is attached.
>
> I also removed the 1.2+ dependency from the Cab code. That was entirely
> unintentional. The compile guard should be removed from the build.xml
> file now. I also corrected a bug in the handling of the cabfile param (I
> don't know how that got in there.) The new file is attached.
>
> Stefan Bodewig wrote:
>
> > >>>>> "RV" == Roger Vaughn <[EMAIL PROTECTED]> writes:
> >
> > RV> This now includes support for nested filesets as well as
> > RV> supporting the traditional matching params. Only one style or
> > RV> the other is allowed in a single task.
> >
> > Roger, could you please (1) update the documentation in
> > docs/index.html for it and (2) remove the JDK 1.2 dependency -
> > File.deleteOnExit and File.createTempFile?
> >
> > Step (1) may wait until I get to document fileset myself of course 8^)
> > - but I really see no reason to make that task depend on JDK > 1.1.
> >
> > Stefan
>
> ------------------------------------------------------------------------
> *** index.html.orig Thu Aug 03 09:41:35 2000 --- index.html Thu Aug 03
> 15:46:46 2000 *************** *** 3335,3366 **** 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
>
> !
>
> ------------------------------------------------------------------------
>
> NetRexxC
>
> Description:
>
> --- 3335,3415 ---- basedir ! the directory from which to start archiving
> files. Yes verbose ! set to "yes" 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 ! ! ! 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
>
> Examples
>
> !
>
> <cab cabfile="${dist}/manual.cab"
> ! basedir="htdocs/manual"
> ! />
>
> !
>
> cabs all files in the htdocs/manual directory in a file called manual.cab !
> in the ${dist} directory.
>
> !
>
> <cab cabfile="${dist}/manual.cab"
> ! basedir="htdocs/manual"
> ! excludes="mydocs/**, **/todo.html"
> ! />
>
> !
>
> cabs all files in the htdocs/manual directory in a file called manual.cab !
> in the ${dist} directory. Files in the directory mydocs, ! or files with the
> name todo.html are excluded.
>
> !
>
> <cab cabfile="${dist}/manual.cab"
> ! basedir="htdocs/manual"
> ! includes="api/**/*.html"
> ! excludes="**/todo.html"
> ! verbose="yes"
> ! />
>
> !
>
> cab all files in the htdocs/manual directory in a file called manual.cab ! in
> the ${dist} directory. Only html files under the directory api ! are
> archived, and files with the name todo.html are excluded. Output from ! the
> cabarc tool is displayed in the build output.
>
> ------------------------------------------------------------------------
>
> NetRexxC
>
> Description:
>
> ------------------------------------------------------------------------
> /*
> * 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 [EMAIL PROTECTED]
> *
> * 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
> * <http://www.apache.org/>.
> */
>
> 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;
> import java.util.Random;
> import java.text.DecimalFormat;
>
> /**
> * Create a CAB archive.
> *
> * @author Roger Vaughn <a href="mailto:[EMAIL PROTECTED]">[EMAIL
> PROTECTED]</a>
> */
>
> 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) {
> this.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<files.size() && upToDate; i++)
> {
> String file = files.elementAt(i).toString();
> if (new File(baseDir,file).lastModified() >
> 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.createArgument().setValue("-r");
> command.createArgument().setValue("-p");
>
> if (!doCompress)
> {
> command.createArgument().setValue("-m");
> command.createArgument().setValue("none");
> }
>
> if (cmdOptions != null)
> {
> command.createArgument().setValue(cmdOptions);
> }
>
> command.createArgument().setValue("n");
> command.createArgument().setFile(cabFile);
> command.createArgument().setValue("@" + listFile.getAbsolutePath());
>
> return command;
> }
>
> private static int counter = new Random().nextInt(100000);
> protected File createTempFile(String prefix, String suffix)
> {
> if (suffix == null)
> {
> suffix = ".tmp";
> }
>
> String name = prefix +
> new DecimalFormat("#####").format(new Integer(counter++)) +
> suffix;
>
> String tmpdir = System.getProperty("java.io.tmpdir");
>
> // java.io.tmpdir is not present in 1.1
> if (tmpdir == null)
> return new File(name);
> else
> return new File(tmpdir, name);
> }
>
> /**
> * 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 = createTempFile("ant", null);
>
> 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();
> File outFile = null;
>
> // die if cabarc fails
> exec.setFailonerror(true);
> exec.setDir(baseDir);
>
> if (!doVerbose)
> {
> outFile = createTempFile("ant", null);
> exec.setOutput(outFile);
> }
>
> exec.setCommand(createCommand(listFile));
> exec.execute();
>
> if (outFile != null)
> {
> outFile.delete();
> }
>
> listFile.delete();
> } catch (IOException ioe) {
> String msg = "Problem creating " + cabFile + " " +
> ioe.getMessage();
> throw new BuildException(msg);
> }
> }
> }
/*
* 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 [EMAIL PROTECTED]
*
* 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
* <http://www.apache.org/>.
*/
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;
import java.util.Random;
import java.text.DecimalFormat;
/**
* Create a CAB archive.
*
* @author Roger Vaughn <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
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) {
this.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<files.size() && upToDate; i++)
{
String file = files.elementAt(i).toString();
if (new File(baseDir,file).lastModified() >
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.createArgument().setValue("-r");
command.createArgument().setValue("-p");
if (!doCompress)
{
command.createArgument().setValue("-m");
command.createArgument().setValue("none");
}
if (cmdOptions != null)
{
command.createArgument().setValue(cmdOptions);
}
command.createArgument().setValue("n");
command.createArgument().setFile(cabFile);
command.createArgument().setValue("@" + listFile.getAbsolutePath());
return command;
}
private static int counter = new Random().nextInt() % 100000;
protected File createTempFile(String prefix, String suffix)
{
if (suffix == null)
{
suffix = ".tmp";
}
String name = prefix +
new DecimalFormat("#####").format(new Integer(counter++)) +
suffix;
String tmpdir = System.getProperty("java.io.tmpdir");
// java.io.tmpdir is not present in 1.1
if (tmpdir == null)
return new File(name);
else
return new File(tmpdir, name);
}
/**
* 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 = createTempFile("ant", null);
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();
File outFile = null;
// die if cabarc fails
exec.setFailonerror(true);
exec.setDir(baseDir);
if (!doVerbose)
{
outFile = createTempFile("ant", null);
exec.setOutput(outFile);
}
exec.setCommand(createCommand(listFile));
exec.execute();
if (outFile != null)
{
outFile.delete();
}
listFile.delete();
} catch (IOException ioe) {
String msg = "Problem creating " + cabFile + " " + ioe.getMessage();
throw new BuildException(msg);
}
}
}