I wrote a trivial extension to the existing Exec task definition to make
it include/exclude aware and I have already posted it here, but
without any (positive or negative) feedback.
With the patch, the Exec task will behave as usual if used as
usual. However, if used with the additional optional attribute 'src' which
should be a directory, it will search for files, and will exec a command
with attached list of files as an additional last argument.
'src' attribute can be renamed to 'dir' or whatever will be the 'standard
look&feel' for matching tasks.
One can use the modified Exec for any task which requires executing a
binary program with a list of files being its arguments;
for example to compile multiple *.idl files:
(*) <exec dir="${basedir}"
command="jidl --output-dir ${src.dir} --package com.my.idl"
src="src/idls" output="out.txt"/>
if inside ${basedir}/src/idls we have files: a.idl, b.idl, c.txt
it would execute effectively:
cd ${basedir}; jidl --output-dir src/main --package com.my.idl \
${basedir}/src/idl/a.idl ${basedir}/src/idl/b.idl ${basedir}/src/idl/c.txt
(*) <exec dir="${basedir}"
command="jidl --output-dir ${src.dir} --package com.my.idl"
src="src/idl" output="out.txt">
<include name="*.idl"/>
</exec>
if inside ${basedir}/src/idls we have files: a.idl, b.idl, c.txt
it would execute effectively:
cd ${basedir}; jidl --output-dir src/main --package com.my.idl \
${basedir}/src/idl/a.idl ${basedir}/src/idl/b.idl
The patch assumes that the command should be invoked once with the list of
all matching files appended to the list of arguments. I cannot find any
use of executing commands in list of files sequentially file after file
with unknown order but if somebody needs it, the patch can be easily
extended (i.e. exec task can be easily extended by additional
flag: 'sequential="true"'). Maybe there are usefull file/source processors
which can deal with single file at once only. All tools I use can take a
list of arguments, and single invocation is enough.
best regards
Mariusz
Index: src/main/org/apache/tools/ant/taskdefs/Exec.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Exec.java,v
retrieving revision 1.9
diff -u -r1.9 Exec.java
--- src/main/org/apache/tools/ant/taskdefs/Exec.java 2000/04/01 14:25:07
1.9
+++ src/main/org/apache/tools/ant/taskdefs/Exec.java 2000/05/25 22:38:58
@@ -58,16 +58,22 @@
import java.io.*;
/**
- * Executes a given command if the os platform is appropriate.
+ * Executes a given command if the os platform is appropriate. This task
conforms to
+ * all other matching tasks and can take src attribute together with
include/exclude tags
+ * for files to be used as arguments of the specified command.
*
* @author [EMAIL PROTECTED]
* @author [EMAIL PROTECTED]
+ * @author Mariusz Nowostawski (Marni)
+ <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
-public class Exec extends Task {
+public class Exec extends MatchingTask {
+
private String os;
private String out;
- private File dir;
+ private File dir; //command to be executed in dir
+ private File srcDir; //source directory for files to be used as parameters
private String command;
private static final int BUFFER_SIZE = 512;
@@ -77,9 +83,8 @@
}
protected int run(String command) throws BuildException {
-
- int err = -1; // assume the worst
-
+ int err = -1;
+
// test if os match
String myos = System.getProperty("os.name");
project.log("Myos = " + myos, Project.MSG_VERBOSE);
@@ -104,41 +109,25 @@
}
try {
- // show the command
- project.log(command, "exec", Project.MSG_VERBOSE);
+ if(srcDir == null){ //normal exec, no files included as arguments
- // exec command on system runtime
- Process proc = Runtime.getRuntime().exec(command);
+ project.log(command, "exec", Project.MSG_VERBOSE);
+ err = executeCommand(command);
- PrintWriter fos=null;
- if( out!=null ) {
- fos=new PrintWriter( new FileWriter( out ) );
- project.log("Output redirected to " + out,
Project.MSG_VERBOSE);
- }
+ }else{//execFor, executes single command with given file list
- // copy input and error to the output stream
- StreamPumper inputPumper =
- new StreamPumper(proc.getInputStream(), "exec", project, fos);
- StreamPumper errorPumper =
- new StreamPumper(proc.getErrorStream(), "error", project, fos);
-
- // starts pumping away the generated output/error
- inputPumper.start();
- errorPumper.start();
-
- // Wait for everything to finish
- proc.waitFor();
- inputPumper.join();
- errorPumper.join();
- proc.destroy();
-
- // close the output file if required
- if (fos != null) fos.close();
-
- // check its exit value
- err = proc.exitValue();
- if (err != 0) {
- project.log("Result: " + err, "exec", Project.MSG_ERR);
+ DirectoryScanner ds = getDirectoryScanner(srcDir);
+ String[] files = ds.getIncludedFiles();
+
+ StringBuffer argFiles = new StringBuffer();
+ String filesep = System.getProperty("file.separator");
+ for (int i = 0; i < files.length; i++) {
+ argFiles.append("
").append(srcDir).append(filesep).append(files[i]);
+ }
+ project.log(this.command+" in "+dir.getAbsolutePath()+" for
"+files.length+" files.", "exec", Project.MSG_INFO);
+ command += argFiles.toString();
+ project.log(command, "exec", Project.MSG_VERBOSE);
+ err = executeCommand(command);
}
} catch (IOException ioe) {
throw new BuildException("Error exec: " + command );
@@ -147,8 +136,53 @@
return err;
}
+ /** Executes (forks) a given command, waits for results, and clean up. */
+ private int executeCommand(String command) throws IOException,
InterruptedException {
+
+ int err = -1; // assume the worst
+
+ // exec command on system runtime
+ Process proc = Runtime.getRuntime().exec(command);
+
+ PrintWriter fos=null;
+ if( out!=null ) {
+ fos=new PrintWriter( new FileWriter( out ) );
+ project.log("Output redirected to " + out, Project.MSG_VERBOSE);
+ }
+
+ // copy input and error to the output stream
+ StreamPumper inputPumper =
+ new StreamPumper(proc.getInputStream(), "exec", project, fos);
+ StreamPumper errorPumper =
+ new StreamPumper(proc.getErrorStream(), "error", project, fos);
+
+ // starts pumping away the generated output/error
+ inputPumper.start();
+ errorPumper.start();
+
+ // Wait for everything to finish
+ proc.waitFor();
+ inputPumper.join();
+ errorPumper.join();
+ proc.destroy();
+
+ // close the output file if required
+ if (fos != null) fos.close();
+
+ // check its exit value
+ err = proc.exitValue();
+ if (err != 0) {
+ project.log("Result: " + err, "exec", Project.MSG_ERR);
+ }
+ return err;
+ }
+
public void setDir(String d) {
this.dir = project.resolveFile(d);
+ }
+
+ public void setSrc(String d) {
+ this.srcDir = project.resolveFile(d);
}
public void setOs(String os) {