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="#antstructure">AntStructure</a></li> | ||||
<li><a href="#available">Available</a></li> | <li><a href="#available">Available</a></li> | ||||
<li><a href="#chmod">Chmod</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="#copydir">Copydir</a></li> | ||||
<li><a href="#copyfile">Copyfile</a></li> | <li><a href="#copyfile">Copyfile</a></li> | ||||
<li><a href="#cvs">Cvs</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="#javadoc">Javadoc/Javadoc2</a></li> | ||||
<li><a href="#mail">Mail</a></li> | <li><a href="#mail">Mail</a></li> | ||||
<li><a href="#mkdir">Mkdir</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="#patch">Patch</a></li> | ||||
<li><a href="#property">Property</a></li> | <li><a href="#property">Property</a></li> | ||||
<li><a href="#rename">Rename</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 | with <code>id</code> <code>other.shared.sources</code> get the same | ||||
permissions.</p> | permissions.</p> | ||||
<hr> | <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> | <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> | <h3>Description</h3> | ||||
<p>Copies a directory tree from the source to the destination.</p> | <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 | <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> | directory.</p> | ||||
<hr> | <hr> | ||||
<h2><a name="copyfile">Copyfile</a></h2> | <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> | <h3>Description</h3> | ||||
<p>Copies a file from the source to the destination. The file is only copied if | <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 | 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> | <hr> | ||||
<h2><a name="delete">Delete</a></h2> | <h2><a name="delete">Delete</a></h2> | ||||
<h3>Description</h3> | <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> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -1427,57 +1503,59 @@ nested <code><include></code>, <code><exclude></code> and | |||||
<td valign="top">dir</td> | <td valign="top">dir</td> | ||||
<td valign="top">The directory to delete files from.</td> | <td valign="top">The directory to delete files from.</td> | ||||
</tr> | </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> | <tr> | ||||
<td valign="top">includes</td> | <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 | deleted. All files are in the current directory | ||||
and any sub-directories are deleted when omitted.</td> | and any sub-directories are deleted when omitted.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">includesfile</td> | <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> | taken to be an include pattern</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">excludes</td> | <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> | excluded from the deletion list. No files (except default excludes) are excluded when omitted.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">excludesfile</td> | <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> | taken to be an exclude pattern</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">defaultexcludes</td> | <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> | ("yes"/"no"). Default excludes are used when omitted.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </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> | </table> | ||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <delete file="/lib/ant.jar" /></pre> | <pre> <delete file="/lib/ant.jar" /></pre> | ||||
<p>deletes the file <code>/lib/ant.jar</code>.</p> | <p>deletes the file <code>/lib/ant.jar</code>.</p> | ||||
<pre> <delete dir="lib" /></pre> | <pre> <delete dir="lib" /></pre> | ||||
<p>deletes all files in the <code>/lib</code> directory.</p> | <p>deletes all files in the <code>/lib</code> directory.</p> | ||||
<pre> <delete dir="." | |||||
includes="**/*.bak" | |||||
/> | |||||
<pre> <delete> | |||||
<fileset dir="." includes="**/*.bak" /> | |||||
</delete> | |||||
</pre> | </pre> | ||||
<p>deletes all files with the extension "<code>.bak</code>" from the current directory | <p>deletes all files with the extension "<code>.bak</code>" from the current directory | ||||
and any sub-directories.</p> | and any sub-directories.</p> | ||||
<hr> | <hr> | ||||
<h2><a name="deltree">Deltree</a></h2> | <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> | <h3>Description</h3> | ||||
<p>Deletes a directory with all its files and subdirectories.</p> | <p>Deletes a directory with all its files and subdirectories.</p> | ||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
@@ -3135,6 +3213,88 @@ necessary.</p> | |||||
<pre><mkdir dir="${dist}/lib" /></pre> | <pre><mkdir dir="${dist}/lib" /></pre> | ||||
<p>creates a directory <code>${dist}/lib</code>.</p> | <p>creates a directory <code>${dist}/lib</code>.</p> | ||||
<hr> | <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> | <h2><a name="patch">Patch</a></h2> | ||||
<h3>Description</h3> | <h3>Description</h3> | ||||
<p>Applies a diff file to originals. | <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. | implementations may use other values for the home directory on Windows. | ||||
<hr> | <hr> | ||||
<h2><a name="rename">Rename</a></h2> | <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> | <h3>Description</h3> | ||||
<p>Renames a given file.</p> | <p>Renames a given file.</p> | ||||
<h3>Parameters</h3> | <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 { | public void execute() throws BuildException { | ||||
log("DEPRECATED - The copydir task is deprecated. Use copy instead."); | |||||
if (srcDir == null) { | if (srcDir == null) { | ||||
throw new BuildException("src attribute must be set!", | throw new BuildException("src attribute must be set!", | ||||
location); | location); | ||||
@@ -89,6 +89,8 @@ public class Copyfile extends Task { | |||||
} | } | ||||
public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
log("DEPRECATED - The copyfile task is deprecated. Use copy instead."); | |||||
if (srcFile == null) { | if (srcFile == null) { | ||||
throw new BuildException("The src attribute must be present.", location); | throw new BuildException("The src attribute must be present.", location); | ||||
} | } | ||||
@@ -54,26 +54,39 @@ | |||||
package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
import org.apache.tools.ant.types.*; | |||||
import java.io.*; | 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 stefano@apache.org | ||||
* @author Tom Dimock <a href="mailto:tad1@cornell.edu">tad1@cornell.edu</a> | * @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 { | 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 int verbosity = Project.MSG_VERBOSE; | ||||
private File f = null; | |||||
/** | /** | ||||
* Set the name of a single file to be removed. | * Set the name of a single file to be removed. | ||||
* | * | ||||
* @param file the file to be deleted | * @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. | * @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" | * @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; | this.verbosity = Project.MSG_INFO; | ||||
} else { | } else { | ||||
this.verbosity = Project.MSG_VERBOSE; | 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 { | public void execute() throws BuildException { | ||||
log("DEPRECATED - The deltree task is deprecated. Use delete instead."); | |||||
if (dir == null) { | if (dir == null) { | ||||
throw new BuildException("dir attribute must be set!", location); | 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. | * thrown, if the rename operation fails. | ||||
*/ | */ | ||||
public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
log("DEPRECATED - The rename task is deprecated. Use move instead."); | |||||
if (dest == null) { | if (dest == null) { | ||||
throw new BuildException("dest attribute is required", location); | 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 | chmod=org.apache.tools.ant.taskdefs.Chmod | ||||
deltree=org.apache.tools.ant.taskdefs.Deltree | deltree=org.apache.tools.ant.taskdefs.Deltree | ||||
delete=org.apache.tools.ant.taskdefs.Delete | 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 | jar=org.apache.tools.ant.taskdefs.Jar | ||||
copydir=org.apache.tools.ant.taskdefs.Copydir | copydir=org.apache.tools.ant.taskdefs.Copydir | ||||
copyfile=org.apache.tools.ant.taskdefs.Copyfile | copyfile=org.apache.tools.ant.taskdefs.Copyfile | ||||