Submitted by: Mariusz Nowostawski <mariusz@marni.otago.ac.nz> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267834 13f79535-47bb-0310-9956-ffa450edef68master
@@ -66,116 +66,140 @@ import java.io.*; | |||
* @author rubys@us.ibm.com | |||
* @author thomas.haas@softwired-inc.com | |||
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||
* @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
*/ | |||
public class ExecTask extends Task { | |||
private String os; | |||
private File out; | |||
private File dir; | |||
private boolean failOnError = false; | |||
protected boolean failOnError = false; | |||
private Integer timeout = null; | |||
private Environment env = new Environment(); | |||
private Commandline cmdl = new Commandline(); | |||
protected Commandline cmdl = new Commandline(); | |||
private FileOutputStream fos = null; | |||
/** | |||
* Timeout in milliseconds after which the process will be killed. | |||
*/ | |||
public void setTimeout(Integer value) { | |||
timeout = value; | |||
} | |||
/** | |||
* The command to execute. | |||
*/ | |||
public void setExecutable(String value) { | |||
cmdl.setExecutable(value); | |||
} | |||
/** | |||
* The working directory of the process | |||
*/ | |||
public void setDir(File d) { | |||
this.dir = d; | |||
} | |||
/** | |||
* Only execute the process if <code>os.name</code> includes this string. | |||
*/ | |||
public void setOs(String os) { | |||
this.os = os; | |||
} | |||
/** | |||
* The full commandline to execute, executable + arguments. | |||
*/ | |||
public void setCommand(Commandline cmdl) { | |||
this.cmdl = cmdl; | |||
} | |||
/** | |||
* File the output of the process is redirected to. | |||
*/ | |||
public void setOutput(File out) { | |||
this.out = out; | |||
} | |||
/** | |||
* Throw a BuildException if process returns non 0. | |||
*/ | |||
public void setFailonerror(boolean fail) { | |||
failOnError = fail; | |||
} | |||
/** | |||
* Add a nested env element - an environment variable. | |||
*/ | |||
public void addEnv(Environment.Variable var) { | |||
env.addVariable(var); | |||
} | |||
/** | |||
* Add a nested arg element - a command line argument. | |||
*/ | |||
public Commandline.Argument createArg() { | |||
return cmdl.createArgument(); | |||
} | |||
/** | |||
* Do the work. | |||
*/ | |||
public void execute() throws BuildException { | |||
checkConfiguration(); | |||
if (isValidOs()) { | |||
runExec(prepareExec()); | |||
} | |||
} | |||
/** | |||
* Has the user set all necessary attributes? | |||
*/ | |||
protected void checkConfiguration() throws BuildException { | |||
if (cmdl.getExecutable() == null) { | |||
throw new BuildException("no executable specified", location); | |||
} | |||
} | |||
String[] orig = cmdl.getCommandline(); | |||
int err = -1; // assume the worst | |||
/** | |||
* Is this the OS the user wanted? | |||
*/ | |||
private boolean isValidOs() { | |||
// test if os match | |||
String myos = System.getProperty("os.name"); | |||
log("Myos = " + myos, Project.MSG_VERBOSE); | |||
if ((os != null) && (os.indexOf(myos) < 0)){ | |||
// this command will be executed only on the specified OS | |||
log("Not found in " + os, Project.MSG_VERBOSE); | |||
return; | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Create an Execute instance with the correct working directory set. | |||
*/ | |||
protected Execute prepareExec() throws BuildException { | |||
// default directory to the project's base directory | |||
if (dir == null) dir = project.getBaseDir(); | |||
// show the command | |||
log(cmdl.toString(), Project.MSG_VERBOSE); | |||
Execute exe = new Execute(createHandler(), createWatchdog()); | |||
exe.setAntRun(project); | |||
exe.setWorkingDirectory(dir); | |||
exe.setEnvironment(env.getVariables()); | |||
return exe; | |||
} | |||
if (myos.toLowerCase().indexOf("windows") >= 0) { | |||
if (!dir.equals(project.resolveFile("."))) { | |||
if (myos.toLowerCase().indexOf("nt") >= 0) { | |||
cmdl = new Commandline(); | |||
cmdl.setExecutable("cmd"); | |||
cmdl.addValue("/c"); | |||
cmdl.addValue("cd"); | |||
cmdl.addValue(dir.getAbsolutePath()); | |||
cmdl.addValue("&&"); | |||
cmdl.addLine(orig); | |||
} else { | |||
String ant = project.getProperty("ant.home"); | |||
if (ant == null) { | |||
throw new BuildException("Property 'ant.home' not found", location); | |||
} | |||
String antRun = project.resolveFile(ant + "/bin/antRun.bat").toString(); | |||
cmdl = new Commandline(); | |||
cmdl.setExecutable(antRun); | |||
cmdl.addValue(dir.getAbsolutePath()); | |||
cmdl.addLine(orig); | |||
} | |||
} | |||
} else { | |||
String ant = project.getProperty("ant.home"); | |||
if (ant == null) throw new BuildException("Property 'ant.home' not found", location); | |||
String antRun = project.resolveFile(ant + "/bin/antRun").toString(); | |||
cmdl = new Commandline(); | |||
cmdl.setExecutable(antRun); | |||
cmdl.addValue(dir.getAbsolutePath()); | |||
cmdl.addLine(orig); | |||
} | |||
/** | |||
* Run the command using the given Execute instance. | |||
*/ | |||
protected void runExec(Execute exe) throws BuildException { | |||
int err = -1; // assume the worst | |||
try { | |||
// show the command | |||
log(cmdl.toString(), Project.MSG_VERBOSE); | |||
final Execute exe = new Execute(createHandler(), createWatchdog()); | |||
exe.setCommandline(cmdl.getCommandline()); | |||
exe.setEnvironment(env.getVariables()); | |||
err = exe.execute(); | |||
if (err != 0) { | |||
if (failOnError) { | |||
@@ -192,7 +216,9 @@ public class ExecTask extends Task { | |||
} | |||
} | |||
/** | |||
* Create the StreamHandler to use with our Execute instance. | |||
*/ | |||
protected ExecuteStreamHandler createHandler() throws BuildException { | |||
if(out!=null) { | |||
try { | |||
@@ -210,11 +236,17 @@ public class ExecTask extends Task { | |||
} | |||
} | |||
/** | |||
* Create the Watchdog to kill a runaway process. | |||
*/ | |||
protected ExecuteWatchdog createWatchdog() throws BuildException { | |||
if (timeout == null) return null; | |||
return new ExecuteWatchdog(timeout.intValue()); | |||
} | |||
/** | |||
* Flush the output stream - if there is one. | |||
*/ | |||
protected void logFlush() { | |||
try { | |||
if (fos != null) fos.close(); | |||
@@ -54,6 +54,10 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
@@ -74,6 +78,12 @@ public class Execute { | |||
private int exitValue = INVALID; | |||
private ExecuteStreamHandler streamHandler; | |||
private ExecuteWatchdog watchdog; | |||
private File workingDirectory; | |||
private String antRun; | |||
private static String antWorkingDirectory = | |||
(new File((new File(".")).getAbsolutePath())).getParent(); | |||
private static String myos = System.getProperty("os.name"); | |||
/** | |||
* Creates a new execute object using <code>PumpStreamHandler</code> for | |||
@@ -104,7 +114,31 @@ public class Execute { | |||
* @return the commandline used to create a subprocess | |||
*/ | |||
public String[] getCommandline() { | |||
return cmdl; | |||
String[] commandLine = cmdl; | |||
if (workingDirectory != null && | |||
!antWorkingDirectory.equals(workingDirectory.getAbsolutePath())) { | |||
if (myos.toLowerCase().indexOf("windows") >= 0 && | |||
myos.toLowerCase().indexOf("nt") >= 0) { | |||
commandLine = new String[cmdl.length+5]; | |||
commandLine[0] = "cmd"; | |||
commandLine[1] = "/c"; | |||
commandLine[2] = "cd"; | |||
commandLine[3] = workingDirectory.getAbsolutePath(); | |||
commandLine[4] = "&&"; | |||
System.arraycopy(cmdl, 0, commandLine, 5, cmdl.length); | |||
} else { | |||
commandLine = new String[cmdl.length+2]; | |||
commandLine[0] = antRun; | |||
commandLine[1] = workingDirectory.getAbsolutePath(); | |||
System.arraycopy(cmdl, 0, commandLine, 2, cmdl.length); | |||
} | |||
} | |||
return commandLine; | |||
} | |||
@@ -128,14 +162,44 @@ public class Execute { | |||
/** | |||
* Sets the commandline of the subprocess to launch. | |||
* Sets the environment variables for the subprocess to launch. | |||
* | |||
* @param commandline the commandline of the subprocess to launch | |||
* @param commandline array of Strings, each element of which has | |||
* an environment variable settings in format <em>key=value</em> | |||
*/ | |||
public void setEnvironment(String[] env) { | |||
this.env = env; | |||
} | |||
/** | |||
* Sets the working directory of the process to execute. | |||
* | |||
* <p>This is emulated using the antRun scripts unless the OS is | |||
* Windows NT in which case a cmd.exe is spawned. | |||
* | |||
* @param wd the working directory of the process. | |||
*/ | |||
public void setWorkingDirectory(File wd) { | |||
workingDirectory = wd; | |||
} | |||
/** | |||
* Set the name of the antRun script using the project's value. | |||
* | |||
* @param project the current project. | |||
*/ | |||
public void setAntRun(Project project) throws BuildException { | |||
String ant = project.getProperty("ant.home"); | |||
if (ant == null) { | |||
throw new BuildException("Property 'ant.home' not found"); | |||
} | |||
if (myos.toLowerCase().indexOf("windows") >= 0) { | |||
antRun = project.resolveFile(ant + "/bin/antRun.bat").toString(); | |||
} else { | |||
antRun = project.resolveFile(ant + "/bin/antRun").toString(); | |||
} | |||
} | |||
/** | |||
* Runs a process defined by the command line and returns its exit status. | |||
@@ -65,14 +65,12 @@ import java.io.IOException; | |||
* Executes a given command, supplying a set of files as arguments. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||
* @author <a href="mailto:mariusz@rakiura.org">Mariusz Nowostawski</a> | |||
*/ | |||
public class ExecuteOn extends Task { | |||
public class ExecuteOn extends ExecTask { | |||
private Vector filesets = new Vector(); | |||
private Commandline command = new Commandline(); | |||
private Environment env = new Environment(); | |||
private Integer timeout = null; | |||
private boolean failOnError = false; | |||
private boolean parallel = false; | |||
/** | |||
* Adds a set of files (nested fileset attribute). | |||
@@ -82,97 +80,79 @@ public class ExecuteOn extends Task { | |||
} | |||
/** | |||
* The executable. | |||
* Shall the command work on all specified files in parallel? | |||
*/ | |||
public void setExecutable(String exe) { | |||
command.setExecutable(exe); | |||
public void setParallel(boolean parallel) { | |||
this.parallel = parallel; | |||
} | |||
/** | |||
* Adds an argument to the command (nested arg element) | |||
*/ | |||
public Commandline.Argument createArg() { | |||
return command.createArgument(); | |||
} | |||
/** | |||
* Adds an environment variable (nested env element) | |||
*/ | |||
public void addEnv(Environment.Variable var) { | |||
env.addVariable(var); | |||
protected void checkConfiguration() { | |||
super.checkConfiguration(); | |||
if (filesets.size() == 0) { | |||
throw new BuildException("no filesets specified", location); | |||
} | |||
} | |||
/** | |||
* Milliseconds we allow the process to run before we kill it. | |||
*/ | |||
public void setTimeout(Integer value) { | |||
timeout = value; | |||
} | |||
protected void runExec(Execute exe) throws BuildException { | |||
try { | |||
/** | |||
* throw a build exception if process returns non 0? | |||
*/ | |||
public void setFailonerror(boolean fail) { | |||
failOnError = fail; | |||
} | |||
Vector v = new Vector(); | |||
for (int i=0; i<filesets.size(); i++) { | |||
FileSet fs = (FileSet) filesets.elementAt(i); | |||
DirectoryScanner ds = fs.getDirectoryScanner(project); | |||
String[] s = ds.getIncludedFiles(); | |||
for (int j=0; j<s.length; j++) { | |||
v.addElement(new File(fs.getDir(), s[j]).getAbsolutePath()); | |||
} | |||
} | |||
public void execute() throws BuildException { | |||
if (command.getExecutable() == null) { | |||
throw new BuildException("no executable specified", location); | |||
} | |||
String[] s = new String[v.size()]; | |||
v.copyInto(s); | |||
if (filesets.size() == 0) { | |||
throw new BuildException("no filesets specified", location); | |||
} | |||
int err = -1; | |||
String myos = System.getProperty("os.name"); | |||
String[] orig = command.getCommandline(); | |||
String[] cmd = new String[orig.length+1]; | |||
System.arraycopy(orig, 0, cmd, 0, orig.length); | |||
Vector v = new Vector(); | |||
for (int i=0; i<filesets.size(); i++) { | |||
FileSet fs = (FileSet) filesets.elementAt(i); | |||
DirectoryScanner ds = fs.getDirectoryScanner(project); | |||
String[] s = ds.getIncludedFiles(); | |||
for (int j=0; j<s.length; j++) { | |||
v.addElement(new File(fs.getDir(), s[j]).getAbsolutePath()); | |||
} | |||
} | |||
String label = command.toString()+" "; | |||
String[] environment = env.getVariables(); | |||
for (int i=0; i<v.size(); i++) { | |||
try { | |||
// show the command | |||
String file = (String) v.elementAt(i); | |||
log(label+file, Project.MSG_VERBOSE); | |||
Execute exe = new Execute(createHandler(), createWatchdog()); | |||
cmd[orig.length] = file; | |||
exe.setCommandline(cmd); | |||
exe.setEnvironment(environment); | |||
int err = exe.execute(); | |||
// antRun.bat currently limits us to directory + executable | |||
// + 7 args | |||
if (parallel && | |||
(myos.toLowerCase().indexOf("windows") < 0 || s.length+cmdl.size() <= 8) | |||
) { | |||
cmdl.addLine(s); | |||
exe.setCommandline(cmdl.getCommandline()); | |||
err = exe.execute(); | |||
if (err != 0) { | |||
if (failOnError) { | |||
throw new BuildException("Exec returned: "+err, location); | |||
throw new BuildException("Exec returned: "+err, | |||
location); | |||
} else { | |||
log("Result: " + err, Project.MSG_ERR); | |||
} | |||
} | |||
} catch (IOException e) { | |||
throw new BuildException("Execute failed: " + e, e, location); | |||
} | |||
} | |||
} | |||
protected ExecuteStreamHandler createHandler() throws BuildException { | |||
return new LogStreamHandler(this, | |||
Project.MSG_INFO, Project.MSG_WARN); | |||
} | |||
} else { | |||
String[] cmd = new String[cmdl.size()+1]; | |||
System.arraycopy(cmdl.getCommandline(), 0, cmd, 0, cmdl.size()); | |||
for (int i=0; i<s.length; i++) { | |||
cmd[cmdl.size()] = s[i]; | |||
exe.setCommandline(cmd); | |||
err = exe.execute(); | |||
if (err != 0) { | |||
if (failOnError) { | |||
throw new BuildException("Exec returned: "+err, | |||
location); | |||
} else { | |||
log("Result: " + err, Project.MSG_ERR); | |||
} | |||
} | |||
} | |||
} | |||
protected ExecuteWatchdog createWatchdog() throws BuildException { | |||
if (timeout == null) return null; | |||
return new ExecuteWatchdog(timeout.intValue()); | |||
} catch (IOException e) { | |||
throw new BuildException("Execute failed: " + e, e, location); | |||
} finally { | |||
// close the output file if required | |||
logFlush(); | |||
} | |||
} | |||
} |
@@ -36,7 +36,7 @@ style=org.apache.tools.ant.taskdefs.XSLTProcess | |||
touch=org.apache.tools.ant.taskdefs.Touch | |||
signjar=org.apache.tools.ant.taskdefs.SignJar | |||
antstructure=org.apache.tools.ant.taskdefs.AntStructure | |||
executeon=org.apache.tools.ant.taskdefs.ExecuteOn | |||
execon=org.apache.tools.ant.taskdefs.ExecuteOn | |||
antcall=org.apache.tools.ant.taskdefs.CallTarget | |||
sql=org.apache.tools.ant.taskdefs.SQLExec | |||