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 {} | |||||