You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@locus.apache.org on 2000/07/25 14:03:28 UTC

cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs ExecTask.java Execute.java ExecuteOn.java defaults.properties

bodewig     00/07/25 05:03:27

  Modified:    src/main/org/apache/tools/ant/taskdefs ExecTask.java
                        Execute.java ExecuteOn.java defaults.properties
  Log:
  Reworked the <exec> and (now so called) <execon> tasks.
  Submitted by:	Mariusz Nowostawski <ma...@marni.otago.ac.nz>
  
  Revision  Changes    Path
  1.4       +78 -46    jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
  
  Index: ExecTask.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ExecTask.java	2000/07/19 15:26:19	1.3
  +++ ExecTask.java	2000/07/25 12:03:26	1.4
  @@ -66,116 +66,140 @@
    * @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) {
  @@ -191,8 +215,10 @@
               logFlush();
           }
       }
  -
   
  +    /**
  +     * Create the StreamHandler to use with our Execute instance.
  +     */
       protected ExecuteStreamHandler createHandler() throws BuildException {
           if(out!=null)  {
               try {
  @@ -210,11 +236,17 @@
           }
       }
   
  +    /**
  +     * 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();
  
  
  
  1.2       +67 -3     jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Execute.java
  
  Index: Execute.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Execute.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Execute.java	2000/07/19 13:00:31	1.1
  +++ Execute.java	2000/07/25 12:03:26	1.2
  @@ -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 @@
       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 @@
        * @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 @@
   
   
       /**
  -     * 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.
  
  
  
  1.2       +59 -79    jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java
  
  Index: ExecuteOn.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteOn.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ExecuteOn.java	2000/07/19 16:00:52	1.1
  +++ ExecuteOn.java	2000/07/25 12:03:26	1.2
  @@ -65,14 +65,12 @@
    * 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 @@
       }
   
       /**
  -     * 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();
  +        }
       }
   
   }
  
  
  
  1.28      +1 -1      jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- defaults.properties	2000/07/24 14:27:13	1.27
  +++ defaults.properties	2000/07/25 12:03:26	1.28
  @@ -36,7 +36,7 @@
   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
   
  
  
  

Re: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs ExecTask.java Execute.java ExecuteOn.java defaults.properties

Posted by Stefan Bodewig <bo...@bost.de>.
This one is merge of Mariusz' patches and some of my ideas.

It hasn't been tested on Windows, any reports whether <exec> still
works or not on Windows are very much appreciated.

I've moved the logic to decide whether we need to change the directory
to the Execute class - maybe other tasks are going to benefit from
this as well.

<executeon> is now <execon> and has the additional attribute parallel
which decides whether the command gets executed once per file or for
all files in one pass. If we happen to be running on Windows the total
size of the resulting command line is checked and parallel mode is not
allowed if antRun.bat could lose our arguments.

Stefan