PR: 1763 Merge <apply> and <execon> into a single task (and keep Transform as an empty class for backwards compatibility at the source level). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269330 13f79535-47bb-0310-9956-ffa450edef68master
@@ -108,6 +108,8 @@ Other changes: | |||||
* New update attribute for <zip> and friends - update an existing | * New update attribute for <zip> and friends - update an existing | ||||
archive instead of creating a new one. | archive instead of creating a new one. | ||||
* <apply> and <execon> have been merged into a single task. | |||||
Fixed bugs: | Fixed bugs: | ||||
----------- | ----------- | ||||
@@ -175,6 +177,9 @@ Fixed bugs: | |||||
* <junit> tries to include all necessary classes for the task itself | * <junit> tries to include all necessary classes for the task itself | ||||
to the classpath when running in fork mode - doesn't work for JDK 1.1 | to the classpath when running in fork mode - doesn't work for JDK 1.1 | ||||
* <apply> and <execon> do now execute the command only once, if you | |||||
specify the parallel attribute - instead of once per fileset. | |||||
Changes from Ant 1.2 to Ant 1.3 | Changes from Ant 1.2 to Ant 1.3 | ||||
=========================================== | =========================================== | ||||
@@ -7,17 +7,23 @@ | |||||
<body> | <body> | ||||
<h2><a name="apply">Apply</a></h2> | |||||
<h2><a name="apply">Apply/<i>ExecOn</i></a></h2> | |||||
<p><i>The name execon is deprecated and only kept for backwards | |||||
compatibilty.</i></p> | |||||
<h3>Description</h3> | <h3>Description</h3> | ||||
<p>Executes a system command. When the <i>os</i> attribute is specified, then | <p>Executes a system command. When the <i>os</i> attribute is specified, then | ||||
the command is only executed when Ant is run on one of the specified operating | the command is only executed when Ant is run on one of the specified operating | ||||
systems.</p> | systems.</p> | ||||
<p>The files and/or directories of a number of <a | <p>The files and/or directories of a number of <a | ||||
href="../CoreTypes/fileset.html">FileSet</a>s are passed as arguments to the system | |||||
command. The timestamp of each source file is compared to the | |||||
timestamp of a target file which is defined by a nested <a | |||||
href="../CoreTypes/mapper.html">mapper</a> element. At least one fileset and exactly | |||||
one mapper element are required.</p> | |||||
href="../CoreTypes/fileset.html">FileSet</a>s are passed as arguments | |||||
to the system command.</p> | |||||
<p>If you specify a nested <a | |||||
href="../CoreTypes/mapper.html">mapper</a> and the destdir attribute, | |||||
the timestamp of each source file is compared to the timestamp of a | |||||
target file which is defined by the nested mapper element and searched | |||||
for in the given destdir.</p> | |||||
<p>At least one fileset is required, you must not specify more than | |||||
one mapper.</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -36,7 +42,7 @@ one mapper element are required.</p> | |||||
<td valign="top">the directory where the <apply> expects the target files will be placed by the | <td valign="top">the directory where the <apply> expects the target files will be placed by the | ||||
command, when it is executed. | command, when it is executed. | ||||
</td> | </td> | ||||
<td align="center" valign="top">Yes</td> | |||||
<td align="center" valign="top">Yes, if you specify a nested mapper</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">dir</td> | <td valign="top">dir</td> | ||||
@@ -67,12 +73,6 @@ one mapper element are required.</p> | |||||
returncode other than 0.</td> | returncode other than 0.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">newenvironment</td> | |||||
<td valign="top">Do not propagate old environment when new environment | |||||
variables are specified.</td> | |||||
<td align="center" valign="top">No, default is <i>false</i></td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">skipemptyfilesets</td> | <td valign="top">skipemptyfilesets</td> | ||||
<td valign="top">Don't run the command, if no source files have | <td valign="top">Don't run the command, if no source files have | ||||
@@ -95,6 +95,23 @@ one mapper element are required.</p> | |||||
the names of directories are considered.</td> | the names of directories are considered.</td> | ||||
<td align="center" valign="top">No, default is <i>file</i></td> | <td align="center" valign="top">No, default is <i>file</i></td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">newenvironment</td> | |||||
<td valign="top">Do not propagate old environment when new environment | |||||
variables are specified.</td> | |||||
<td align="center" valign="top">No, default is <i>false</i></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">vmlauncher</td> | |||||
<td valign="top">Run command using the Java VM's execution facilities | |||||
where available. If set to false the underlying OS's shell, | |||||
either directly or through the antRun scripts, will be used. | |||||
Under some operating systems, this gives access to facilities | |||||
not normally available through the VM including, under Windows, | |||||
being able to execute scripts, rather than their associated | |||||
interpreter.</td> | |||||
<td align="center" valign="top">No, default is <i>true</i></td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
<h4>fileset</h4> | <h4>fileset</h4> | ||||
@@ -114,7 +131,9 @@ use a nested <code><srcfile></code> element between your | |||||
<p><code><targetfile></code> is similar to | <p><code><targetfile></code> is similar to | ||||
<code><srcfile></code> and marks the position of the target | <code><srcfile></code> and marks the position of the target | ||||
filename on the command line. If omitted, the target filenames will | filename on the command line. If omitted, the target filenames will | ||||
not be added to the command line at all.</p> | |||||
not be added to the command line at all. This element can only be | |||||
specified, if you also define a nested mapper and the destdir | |||||
attribute.</p> | |||||
<h4>env</h4> | <h4>env</h4> | ||||
<p>It is possible to specify environment variables to pass to the | <p>It is possible to specify environment variables to pass to the | ||||
system command via nested <code><env></code> elements. See the | system command via nested <code><env></code> elements. See the | ||||
@@ -124,6 +143,34 @@ description in the section about <a href="exec.html#env">exec</a></p> | |||||
<code><env></code>.</p> | <code><env></code>.</p> | ||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<blockquote><pre> | <blockquote><pre> | ||||
<apply executable="ls" > | |||||
<arg value="-l"/> | |||||
<fileset dir="/tmp"> | |||||
<patternset> | |||||
<exclude name="**/*.txt"/> | |||||
</patternset> | |||||
</fileset> | |||||
<fileset refid="other.files"/> | |||||
</apply> | |||||
</pre></blockquote> | |||||
<p>invokes <code>ls -l</code>, adding the absolute filenames of all | |||||
files below <code>/tmp</code> not ending in <code>.txt</code> and all | |||||
files of the FileSet with <code>id</code> <code>other.files</code> to | |||||
the command line.</p> | |||||
<blockquote><pre> | |||||
<apply executable="somecommand" parallel="false" > | |||||
<arg value="arg1"/> | |||||
<srfile/> | |||||
<arg value="arg2"/> | |||||
<fileset dir="/tmp"/> | |||||
</apply> | |||||
</pre></blockquote> | |||||
<p>invokes <code>somecommand arg1 SOURCEFILENAME arg2</code> for each | |||||
file in <code>/tmp</code> replacing SOURCEFILENAME with the absolute | |||||
filename of each file in turn. If <code>parallel</code> had been set | |||||
to true, SOURCEFILENAME would be replaced with the absolute filenames | |||||
of all files separated by spaces.</p> | |||||
<blockquote><pre> | |||||
<apply executable="cc" dest="src/C" parallel="false"> | <apply executable="cc" dest="src/C" parallel="false"> | ||||
<arg value="-c"/> | <arg value="-c"/> | ||||
<arg value="-o"/> | <arg value="-o"/> | ||||
@@ -1,156 +0,0 @@ | |||||
<html> | |||||
<head> | |||||
<meta http-equiv="Content-Language" content="en-us"> | |||||
<title>Ant User Manual</title> | |||||
</head> | |||||
<body> | |||||
<h2><a name="execon">ExecOn</a></h2> | |||||
<h3>Description</h3> | |||||
<p>Executes a system command. When the <i>os</i> attribute is specified, then | |||||
the command is only executed when Ant is run on one of the specified operating | |||||
systems.</p> | |||||
<p>The files and/or directories of a number of <a | |||||
href="../CoreTypes/fileset.html">FileSet</a>s are passed as arguments to the system | |||||
command. At least one nested <code><fileset></code> is required.</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">executable</td> | |||||
<td valign="top">the command to execute without any command line | |||||
arguments.</td> | |||||
<td align="center" valign="top">Yes</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">dir</td> | |||||
<td valign="top">the directory in which the command should be executed.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">os</td> | |||||
<td valign="top">list of Operating Systems on which the command may be | |||||
executed. If the current OS's name is contained in this list, the command will | |||||
be executed. The OS's name is determined by the Java Virtual machine and is set | |||||
in the "os.name" system property.</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">output</td> | |||||
<td valign="top">the file to which the output of the command should be | |||||
redirected.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">timeout</td> | |||||
<td valign="top">Stop the command if it doesn't finish within the | |||||
specified time (given in milliseconds).</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">failonerror</td> | |||||
<td valign="top">Stop the buildprocess if the command exits with a | |||||
returncode other than 0.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">newenvironment</td> | |||||
<td valign="top">Do not propagate old environment when new environment | |||||
variables are specified.</td> | |||||
<td align="center" valign="top">No, default is <i>false</i></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">vmlauncher</td> | |||||
<td valign="top">Run command using the Java VM's execution facilities | |||||
where available. If set to false the underlying OS's shell, | |||||
either directly or through the antRun scripts, will be used. | |||||
Under some operating systems, this gives access to facilities | |||||
not nomrally available through the VM including, under Windows, | |||||
being able to execute scripts, rather than their associated | |||||
interpreter.</td> | |||||
<td align="center" valign="top">No, default is <i>true</i></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">skipemptyfilesets</td> | |||||
<td valign="top">Don't run the command, if no source files have | |||||
been found.</td> | |||||
<td align="center" valign="top">No, default is <i>false</i></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">parallel</td> | |||||
<td valign="top">Run the command only once, appending all files as | |||||
arguments. If false, command will be executed once for every file. | |||||
Defaults to false. </td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">type</td> | |||||
<td valign="top">One of <i>file</i>, <i>dir</i> or | |||||
<i>both</i>. If set to <i>file</i>, only the names of plain | |||||
files will be sent to the command. If set to <i>dir</i>, only | |||||
the names of directories are considered.</td> | |||||
<td align="center" valign="top">No, default is <i>file</i></td> | |||||
</tr> | |||||
</table> | |||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>fileset</h4> | |||||
<p>You can use any number of nested <code><fileset></code> | |||||
elements to define the files for this task and refer to | |||||
<code><fileset></code>s defined elsewhere.</p> | |||||
<h4>arg</h4> | |||||
<p>Command line arguments should be specified as nested | |||||
<code><arg></code> elements. See <a | |||||
href="../using.html#arg">Command line arguments</a>.</p> | |||||
<h4>srcfile</h4> | |||||
<p>By default the file names of the source files will be added to the | |||||
end of the command line. If you need to place it somewhere different, | |||||
use a nested <code><srcfile></code> element between your | |||||
<code><arg></code> elements to mark the insertion point.</p> | |||||
<h4>env</h4> | |||||
<p>It is possible to specify environment variables to pass to the | |||||
system command via nested <code><env></code> elements. See the | |||||
description in the section about <a href="exec.html#env">exec</a></p> | |||||
<p>Please note that the environment of the current Ant process is | |||||
<b>not</b> passed to the system command if you specify variables using | |||||
<code><env></code>.</p> | |||||
<h3>Examples</h3> | |||||
<blockquote><pre> | |||||
<execon executable="ls" > | |||||
<arg value="-l"/> | |||||
<fileset dir="/tmp"> | |||||
<patternset> | |||||
<exclude name="**/*.txt"/> | |||||
</patternset> | |||||
</fileset> | |||||
<fileset refid="other.files"/> | |||||
</execon> | |||||
</pre></blockquote> | |||||
<p>invokes <code>ls -l</code>, adding the absolute filenames of all | |||||
files below <code>/tmp</code> not ending in <code>.txt</code> and all | |||||
files of the FileSet with <code>id</code> <code>other.files</code> to | |||||
the command line.</p> | |||||
<blockquote><pre> | |||||
<execon executable="somecommand" parallel="false" > | |||||
<arg value="arg1"/> | |||||
<srfile/> | |||||
<arg value="arg2"/> | |||||
<fileset dir="/tmp"/> | |||||
</execon> | |||||
</pre></blockquote> | |||||
<p>invokes <code>somecommand arg1 SOURCEFILENAME arg2</code> for each | |||||
file in <code>/tmp</code> replacing SOURCEFILENAME with the absolute | |||||
filename of each file in turn. If <code>parallel</code> had been set | |||||
to true, SOURCEFILENAME would be replaced with the absolute filenames | |||||
of all files separated by spaces.</p> | |||||
<hr> | |||||
<p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | |||||
Reserved.</p> | |||||
</body> | |||||
</html> | |||||
@@ -23,7 +23,7 @@ | |||||
<a href="CoreTasks/ant.html">Ant</a><br> | <a href="CoreTasks/ant.html">Ant</a><br> | ||||
<a href="CoreTasks/antcall.html">AntCall</a><br> | <a href="CoreTasks/antcall.html">AntCall</a><br> | ||||
<a href="CoreTasks/antstructure.html">AntStructure</a><br> | <a href="CoreTasks/antstructure.html">AntStructure</a><br> | ||||
<a href="CoreTasks/apply.html">Apply</a><br> | |||||
<a href="CoreTasks/apply.html">Apply/<i>ExecOn</i></a><br> | |||||
<a href="CoreTasks/available.html">Available</a><br> | <a href="CoreTasks/available.html">Available</a><br> | ||||
<a href="CoreTasks/chmod.html">Chmod</a><br> | <a href="CoreTasks/chmod.html">Chmod</a><br> | ||||
<a href="CoreTasks/copy.html">Copy</a><br> | <a href="CoreTasks/copy.html">Copy</a><br> | ||||
@@ -36,7 +36,6 @@ | |||||
<a href="CoreTasks/ear.html">Ear</a><br> | <a href="CoreTasks/ear.html">Ear</a><br> | ||||
<a href="CoreTasks/echo.html">Echo</a><br> | <a href="CoreTasks/echo.html">Echo</a><br> | ||||
<a href="CoreTasks/exec.html">Exec</a><br> | <a href="CoreTasks/exec.html">Exec</a><br> | ||||
<a href="CoreTasks/execon.html">ExecOn</a><br> | |||||
<a href="CoreTasks/fail.html">Fail</a><br> | <a href="CoreTasks/fail.html">Fail</a><br> | ||||
<a href="CoreTasks/filter.html">Filter</a><br> | <a href="CoreTasks/filter.html">Filter</a><br> | ||||
<a href="CoreTasks/fixcrlf.html">FixCRLF</a><br> | <a href="CoreTasks/fixcrlf.html">FixCRLF</a><br> | ||||
@@ -56,7 +56,9 @@ package org.apache.tools.ant.taskdefs; | |||||
import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
import org.apache.tools.ant.types.*; | import org.apache.tools.ant.types.*; | ||||
import org.apache.tools.ant.util.*; | |||||
import java.util.Hashtable; | |||||
import java.util.Vector; | import java.util.Vector; | ||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
@@ -74,6 +76,15 @@ public class ExecuteOn extends ExecTask { | |||||
protected String type = "file"; | protected String type = "file"; | ||||
protected Commandline.Marker srcFilePos = null; | protected Commandline.Marker srcFilePos = null; | ||||
private boolean skipEmpty = false; | private boolean skipEmpty = false; | ||||
protected Commandline.Marker targetFilePos = null; | |||||
protected Mapper mapperElement = null; | |||||
protected FileNameMapper mapper = null; | |||||
protected File destDir = null; | |||||
/** | |||||
* Has <srcfile> been specified before <targetfile> | |||||
*/ | |||||
protected boolean srcIsFirst = true; | |||||
/** | /** | ||||
* Adds a set of files (nested fileset attribute). | * Adds a set of files (nested fileset attribute). | ||||
@@ -103,6 +114,13 @@ public class ExecuteOn extends ExecTask { | |||||
skipEmpty = skip; | skipEmpty = skip; | ||||
} | } | ||||
/** | |||||
* Set the destination directory. | |||||
*/ | |||||
public void setDest(File destDir) { | |||||
this.destDir = destDir; | |||||
} | |||||
/** | /** | ||||
* Marker that indicates where the name of the source file should | * Marker that indicates where the name of the source file should | ||||
* be put on the command line. | * be put on the command line. | ||||
@@ -116,18 +134,62 @@ public class ExecuteOn extends ExecTask { | |||||
return srcFilePos; | return srcFilePos; | ||||
} | } | ||||
/** | |||||
* Marker that indicates where the name of the target file should | |||||
* be put on the command line. | |||||
*/ | |||||
public Commandline.Marker createTargetfile() { | |||||
if (targetFilePos != null) { | |||||
throw new BuildException(taskType + " doesn\'t support multiple targetfile elements.", | |||||
location); | |||||
} | |||||
targetFilePos = cmdl.createMarker(); | |||||
srcIsFirst = (srcFilePos != null); | |||||
return targetFilePos; | |||||
} | |||||
/** | |||||
* Defines the FileNameMapper to use (nested mapper element). | |||||
*/ | |||||
public Mapper createMapper() throws BuildException { | |||||
if (mapperElement != null) { | |||||
throw new BuildException("Cannot define more than one mapper", | |||||
location); | |||||
} | |||||
mapperElement = new Mapper(project); | |||||
return mapperElement; | |||||
} | |||||
protected void checkConfiguration() { | protected void checkConfiguration() { | ||||
if ("execon".equals(taskName)) { | |||||
log("!! execon is deprecated. Use apply instead. !!"); | |||||
} | |||||
super.checkConfiguration(); | super.checkConfiguration(); | ||||
if (filesets.size() == 0) { | if (filesets.size() == 0) { | ||||
throw new BuildException("no filesets specified", location); | throw new BuildException("no filesets specified", location); | ||||
} | } | ||||
if (targetFilePos != null || mapperElement != null | |||||
|| destDir != null) { | |||||
if (mapperElement == null) { | |||||
throw new BuildException("no mapper specified", location); | |||||
} | |||||
if (mapperElement == null) { | |||||
throw new BuildException("no dest attribute specified", | |||||
location); | |||||
} | |||||
mapper = mapperElement.getImplementation(); | |||||
} | |||||
} | } | ||||
protected void runExec(Execute exe) throws BuildException { | protected void runExec(Execute exe) throws BuildException { | ||||
try { | try { | ||||
Vector fileNames = new Vector(); | |||||
Vector baseDirs = new Vector(); | |||||
for (int i=0; i<filesets.size(); i++) { | for (int i=0; i<filesets.size(); i++) { | ||||
Vector v = new Vector(); | |||||
FileSet fs = (FileSet) filesets.elementAt(i); | FileSet fs = (FileSet) filesets.elementAt(i); | ||||
File base = fs.getDir(project); | File base = fs.getDir(project); | ||||
DirectoryScanner ds = fs.getDirectoryScanner(project); | DirectoryScanner ds = fs.getDirectoryScanner(project); | ||||
@@ -135,36 +197,28 @@ public class ExecuteOn extends ExecTask { | |||||
if (!"dir".equals(type)) { | if (!"dir".equals(type)) { | ||||
String[] s = getFiles(base, ds); | String[] s = getFiles(base, ds); | ||||
for (int j=0; j<s.length; j++) { | for (int j=0; j<s.length; j++) { | ||||
v.addElement(s[j]); | |||||
fileNames.addElement(s[j]); | |||||
baseDirs.addElement(base); | |||||
} | } | ||||
} | } | ||||
if (!"file".equals(type)) { | if (!"file".equals(type)) { | ||||
String[] s = getDirs(base, ds);; | String[] s = getDirs(base, ds);; | ||||
for (int j=0; j<s.length; j++) { | for (int j=0; j<s.length; j++) { | ||||
v.addElement(s[j]); | |||||
fileNames.addElement(s[j]); | |||||
baseDirs.addElement(base); | |||||
} | } | ||||
} | } | ||||
if (v.size() == 0 && skipEmpty) { | |||||
if (fileNames.size() == 0 && skipEmpty) { | |||||
log("Skipping fileset for directory " | log("Skipping fileset for directory " | ||||
+ base + ". It is empty.", Project.MSG_INFO); | + base + ". It is empty.", Project.MSG_INFO); | ||||
continue; | continue; | ||||
} | } | ||||
String[] s = new String[v.size()]; | |||||
v.copyInto(s); | |||||
int err = -1; | |||||
if (parallel) { | |||||
String[] command = getCommandline(s, base); | |||||
log("Executing " + Commandline.toString(command), | |||||
Project.MSG_VERBOSE); | |||||
exe.setCommandline(command); | |||||
runExecute(exe); | |||||
} else { | |||||
if (!parallel) { | |||||
String[] s = new String[fileNames.size()]; | |||||
fileNames.copyInto(s); | |||||
for (int j=0; j<s.length; j++) { | for (int j=0; j<s.length; j++) { | ||||
String[] command = getCommandline(s[j], base); | String[] command = getCommandline(s[j], base); | ||||
log("Executing " + Commandline.toString(command), | log("Executing " + Commandline.toString(command), | ||||
@@ -172,9 +226,23 @@ public class ExecuteOn extends ExecTask { | |||||
exe.setCommandline(command); | exe.setCommandline(command); | ||||
runExecute(exe); | runExecute(exe); | ||||
} | } | ||||
fileNames.removeAllElements(); | |||||
baseDirs.removeAllElements(); | |||||
} | } | ||||
} | } | ||||
if (parallel) { | |||||
String[] s = new String[fileNames.size()]; | |||||
fileNames.copyInto(s); | |||||
File[] b = new File[baseDirs.size()]; | |||||
baseDirs.copyInto(b); | |||||
String[] command = getCommandline(s, b); | |||||
log("Executing " + Commandline.toString(command), | |||||
Project.MSG_VERBOSE); | |||||
exe.setCommandline(command); | |||||
runExecute(exe); | |||||
} | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new BuildException("Execute failed: " + e, e, location); | throw new BuildException("Execute failed: " + e, e, location); | ||||
} finally { | } finally { | ||||
@@ -189,22 +257,87 @@ public class ExecuteOn extends ExecTask { | |||||
* @param srcFiles The filenames to add to the commandline | * @param srcFiles The filenames to add to the commandline | ||||
* @param baseDir filenames are relative to this dir | * @param baseDir filenames are relative to this dir | ||||
*/ | */ | ||||
protected String[] getCommandline(String[] srcFiles, File baseDir) { | |||||
protected String[] getCommandline(String[] srcFiles, File[] baseDirs) { | |||||
Vector targets = new Vector(); | |||||
if (targetFilePos != null) { | |||||
Hashtable addedFiles = new Hashtable(); | |||||
for (int i=0; i<srcFiles.length; i++) { | |||||
String[] subTargets = mapper.mapFileName(srcFiles[i]); | |||||
if (subTargets != null) { | |||||
for (int j=0; j<subTargets.length; j++) { | |||||
String name = (new File(destDir, subTargets[j])).getAbsolutePath(); | |||||
if (!addedFiles.contains(name)) { | |||||
targets.addElement(name); | |||||
addedFiles.put(name, name); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
String[] targetFiles = new String[targets.size()]; | |||||
targets.copyInto(targetFiles); | |||||
String[] orig = cmdl.getCommandline(); | String[] orig = cmdl.getCommandline(); | ||||
String[] result = new String[orig.length+srcFiles.length]; | |||||
String[] result = new String[orig.length+srcFiles.length+targetFiles.length]; | |||||
int index = orig.length; | |||||
int srcIndex = orig.length; | |||||
if (srcFilePos != null) { | if (srcFilePos != null) { | ||||
index = srcFilePos.getPosition(); | |||||
srcIndex = srcFilePos.getPosition(); | |||||
} | } | ||||
System.arraycopy(orig, 0, result, 0, index); | |||||
if (targetFilePos != null) { | |||||
int targetIndex = targetFilePos.getPosition(); | |||||
if (srcIndex < targetIndex | |||||
|| (srcIndex == targetIndex && srcIsFirst)) { | |||||
// 0 --> srcIndex | |||||
System.arraycopy(orig, 0, result, 0, srcIndex); | |||||
// srcIndex --> targetIndex | |||||
System.arraycopy(orig, srcIndex, result, | |||||
srcIndex + srcFiles.length, | |||||
targetIndex - srcIndex); | |||||
// targets are already absolute file names | |||||
System.arraycopy(targetFiles, 0, result, | |||||
targetIndex + srcFiles.length, | |||||
targetFiles.length); | |||||
// targetIndex --> end | |||||
System.arraycopy(orig, targetIndex, result, | |||||
targetIndex + srcFiles.length + targetFiles.length, | |||||
orig.length - targetIndex); | |||||
} else { | |||||
// 0 --> targetIndex | |||||
System.arraycopy(orig, 0, result, 0, targetIndex); | |||||
// targets are already absolute file names | |||||
System.arraycopy(targetFiles, 0, result, | |||||
targetIndex, | |||||
targetFiles.length); | |||||
// targetIndex --> srcIndex | |||||
System.arraycopy(orig, targetIndex, result, | |||||
targetIndex + targetFiles.length, | |||||
srcIndex - targetIndex); | |||||
// srcIndex --> end | |||||
System.arraycopy(orig, srcIndex, result, | |||||
srcIndex + srcFiles.length + targetFiles.length, | |||||
orig.length - srcIndex); | |||||
srcIndex += targetFiles.length; | |||||
} | |||||
} else { // no targetFilePos | |||||
System.arraycopy(orig, 0, result, 0, srcIndex); | |||||
} | |||||
// fill in source file names | |||||
for (int i=0; i < srcFiles.length; i++) { | for (int i=0; i < srcFiles.length; i++) { | ||||
result[index+i] = (new File(baseDir, srcFiles[i])).getAbsolutePath(); | |||||
result[srcIndex+i] = | |||||
(new File(baseDirs[i], srcFiles[i])).getAbsolutePath(); | |||||
} | } | ||||
System.arraycopy(orig, index, result, index+srcFiles.length, | |||||
orig.length-index); | |||||
return result; | return result; | ||||
} | } | ||||
@@ -215,23 +348,35 @@ public class ExecuteOn extends ExecTask { | |||||
* @param baseDir filename is relative to this dir | * @param baseDir filename is relative to this dir | ||||
*/ | */ | ||||
protected String[] getCommandline(String srcFile, File baseDir) { | protected String[] getCommandline(String srcFile, File baseDir) { | ||||
return getCommandline(new String[] {srcFile}, baseDir); | |||||
return getCommandline(new String[] {srcFile}, new File[] {baseDir}); | |||||
} | } | ||||
/** | /** | ||||
* Return the list of files from this DirectoryScanner that should | * Return the list of files from this DirectoryScanner that should | ||||
* be included on the command line. | * be included on the command line. | ||||
*/ | */ | ||||
protected String[] getFiles(File basedir, DirectoryScanner ds) { | |||||
return ds.getIncludedFiles(); | |||||
protected String[] getFiles(File baseDir, DirectoryScanner ds) { | |||||
if (mapper != null) { | |||||
SourceFileScanner sfs = new SourceFileScanner(this); | |||||
return sfs.restrict(ds.getIncludedFiles(), baseDir, destDir, | |||||
mapper); | |||||
} else { | |||||
return ds.getIncludedFiles(); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
* Return the list of Directories from this DirectoryScanner that | * Return the list of Directories from this DirectoryScanner that | ||||
* should be included on the command line. | * should be included on the command line. | ||||
*/ | */ | ||||
protected String[] getDirs(File basedir, DirectoryScanner ds) { | |||||
return ds.getIncludedDirectories(); | |||||
protected String[] getDirs(File baseDir, DirectoryScanner ds) { | |||||
if (mapper != null) { | |||||
SourceFileScanner sfs = new SourceFileScanner(this); | |||||
return sfs.restrict(ds.getIncludedDirectories(), baseDir, destDir, | |||||
mapper); | |||||
} else { | |||||
return ds.getIncludedDirectories(); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -54,193 +54,9 @@ | |||||
package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
import java.io.File; | |||||
import java.util.Hashtable; | |||||
import java.util.Vector; | |||||
import org.apache.tools.ant.*; | |||||
import org.apache.tools.ant.types.*; | |||||
import org.apache.tools.ant.util.*; | |||||
/** | /** | ||||
* Executes a given command, supplying a set of files as arguments. | |||||
* | |||||
* <p>Only those files that are newer than their corresponding target | |||||
* files will be handeled, the rest will be ignored.</p> | |||||
* Has been merged into ExecuteOn, empty class for backwards compatibility. | |||||
* | * | ||||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | ||||
*/ | */ | ||||
public class Transform extends ExecuteOn { | |||||
protected Commandline.Marker targetFilePos = null; | |||||
protected Mapper mapperElement = null; | |||||
protected FileNameMapper mapper = null; | |||||
protected File destDir = null; | |||||
/** | |||||
* Has <srcfile> been specified before <targetfile> | |||||
*/ | |||||
protected boolean srcIsFirst = true; | |||||
/** | |||||
* Set the destination directory. | |||||
*/ | |||||
public void setDest(File destDir) { | |||||
this.destDir = destDir; | |||||
} | |||||
/** | |||||
* Marker that indicates where the name of the target file should | |||||
* be put on the command line. | |||||
*/ | |||||
public Commandline.Marker createTargetfile() { | |||||
if (targetFilePos != null) { | |||||
throw new BuildException(taskType + " doesn\'t support multiple targetfile elements.", | |||||
location); | |||||
} | |||||
targetFilePos = cmdl.createMarker(); | |||||
srcIsFirst = (srcFilePos != null); | |||||
return targetFilePos; | |||||
} | |||||
/** | |||||
* Defines the FileNameMapper to use (nested mapper element). | |||||
*/ | |||||
public Mapper createMapper() throws BuildException { | |||||
if (mapperElement != null) { | |||||
throw new BuildException("Cannot define more than one mapper", | |||||
location); | |||||
} | |||||
mapperElement = new Mapper(project); | |||||
return mapperElement; | |||||
} | |||||
protected void checkConfiguration() { | |||||
super.checkConfiguration(); | |||||
if (mapperElement == null) { | |||||
throw new BuildException("no mapper specified", location); | |||||
} | |||||
if (destDir == null) { | |||||
throw new BuildException("no dest attribute specified", location); | |||||
} | |||||
mapper = mapperElement.getImplementation(); | |||||
} | |||||
/** | |||||
* Return the list of files from this DirectoryScanner that should | |||||
* be included on the command line - i.e. only those that are | |||||
* newer than the corresponding target files. | |||||
*/ | |||||
protected String[] getFiles(File baseDir, DirectoryScanner ds) { | |||||
SourceFileScanner sfs = new SourceFileScanner(this); | |||||
return sfs.restrict(ds.getIncludedFiles(), baseDir, destDir, mapper); | |||||
} | |||||
/** | |||||
* Return the list of Directories from this DirectoryScanner that | |||||
* should be included on the command line - i.e. only those that | |||||
* are newer than the corresponding target files. | |||||
*/ | |||||
protected String[] getDirs(File baseDir, DirectoryScanner ds) { | |||||
SourceFileScanner sfs = new SourceFileScanner(this); | |||||
return sfs.restrict(ds.getIncludedDirectories(), baseDir, destDir, | |||||
mapper); | |||||
} | |||||
/** | |||||
* Construct the command line for parallel execution. | |||||
* | |||||
* @param srcFiles The filenames to add to the commandline | |||||
* @param baseDir filenames are relative to this dir | |||||
*/ | |||||
protected String[] getCommandline(String[] srcFiles, File baseDir) { | |||||
if (targetFilePos == null) { | |||||
return super.getCommandline(srcFiles, baseDir); | |||||
} | |||||
Vector targets = new Vector(); | |||||
Hashtable addedFiles = new Hashtable(); | |||||
for (int i=0; i<srcFiles.length; i++) { | |||||
String[] subTargets = mapper.mapFileName(srcFiles[i]); | |||||
if (subTargets != null) { | |||||
for (int j=0; j<subTargets.length; j++) { | |||||
String name = (new File(destDir, subTargets[j])).getAbsolutePath(); | |||||
if (!addedFiles.contains(name)) { | |||||
targets.addElement(name); | |||||
addedFiles.put(name, name); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
String[] targetFiles = new String[targets.size()]; | |||||
targets.copyInto(targetFiles); | |||||
String[] orig = cmdl.getCommandline(); | |||||
String[] result = new String[orig.length+srcFiles.length+targetFiles.length]; | |||||
int srcIndex = orig.length; | |||||
if (srcFilePos != null) { | |||||
srcIndex = srcFilePos.getPosition(); | |||||
} | |||||
int targetIndex = targetFilePos.getPosition(); | |||||
if (srcIndex < targetIndex || (srcIndex == targetIndex && srcIsFirst)) { | |||||
// 0 --> srcIndex | |||||
System.arraycopy(orig, 0, result, 0, srcIndex); | |||||
// srcIndex --> targetIndex | |||||
System.arraycopy(orig, srcIndex, result, | |||||
srcIndex + srcFiles.length, | |||||
targetIndex - srcIndex); | |||||
// targets are already absolute file names | |||||
System.arraycopy(targetFiles, 0, result, | |||||
targetIndex + srcFiles.length, | |||||
targetFiles.length); | |||||
// targetIndex --> end | |||||
System.arraycopy(orig, targetIndex, result, | |||||
targetIndex + srcFiles.length + targetFiles.length, | |||||
orig.length - targetIndex); | |||||
} else { | |||||
// 0 --> targetIndex | |||||
System.arraycopy(orig, 0, result, 0, targetIndex); | |||||
// targets are already absolute file names | |||||
System.arraycopy(targetFiles, 0, result, | |||||
targetIndex, | |||||
targetFiles.length); | |||||
// targetIndex --> srcIndex | |||||
System.arraycopy(orig, targetIndex, result, | |||||
targetIndex + targetFiles.length, | |||||
srcIndex - targetIndex); | |||||
// srcIndex --> end | |||||
System.arraycopy(orig, srcIndex, result, | |||||
srcIndex + srcFiles.length + targetFiles.length, | |||||
orig.length - srcIndex); | |||||
srcIndex += targetFiles.length; | |||||
} | |||||
for (int i=0; i < srcFiles.length; i++) { | |||||
result[srcIndex+i] = | |||||
(new File(baseDir, srcFiles[i])).getAbsolutePath(); | |||||
} | |||||
return result; | |||||
} | |||||
/** | |||||
* Construct the command line for serial execution. | |||||
* | |||||
* @param srcFile The filename to add to the commandline | |||||
* @param baseDir filename is relative to this dir | |||||
*/ | |||||
protected String[] getCommandline(String srcFile, File baseDir) { | |||||
return getCommandline(new String[] {srcFile}, baseDir); | |||||
} | |||||
} | |||||
public class Transform extends ExecuteOn {} |