Copy, Move, and Delete tasks. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268051 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -846,6 +846,7 @@ same patterns as the example before.</p> | |||
| <li><a href="#antstructure">AntStructure</a></li> | |||
| <li><a href="#available">Available</a></li> | |||
| <li><a href="#chmod">Chmod</a></li> | |||
| <li><a href="#copy">Copy</a></li> | |||
| <li><a href="#copydir">Copydir</a></li> | |||
| <li><a href="#copyfile">Copyfile</a></li> | |||
| <li><a href="#cvs">Cvs</a></li> | |||
| @@ -867,6 +868,7 @@ same patterns as the example before.</p> | |||
| <li><a href="#javadoc">Javadoc/Javadoc2</a></li> | |||
| <li><a href="#mail">Mail</a></li> | |||
| <li><a href="#mkdir">Mkdir</a></li> | |||
| <li><a href="#move">Move</a></li> | |||
| <li><a href="#patch">Patch</a></li> | |||
| <li><a href="#property">Property</a></li> | |||
| <li><a href="#rename">Rename</a></li> | |||
| @@ -1172,7 +1174,91 @@ group on a UNIX system. In addition all files belonging to a FileSet | |||
| with <code>id</code> <code>other.shared.sources</code> get the same | |||
| permissions.</p> | |||
| <hr> | |||
| <h2><a name="copy">Copy</a></h2> | |||
| <h3>Description</h3> | |||
| <p>Copies a file or directory to a new file or directory. Files are | |||
| only copied if the source file is newer than the destination file, | |||
| or when the destination file does not exist. However, you can explicitly | |||
| overwrite files with the <var>overwrite</var> attribute.</p> | |||
| <p><a href="#fileset">FileSet</a>s are used to select files to copy. | |||
| To use a fileset, the <var>todir</var> attribute must be set.</p> | |||
| <h3>Parameters</h3> | |||
| <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">file</td> | |||
| <td valign="top">the file to copy</td> | |||
| <td valign="top" align="center" rowspan="2">One of <var>file</var> or | |||
| <var>dir</var> are required, or at least one nested fileset element.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">dir</td> | |||
| <td valign="top">the directory to copy</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">tofile</td> | |||
| <td valign="top">the file to copy to</td> | |||
| <td valign="top" align="center" rowspan="2">With the <var>file</var> attribute, | |||
| either <var>tofile</var> or <var>todir</var> can be used. With the <var>dir</var> | |||
| attribute and nested filesets, only <var>todir</var> is allowed.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">todir</td> | |||
| <td valign="top">the directory to copy to</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">overwrite</td> | |||
| <td valign="top">overwrite existing files even if the destination | |||
| files are newer (default is no)</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">filtering</td> | |||
| <td valign="top">indicates whether token filtering should take place during | |||
| the copy (default is no)</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">flatten</td> | |||
| <td valign="top">ignore directory structure of source directory, | |||
| copy all files into a single directory, specified by the <var>todir</var> | |||
| attribute (default is false)</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Examples</h3> | |||
| <p><b>Copy a single file</b></p> | |||
| <pre> | |||
| <copy file="myfile.txt" tofile="mycopy.txt" /> | |||
| </pre> | |||
| <p><b>Copy a file to a directory</b></p> | |||
| <pre> | |||
| <copy file="myfile.txt" todir="../some/dir/tree" /> | |||
| </pre> | |||
| <p><b>Copy a directory to another directory</b></p> | |||
| <pre> | |||
| <copy dir="src_dir" todir="../new/dir" /> | |||
| </pre> | |||
| <p><b>Copy a set of files to a directory</b></p> | |||
| <pre> | |||
| <copy todir="../dest/dir" > | |||
| <fileset dir="src_dir" > | |||
| <exclude name="**/*.java" /> | |||
| </fileset> | |||
| </copy> | |||
| <copy todir="../dest/dir" > | |||
| <fileset dir="src_dir" excludes="**/*.java" /> | |||
| </copy> | |||
| </pre> | |||
| <hr> | |||
| <h2><a name="copydir">Copydir</a></h2> | |||
| <h3><i>Deprecated</i></h3> | |||
| <p><i>This task has been deprecated. Use the Copy task instead.</i></p> | |||
| <h3>Description</h3> | |||
| <p>Copies a directory tree from the source to the destination.</p> | |||
| <p>It is possible to refine the set of files that are being copied. This can be | |||
| @@ -1277,6 +1363,8 @@ recursively. All java files are copied, except for the files under the <code>myp | |||
| directory.</p> | |||
| <hr> | |||
| <h2><a name="copyfile">Copyfile</a></h2> | |||
| <h3><i>Deprecated</i></h3> | |||
| <p><i>This task has been deprecated. Use the Copy task instead.</i></p> | |||
| <h3>Description</h3> | |||
| <p>Copies a file from the source to the destination. The file is only copied if | |||
| the source file is newer than the destination file, or when the destination file | |||
| @@ -1396,21 +1484,9 @@ repository pointed to by the cvsRoot attribute, and stores the files in "${ | |||
| <hr> | |||
| <h2><a name="delete">Delete</a></h2> | |||
| <h3>Description</h3> | |||
| <p>Deletes either a single file or | |||
| all files in a specified directory and its sub-directories.</p> | |||
| <p>It is possible to refine the set of files that are being deleted. This can be | |||
| done with the <i>includes</i>, <i>includesfile</i>, <i>excludes</i>, <i>excludesfile</i> and <i>defaultexcludes</i> | |||
| attributes. With the <i>includes</i> or <i>includesfile</i> attribute you specify the files you want to | |||
| have included in the deletion process by using patterns. The <i>exclude</i> or <i>excludesfile</i> attribute is used to specify | |||
| the files you want to have excluded from the deletion process. This is also done with patterns. And | |||
| finally with the <i>defaultexcludes</i> attribute, you can specify whether you | |||
| want to use default exclusions or not. See the section on <a | |||
| href="#directorybasedtasks">directory based tasks</a>, on how the | |||
| inclusion/exclusion of files works, and how to write patterns.</p> | |||
| <p>This task forms an implicit <a href="#fileset">FileSet</a> and | |||
| supports all attributes of <code><fileset></code> as well as the | |||
| nested <code><include></code>, <code><exclude></code> and | |||
| <code><patternset></code> elements.</p> | |||
| <p>Deletes either a single file, all files in a specified directory and its | |||
| sub-directories, or a set of files specified by one or more <a href="#fileset">FileSet</a>s. | |||
| When specifying a set of files, empty directories are <em>not</em> removed.</p> | |||
| <h3>Parameters</h3> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| @@ -1427,57 +1503,59 @@ nested <code><include></code>, <code><exclude></code> and | |||
| <td valign="top">dir</td> | |||
| <td valign="top">The directory to delete files from.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">verbose</td> | |||
| <td valign="top">Show name of each deleted file ("true"/"false"). | |||
| Default is "false" when omitted.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">includes</td> | |||
| <td valign="top">Comma separated list of patterns of files that must be | |||
| <td valign="top"><i>Deprecated.</i> Comma separated list of patterns of files that must be | |||
| deleted. All files are in the current directory | |||
| and any sub-directories are deleted 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 | |||
| <td valign="top"><i>Deprecated.</i> 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 | |||
| <td valign="top"><i>Deprecated.</i> Comma separated list of patterns of files that must be | |||
| excluded from the deletion list. 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 | |||
| <td valign="top"><i>Deprecated.</i> 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> | |||
| <tr> | |||
| <td valign="top">defaultexcludes</td> | |||
| <td valign="top">Indicates whether default excludes should be used or not | |||
| <td valign="top"><i>Deprecated.</i> 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">verbose</td> | |||
| <td valign="top">Show name of each deleted file ("true"/"false"). | |||
| Default is "false" when omitted.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Examples</h3> | |||
| <pre> <delete file="/lib/ant.jar" /></pre> | |||
| <p>deletes the file <code>/lib/ant.jar</code>.</p> | |||
| <pre> <delete dir="lib" /></pre> | |||
| <p>deletes all files in the <code>/lib</code> directory.</p> | |||
| <pre> <delete dir="." | |||
| includes="**/*.bak" | |||
| /> | |||
| <pre> <delete> | |||
| <fileset dir="." includes="**/*.bak" /> | |||
| </delete> | |||
| </pre> | |||
| <p>deletes all files with the extension "<code>.bak</code>" from the current directory | |||
| and any sub-directories.</p> | |||
| <hr> | |||
| <h2><a name="deltree">Deltree</a></h2> | |||
| <h3><i>Deprecated</i></h3> | |||
| <p><i>This task has been deprecated. Use the Delete task instead.</i></p> | |||
| <h3>Description</h3> | |||
| <p>Deletes a directory with all its files and subdirectories.</p> | |||
| <h3>Parameters</h3> | |||
| @@ -3135,6 +3213,88 @@ necessary.</p> | |||
| <pre><mkdir dir="${dist}/lib" /></pre> | |||
| <p>creates a directory <code>${dist}/lib</code>.</p> | |||
| <hr> | |||
| <h2><a name="move">Move</a></h2> | |||
| <h3>Description</h3> | |||
| <p>Moves a file or directory to a new file or directory, or sets of files to | |||
| a new directory. By default, the | |||
| destination file is overwritten if it already exists. When <var>overwrite</var> is | |||
| turned off, then files are only moved if the source file is newer than | |||
| the destination file, or when the destination file does not exist.</p> | |||
| <p><a href="#fileset">FileSet</a>s are used to select sets of files | |||
| to move to the <var>todir</var> directory.</p> | |||
| <h3>Parameters</h3> | |||
| <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">file</td> | |||
| <td valign="top">the file to move</td> | |||
| <td valign="top" align="center" rowspan="2">One of <var>file</var> or | |||
| <var>dir</var> are required, or at least one nested fileset element</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">dir</td> | |||
| <td valign="top">the directory to move</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">tofile</td> | |||
| <td valign="top">the file to move to</td> | |||
| <td valign="top" align="center" rowspan="2">With the <var>file</var> attribute, | |||
| either <var>tofile</var> or <var>todir</var> can be used. With the <var>dir</var> | |||
| attribute or a nested fileset, only <var>todir</var> is allowed.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">todir</td> | |||
| <td valign="top">the directory to move to</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">overwrite</td> | |||
| <td valign="top">overwrite existing files even if the destination | |||
| files are newer (default is "true")</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">filtering</td> | |||
| <td valign="top">indicates whether token filtering should take place during | |||
| the move. See the <a href="#filter">filter</a> task for a description of | |||
| how filters work.</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">flatten</td> | |||
| <td valign="top">ignore directory structure of source directory, | |||
| copy all files into a single directory, specified by the <var>todir</var> | |||
| attribute (default is "false").</td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Examples</h3> | |||
| <p><b>Move a single file (rename a file)</b></p> | |||
| <pre> | |||
| <move file="file.orig" tofile="file.moved" /> | |||
| </pre> | |||
| <p><b>Move a single file to a directory</b></p> | |||
| <pre> | |||
| <move file="file.orig" todir="dir/to/move/to" /> | |||
| </pre> | |||
| <p><b>Move a directory to a new directory</b></p> | |||
| <pre> | |||
| <move dir="src/dir" todir="new/dir/to/move/to" /> | |||
| </pre> | |||
| <p>Note that the directory src/dir will be removed.</p> | |||
| <p><b>Move a set of files to a new directory</b></p> | |||
| <pre> | |||
| <move todir="some/new/dir" > | |||
| <fileset dir="my/src/dir" > | |||
| <include name="**/*.jar" /> | |||
| <exclude name="**/ant.jar" /> | |||
| </fileset> | |||
| </move> | |||
| </pre> | |||
| <hr> | |||
| <h2><a name="patch">Patch</a></h2> | |||
| <h3>Description</h3> | |||
| <p>Applies a diff file to originals. | |||
| @@ -3272,6 +3432,8 @@ JVM that I tested, the home directory on Windows is "C:\". Different | |||
| implementations may use other values for the home directory on Windows. | |||
| <hr> | |||
| <h2><a name="rename">Rename</a></h2> | |||
| <h3><i>Deprecated</i></h3> | |||
| <p><i>This task has been deprecated. Use the Move task instead.</i></p> | |||
| <h3>Description</h3> | |||
| <p>Renames a given file.</p> | |||
| <h3>Parameters</h3> | |||
| @@ -0,0 +1,285 @@ | |||
| /* | |||
| * 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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.*; | |||
| import org.apache.tools.ant.types.*; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| /** | |||
| * A consolidated copy task. Copies a file or directory to a new file | |||
| * or directory. Files are only copied if the source file is newer | |||
| * than the destination file, or when the destination file does not | |||
| * exist. It is possible to explicitly overwrite existing files.</p> | |||
| * | |||
| * <p>This implementation is based on Arnout Kuiper's initial design | |||
| * document, the following mailing list discussions, and the | |||
| * copyfile/copydir tasks.</p> | |||
| * | |||
| * @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||
| */ | |||
| public class Copy extends Task { | |||
| protected File file = null; // the source file | |||
| protected File dir = null; // the source directory | |||
| protected File destFile = null; // the destination file | |||
| protected File destDir = null; // the destination directory | |||
| protected Vector filesets = new Vector(); | |||
| protected boolean filtering = false; | |||
| protected boolean forceOverwrite = false; | |||
| protected boolean flatten = false; | |||
| protected int verbosity = Project.MSG_VERBOSE; | |||
| protected Hashtable fileCopyMap = new Hashtable(); | |||
| /** | |||
| * Sets a single source file to copy. | |||
| */ | |||
| public void setFile(File file) { | |||
| this.file = file; | |||
| } | |||
| /** | |||
| * Sets a directory to copy. | |||
| */ | |||
| public void setDir(File dir) { | |||
| this.dir = dir; | |||
| } | |||
| /** | |||
| * Sets the destination file. | |||
| */ | |||
| public void setTofile(File destFile) { | |||
| this.destFile = destFile; | |||
| } | |||
| /** | |||
| * Sets the destination directory. | |||
| */ | |||
| public void setTodir(File destDir) { | |||
| this.destDir = destDir; | |||
| } | |||
| /** | |||
| * Sets filtering. | |||
| */ | |||
| public void setFiltering(boolean filtering) { | |||
| this.filtering = filtering; | |||
| } | |||
| /** | |||
| * Overwrite any existing destination file(s). | |||
| */ | |||
| public void setOverwrite(boolean overwrite) { | |||
| this.forceOverwrite = overwrite; | |||
| } | |||
| /** | |||
| * When copying directory trees, the files can be "flattened" | |||
| * into a single directory. If there are multiple files with | |||
| * the same name in the source directory tree, only the first | |||
| * file will be copied into the "flattened" directory, unless | |||
| * the forceoverwrite attribute is true. | |||
| */ | |||
| public void setFlatten(boolean flatten) { | |||
| this.flatten = flatten; | |||
| } | |||
| /** | |||
| * Used to force listing of all names of copied files. | |||
| */ | |||
| public void setVerbose(boolean verbose) { | |||
| if (verbose) { | |||
| this.verbosity = Project.MSG_INFO; | |||
| } else { | |||
| this.verbosity = Project.MSG_VERBOSE; | |||
| } | |||
| } | |||
| /** | |||
| * Adds a set of files (nested fileset attribute). | |||
| */ | |||
| public void addFileset(FileSet set) { | |||
| filesets.addElement(set); | |||
| } | |||
| /** | |||
| * Performs the copy operation. | |||
| */ | |||
| public void execute() throws BuildException { | |||
| // make sure we don't have an illegal set of options | |||
| validateAttributes(); | |||
| // deal with the single file | |||
| if (file != null) { | |||
| if (destFile == null) { | |||
| destFile = new File(destDir, file.getName()); | |||
| } | |||
| if (forceOverwrite || | |||
| (file.lastModified() > destFile.lastModified())) { | |||
| fileCopyMap.put(file.getAbsolutePath(), destFile.getAbsolutePath()); | |||
| } | |||
| } | |||
| // deal with the directory | |||
| if (dir != null) { | |||
| DirectoryScanner ds = new DirectoryScanner(); | |||
| ds.setBasedir(dir); | |||
| ds.scan(); // include EVERYTHING | |||
| String[] srcFiles = ds.getIncludedFiles(); | |||
| scan(dir, destDir, srcFiles); // add to fileCopyMap | |||
| } | |||
| // deal with the filesets | |||
| for (int i=0; i<filesets.size(); i++) { | |||
| FileSet fs = (FileSet) filesets.elementAt(i); | |||
| DirectoryScanner ds = fs.getDirectoryScanner(project); | |||
| String[] srcFiles = ds.getIncludedFiles(); | |||
| scan(fs.getDir(project), destDir, srcFiles); // add to fileCopyMap | |||
| } | |||
| // do all the copy operations now... | |||
| doFileOperations(); | |||
| } | |||
| //************************************************************************ | |||
| // protected and private methods | |||
| //************************************************************************ | |||
| /** | |||
| * Ensure we have a consistent and legal set of attributes, and set | |||
| * any internal flags necessary based on different combinations | |||
| * of attributes. | |||
| */ | |||
| protected void validateAttributes() throws BuildException { | |||
| if (file == null && dir == null && filesets.size() == 0) { | |||
| throw new BuildException("Specify at least one source - a file, a dir, or a fileset."); | |||
| } | |||
| if (destFile != null && destDir != null) { | |||
| throw new BuildException("Only one of destfile and destdir may be set."); | |||
| } | |||
| if (destFile == null && destDir == null) { | |||
| throw new BuildException("One of destfile or destdir must be set."); | |||
| } | |||
| if (dir != null && destFile != null) { | |||
| throw new BuildException("Cannot copy a directory into a file."); | |||
| } | |||
| if (destFile != null && filesets.size() > 0) { | |||
| throw new BuildException("Cannot concatenate multple files into a single file."); | |||
| } | |||
| if (destFile != null) { | |||
| destDir = new File(destFile.getParent()); // be 1.1 friendly | |||
| } | |||
| } | |||
| /** | |||
| * Compares source files to destination files to see if they should be | |||
| * copied. | |||
| */ | |||
| protected void scan(File fromDir, File toDir, String[] files) { | |||
| for (int i = 0; i < files.length; i++) { | |||
| String filename = files[i]; | |||
| File src = new File(fromDir, filename); | |||
| File dest; | |||
| if (flatten) { | |||
| dest = new File(toDir, new File(filename).getName()); | |||
| } else { | |||
| dest = new File(toDir, filename); | |||
| } | |||
| if (forceOverwrite || | |||
| (src.lastModified() > dest.lastModified())) { | |||
| fileCopyMap.put(src.getAbsolutePath(), | |||
| dest.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| protected void doFileOperations() { | |||
| if (fileCopyMap.size() > 0) { | |||
| log("Copying " + fileCopyMap.size() + " files to " + | |||
| destDir.getAbsolutePath() ); | |||
| Enumeration e = fileCopyMap.keys(); | |||
| while (e.hasMoreElements()) { | |||
| String fromFile = (String) e.nextElement(); | |||
| String toFile = (String) fileCopyMap.get(fromFile); | |||
| try { | |||
| log("Copying " + fromFile + " to " + toFile, verbosity); | |||
| project.copyFile(fromFile, | |||
| toFile, | |||
| filtering, | |||
| forceOverwrite); | |||
| } catch (IOException ioe) { | |||
| String msg = "Failed to copy " + fromFile + " to " + toFile | |||
| + " due to " + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe, location); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -95,6 +95,8 @@ public class Copydir extends MatchingTask { | |||
| } | |||
| public void execute() throws BuildException { | |||
| log("DEPRECATED - The copydir task is deprecated. Use copy instead."); | |||
| if (srcDir == null) { | |||
| throw new BuildException("src attribute must be set!", | |||
| location); | |||
| @@ -89,6 +89,8 @@ public class Copyfile extends Task { | |||
| } | |||
| public void execute() throws BuildException { | |||
| log("DEPRECATED - The copyfile task is deprecated. Use copy instead."); | |||
| if (srcFile == null) { | |||
| throw new BuildException("The src attribute must be present.", location); | |||
| } | |||
| @@ -54,26 +54,39 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.*; | |||
| import org.apache.tools.ant.types.*; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| /** | |||
| * Deletes a single file or a set of files defined by a pattern. | |||
| * Deletes a file or directory, or set of files defined by a fileset. | |||
| * The original delete task would delete a file, or a set of files | |||
| * using the include/exclude syntax. The deltree task would delete a | |||
| * directory tree. This task combines the functionality of these two | |||
| * originally distinct tasks. | |||
| * <p>Currently Delete extends MatchingTask. This is intend <i>only</i> | |||
| * to provide backwards compatibility for a release. The future position | |||
| * is to use nested filesets exclusively.</p> | |||
| * | |||
| * @author stefano@apache.org | |||
| * @author Tom Dimock <a href="mailto:tad1@cornell.edu">tad1@cornell.edu</a> | |||
| * @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||
| */ | |||
| public class Delete extends MatchingTask { | |||
| private File delDir = null; | |||
| protected File file = null; | |||
| protected File dir = null; | |||
| protected Vector filesets = new Vector(); | |||
| protected boolean usedMatchingTask = false; | |||
| private int verbosity = Project.MSG_VERBOSE; | |||
| private File f = null; | |||
| /** | |||
| * Set the name of a single file to be removed. | |||
| * | |||
| * @param file the file to be deleted | |||
| */ | |||
| public void setFile(String file) { | |||
| f = project.resolveFile(file); | |||
| public void setFile(File file) { | |||
| this.file = file; | |||
| } | |||
| /** | |||
| @@ -81,8 +94,8 @@ public class Delete extends MatchingTask { | |||
| * | |||
| * @param dir the directory path. | |||
| */ | |||
| public void setDir(String dir) { | |||
| delDir = project.resolveFile(dir); | |||
| public void setDir(File dir) { | |||
| this.dir = dir; | |||
| } | |||
| /** | |||
| @@ -90,8 +103,8 @@ public class Delete extends MatchingTask { | |||
| * | |||
| * @param verbose "true" or "on" | |||
| */ | |||
| public void setVerbose(String verbose) { | |||
| if ("true".equalsIgnoreCase(verbose.trim()) || "on".equalsIgnoreCase(verbose.trim())) { | |||
| public void setVerbose(boolean verbose) { | |||
| if (verbose) { | |||
| this.verbosity = Project.MSG_INFO; | |||
| } else { | |||
| this.verbosity = Project.MSG_VERBOSE; | |||
| @@ -99,60 +112,178 @@ public class Delete extends MatchingTask { | |||
| } | |||
| /** | |||
| * Make it so. Delete the file(s). | |||
| * | |||
| * @throws BuildException | |||
| * Adds a set of files (nested fileset attribute). | |||
| */ | |||
| public void execute() throws BuildException { | |||
| if (f == null && delDir == null) { | |||
| throw new BuildException("<file> or <dir> attribute must be set!"); | |||
| } | |||
| public void addFileset(FileSet set) { | |||
| filesets.addElement(set); | |||
| } | |||
| /** | |||
| * add a name entry on the include list | |||
| */ | |||
| public PatternSet.NameEntry createInclude() { | |||
| usedMatchingTask = true; | |||
| return super.createInclude(); | |||
| } | |||
| /** | |||
| * add a name entry on the exclude list | |||
| */ | |||
| public PatternSet.NameEntry createExclude() { | |||
| usedMatchingTask = true; | |||
| return super.createExclude(); | |||
| } | |||
| // old <delete> functionality must still work | |||
| if (f != null) { | |||
| if (f.exists()) { | |||
| if (f.isDirectory()) { | |||
| log("Directory: " + f.getAbsolutePath() + " cannot be removed with delete. Use Deltree instead."); | |||
| } else { | |||
| log("Deleting: " + f.getAbsolutePath()); | |||
| /** | |||
| * add a set of patterns | |||
| */ | |||
| public PatternSet createPatternSet() { | |||
| usedMatchingTask = true; | |||
| return super.createPatternSet(); | |||
| } | |||
| if (!f.delete()) { | |||
| throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Sets the set of include patterns. Patterns may be separated by a comma | |||
| * or a space. | |||
| * | |||
| * @param includes the string containing the include patterns | |||
| */ | |||
| public void setIncludes(String includes) { | |||
| usedMatchingTask = true; | |||
| super.setIncludes(includes); | |||
| } | |||
| // now we'll do the fancy pattern-driven deletes | |||
| if (delDir == null) { | |||
| return; | |||
| } | |||
| /** | |||
| * Sets the set of exclude patterns. Patterns may be separated by a comma | |||
| * or a space. | |||
| * | |||
| * @param excludes the string containing the exclude patterns | |||
| */ | |||
| public void setExcludes(String excludes) { | |||
| usedMatchingTask = true; | |||
| super.setExcludes(excludes); | |||
| } | |||
| if (!delDir.exists()) { | |||
| throw new BuildException("dir does not exist!"); | |||
| } | |||
| /** | |||
| * Sets whether default exclusions should be used or not. | |||
| * | |||
| * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions | |||
| * should be used, "false"|"off"|"no" when they | |||
| * shouldn't be used. | |||
| */ | |||
| public void setDefaultexcludes(boolean useDefaultExcludes) { | |||
| usedMatchingTask = true; | |||
| super.setDefaultexcludes(useDefaultExcludes); | |||
| } | |||
| DirectoryScanner ds = super.getDirectoryScanner(delDir); | |||
| String[] files = ds.getIncludedFiles(); | |||
| /** | |||
| * Sets the name of the file containing the includes patterns. | |||
| * | |||
| * @param includesfile A string containing the filename to fetch | |||
| * the include patterns from. | |||
| */ | |||
| public void setIncludesfile(File includesfile) { | |||
| usedMatchingTask = true; | |||
| super.setIncludesfile(includesfile); | |||
| } | |||
| if (files.length > 0) { | |||
| log("Deleting " + files.length + " file" | |||
| + (files.length == 1 ? "" : "s") | |||
| + " from " + delDir.getAbsolutePath()); | |||
| /** | |||
| * Sets the name of the file containing the includes patterns. | |||
| * | |||
| * @param excludesfile A string containing the filename to fetch | |||
| * the include patterns from. | |||
| */ | |||
| public void setExcludesfile(File excludesfile) { | |||
| usedMatchingTask = true; | |||
| super.setExcludesfile(excludesfile); | |||
| } | |||
| for (int i = 0; i < files.length; i++) { | |||
| File f = new File(delDir, files[i]); | |||
| /** | |||
| * Delete the file(s). | |||
| */ | |||
| public void execute() throws BuildException { | |||
| if (usedMatchingTask) { | |||
| log("DEPRECATED - Use of the implicit FileSet is deprecated. Use a nested fileset element instead."); | |||
| } | |||
| if (f.exists()) { | |||
| log("Deleting: " + f.getAbsolutePath(), verbosity); | |||
| if (file == null && dir == null && filesets.size() == 0) { | |||
| throw new BuildException("At least one of the file or dir attributes, or a fileset element, must be set."); | |||
| } | |||
| if (!f.delete()) { | |||
| throw new BuildException("Unable to delete " + f.getAbsolutePath()); | |||
| // delete the single file | |||
| if (file != null) { | |||
| if (file.exists()) { | |||
| if (file.isDirectory()) { | |||
| log("Directory " + file.getAbsolutePath() + " cannot be removed using the file attribute. Use dir instead."); | |||
| } else { | |||
| log("Deleting: " + file.getAbsolutePath()); | |||
| if (!file.delete()) { | |||
| throw new BuildException("Unable to delete file " + file.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| log("Could not find file " + file.getAbsolutePath() + " to delete."); | |||
| } | |||
| } | |||
| // delete the directory | |||
| if (dir != null && !usedMatchingTask) { | |||
| log("Deleting directory " + dir.getAbsolutePath()); | |||
| removeDir(dir); | |||
| } | |||
| // delete the files in the filesets | |||
| for (int i=0; i<filesets.size(); i++) { | |||
| FileSet fs = (FileSet) filesets.elementAt(i); | |||
| DirectoryScanner ds = fs.getDirectoryScanner(project); | |||
| String[] files = ds.getIncludedFiles(); | |||
| removeFiles(fs.getDir(project), files); | |||
| } | |||
| // delete the files from the default fileset | |||
| if (usedMatchingTask && dir != null) { | |||
| DirectoryScanner ds = super.getDirectoryScanner(dir); | |||
| String [] files = ds.getIncludedFiles(); | |||
| removeFiles(dir, files); | |||
| } | |||
| } | |||
| //************************************************************************ | |||
| // protected and private methods | |||
| //************************************************************************ | |||
| protected void removeDir(File d) { | |||
| String[] list = d.list(); | |||
| for (int i = 0; i < list.length; i++) { | |||
| String s = list[i]; | |||
| File f = new File(d, s); | |||
| if (f.isDirectory()) { | |||
| removeDir(f); | |||
| } else { | |||
| log("Deleting " + f.getAbsolutePath(), verbosity); | |||
| if (!f.delete()) { | |||
| throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| log("Deleting directory " + d.getAbsolutePath(), verbosity); | |||
| if (!d.delete()) { | |||
| throw new BuildException("Unable to delete directory " + dir.getAbsolutePath()); | |||
| } | |||
| } | |||
| protected void removeFiles(File d, String[] files) { | |||
| if (files.length > 0) { | |||
| log("Deleting " + files.length + " files from " + d.getAbsolutePath()); | |||
| for (int j=0; j<files.length; j++) { | |||
| File f = new File(d, files[j]); | |||
| log("Deleting " + f.getAbsolutePath(), verbosity); | |||
| if (!f.delete()) { | |||
| throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -72,6 +72,8 @@ public class Deltree extends Task { | |||
| } | |||
| public void execute() throws BuildException { | |||
| log("DEPRECATED - The deltree task is deprecated. Use delete instead."); | |||
| if (dir == null) { | |||
| throw new BuildException("dir attribute must be set!", location); | |||
| } | |||
| @@ -0,0 +1,146 @@ | |||
| /* | |||
| * 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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.*; | |||
| import org.apache.tools.ant.types.*; | |||
| import java.io.*; | |||
| import java.util.*; | |||
| /** | |||
| * Moves a file or directory to a new file or directory. By default, | |||
| * the destination is overwriten when existing. When overwrite is | |||
| * turned off, then files are only moved if the source file is | |||
| * newer than the destination file, or when the destination file does | |||
| * not exist.</p> | |||
| * | |||
| * <p>Source files and directories are only deleted when the file or | |||
| * directory has been copied to the destination successfully. Filtering | |||
| * also works.</p> | |||
| * | |||
| * <p>This implementation is based on Arnout Kuiper's initial design | |||
| * document, the following mailing list discussions, and the | |||
| * copyfile/copydir tasks.</p> | |||
| * | |||
| * @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||
| */ | |||
| public class Move extends Copy { | |||
| public Move() { | |||
| super(); | |||
| forceOverwrite = true; | |||
| } | |||
| public void execute() throws BuildException { | |||
| super.execute(); | |||
| // take care of the source directory | |||
| if (dir != null && dir.exists()) { | |||
| deleteDir(dir); | |||
| } | |||
| } | |||
| //************************************************************************ | |||
| // protected and private methods | |||
| //************************************************************************ | |||
| protected void doFileOperations() { | |||
| if (fileCopyMap.size() > 0) { | |||
| log("Moving " + fileCopyMap.size() + " files to " + | |||
| destDir.getAbsolutePath() ); | |||
| Enumeration e = fileCopyMap.keys(); | |||
| while (e.hasMoreElements()) { | |||
| String fromFile = (String) e.nextElement(); | |||
| String toFile = (String) fileCopyMap.get(fromFile); | |||
| try { | |||
| log("Moving " + fromFile + " to " + toFile, verbosity); | |||
| project.copyFile(fromFile, | |||
| toFile, | |||
| filtering, | |||
| forceOverwrite); | |||
| File f = new File(fromFile); | |||
| if (!f.delete()) { | |||
| throw new BuildException("Unable to delete file " + f.getAbsolutePath()); | |||
| } | |||
| } catch (IOException ioe) { | |||
| String msg = "Failed to copy " + fromFile + " to " + toFile | |||
| + " due to " + ioe.getMessage(); | |||
| throw new BuildException(msg, ioe, location); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| protected void deleteDir(File d) { | |||
| String[] list = d.list(); | |||
| for (int i = 0; i < list.length; i++) { | |||
| String s = list[i]; | |||
| File f = new File(d, s); | |||
| if (f.isDirectory()) { | |||
| deleteDir(f); | |||
| } else { | |||
| throw new BuildException("UNEXPECTED ERROR - The file " + f.getAbsolutePath() + " should not exist!"); | |||
| } | |||
| } | |||
| log("Deleting directory " + d.getAbsolutePath(), verbosity); | |||
| if (!d.delete()) { | |||
| throw new BuildException("Unable to delete directory " + dir.getAbsolutePath()); | |||
| } | |||
| } | |||
| } | |||
| @@ -102,6 +102,8 @@ public class Rename extends Task { | |||
| * thrown, if the rename operation fails. | |||
| */ | |||
| public void execute() throws BuildException { | |||
| log("DEPRECATED - The rename task is deprecated. Use move instead."); | |||
| if (dest == null) { | |||
| throw new BuildException("dest attribute is required", location); | |||
| } | |||
| @@ -4,6 +4,8 @@ javac=org.apache.tools.ant.taskdefs.Javac | |||
| chmod=org.apache.tools.ant.taskdefs.Chmod | |||
| deltree=org.apache.tools.ant.taskdefs.Deltree | |||
| delete=org.apache.tools.ant.taskdefs.Delete | |||
| copy=org.apache.tools.ant.taskdefs.Copy | |||
| move=org.apache.tools.ant.taskdefs.Move | |||
| jar=org.apache.tools.ant.taskdefs.Jar | |||
| copydir=org.apache.tools.ant.taskdefs.Copydir | |||
| copyfile=org.apache.tools.ant.taskdefs.Copyfile | |||