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