You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ek...@apache.org on 2005/08/12 17:23:08 UTC

svn commit: r232310 [39/92] - in /beehive/trunk/controls/test: common/ infra/gtlf/ infra/gtlf/xsl/ infra/mantis/ infra/tch/ infra/tch/messages/ infra/tch/runtime/ infra/tch/schema/ perf/ perf/bin/ perf/cases/ perf/ctlsrc/org/apache/beehive/controls/per...

Modified: beehive/trunk/controls/test/tools/tch/src/java/org/apache/beehive/test/tools/tch/ant/Execute.java
URL: http://svn.apache.org/viewcvs/beehive/trunk/controls/test/tools/tch/src/java/org/apache/beehive/test/tools/tch/ant/Execute.java?rev=232310&r1=232309&r2=232310&view=diff
==============================================================================
--- beehive/trunk/controls/test/tools/tch/src/java/org/apache/beehive/test/tools/tch/ant/Execute.java (original)
+++ beehive/trunk/controls/test/tools/tch/src/java/org/apache/beehive/test/tools/tch/ant/Execute.java Fri Aug 12 08:12:28 2005
@@ -1,903 +1,903 @@
-package org.apache.beehive.test.tools.tch.ant;
-
-/*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- *    any, must include the following acknowlegement:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowlegement may appear in the software itself,
- *    if and wherever such third-party acknowlegements normally appear.
- *
- * 4. The names "Ant" and "Apache Software
- *    Foundation" must not be used to endorse or promote products derived
- *    from this software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- *    nor may "Apache" appear in their names without prior written
- *    permission of the Apache Group.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-//package org.apache.tools.ant.taskdefs;
-import org.apache.tools.ant.taskdefs.*;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.types.Commandline;
-import org.apache.tools.ant.taskdefs.condition.Os;
-
-import java.io.File;
-import java.io.IOException;
-
-import java.io.BufferedReader;
-import java.io.StringReader;
-import java.io.ByteArrayOutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Vector;
-
-/**
- * Runs an external program.
- *
- *
- * @since Ant 1.2
- *
- * @version $Revision: 1.43.2.7 $
- */
-public class Execute {
-
-    /** Invalid exit code. **/
-    public static final int INVALID = Integer.MAX_VALUE;
-
-    private String[] cmdl = null;
-    private String[] env = null;
-    private int exitValue = INVALID;
-    private ExecuteStreamHandler streamHandler;
-    private ExecuteWatchdog watchdog;
-    private File workingDirectory = null;
-    private Project project = null;
-    private boolean newEnvironment = false;
-
-    /** Controls whether the VM is used to launch commands, where possible */
-    private boolean useVMLauncher = true;
-
-    private static String antWorkingDirectory = System.getProperty("user.dir");
-    private static CommandLauncher vmLauncher = null;
-    private static CommandLauncher shellLauncher = null;
-    private static Vector procEnvironment = null;
-
-    /** Used to destroy processes when the VM exits. */
-    private static ProcessDestroyer processDestroyer = new ProcessDestroyer();
-
-    /**
-     * Builds a command launcher for the OS and JVM we are running under
-     */
-    static {
-        // Try using a JDK 1.3 launcher
-        try {
-            vmLauncher = new Java13CommandLauncher();
-        } catch (NoSuchMethodException exc) {
-            // Ignore and keep trying
-        }
-
-        if (Os.isFamily("mac")) {
-            // Mac
-            shellLauncher = new MacCommandLauncher(new CommandLauncher());
-        } else if (Os.isFamily("os/2")) {
-            // OS/2
-            shellLauncher = new OS2CommandLauncher(new CommandLauncher());
-        } else if (Os.isFamily("windows")) {
-            // Windows.  Need to determine which JDK we're running in
-
-            CommandLauncher baseLauncher;
-            if (System.getProperty("java.version").startsWith("1.1")) {
-                // JDK 1.1
-                baseLauncher = new Java11CommandLauncher();
-            } else {
-                // JDK 1.2
-                baseLauncher = new CommandLauncher();
-            }
-
-            if (!Os.isFamily("win9x")) {
-                // Windows XP/2000/NT
-                shellLauncher = new WinNTCommandLauncher(baseLauncher);
-            } else {
-                // Windows 98/95 - need to use an auxiliary script
-                shellLauncher
-                    = new ScriptCommandLauncher("bin/antRun.bat", baseLauncher);
-            }
-        } else if (Os.isFamily("netware")) {
-            // NetWare.  Need to determine which JDK we're running in
-            CommandLauncher baseLauncher;
-            if (System.getProperty("java.version").startsWith("1.1")) {
-                // JDK 1.1
-                baseLauncher = new Java11CommandLauncher();
-            } else {
-                // JDK 1.2
-                baseLauncher = new CommandLauncher();
-            }
-
-            shellLauncher
-                = new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher);
-        } else {
-            // Generic
-            shellLauncher = new ScriptCommandLauncher("bin/antRun",
-                new CommandLauncher());
-        }
-    }
-
-    /**
-     * Find the list of environment variables for this process.
-     */
-    public static synchronized Vector getProcEnvironment() {
-        if (procEnvironment != null) {
-            return procEnvironment;
-        }
-
-        procEnvironment = new Vector();
-        try {
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            Execute exe = new Execute(new PumpStreamHandler(out));
-            exe.setCommandline(getProcEnvCommand());
-            // Make sure we do not recurse forever
-            exe.setNewenvironment(true);
-            int retval = exe.execute();
-            if (retval != 0) {
-                // Just try to use what we got
-            }
-
-            BufferedReader in =
-                new BufferedReader(new StringReader(toString(out)));
-
-            String var = null;
-            String line, lineSep = System.getProperty("line.separator");
-            while ((line = in.readLine()) != null) {
-                if (line.indexOf('=') == -1) {
-                    // Chunk part of previous env var (UNIX env vars can
-                    // contain embedded new lines).
-                    if (var == null) {
-                        var = lineSep + line;
-                    } else {
-                        var += lineSep + line;
-                    }
-                } else {
-                    // New env var...append the previous one if we have it.
-                    if (var != null) {
-                        procEnvironment.addElement(var);
-                    }
-                    var = line;
-                }
-            }
-            // Since we "look ahead" before adding, there's one last env var.
-            if (var != null) {
-                procEnvironment.addElement(var);
-            }
-        } catch (java.io.IOException exc) {
-            exc.printStackTrace();
-            // Just try to see how much we got
-        }
-        return procEnvironment;
-    }
-
-    private static String[] getProcEnvCommand() {
-        if (Os.isFamily("os/2")) {
-            // OS/2 - use same mechanism as Windows 2000
-            String[] cmd = {"cmd", "/c", "set" };
-            return cmd;
-        } else if (Os.isFamily("windows")) {
-            // Determine if we're running under XP/2000/NT or 98/95
-            if (!Os.isFamily("win9x")) {
-                // Windows XP/2000/NT
-                String[] cmd = {"cmd", "/c", "set" };
-                return cmd;
-            } else {
-                // Windows 98/95
-                String[] cmd = {"command.com", "/c", "set" };
-                return cmd;
-            }
-        } else if (Os.isFamily("z/os")) {
-            String[] cmd = {"/bin/env"};
-            return cmd;
-        } else if (Os.isFamily("unix")) {
-            // Generic UNIX
-            // Alternatively one could use: /bin/sh -c env
-            String[] cmd = {"/usr/bin/env"};
-            return cmd;
-        } else if (Os.isFamily("netware")) {
-            String[] cmd = {"env"};
-            return cmd;
-        } else {
-            // MAC OS 9 and previous
-            // TODO: I have no idea how to get it, someone must fix it
-            String[] cmd = null;
-            return cmd;
-        }
-    }
-
-    /**
-     * ByteArrayOutputStream#toString doesn't seem to work reliably on
-     * OS/390, at least not the way we use it in the execution
-     * context.
-     *
-     * @since Ant 1.5
-     */
-    public static String toString(ByteArrayOutputStream bos) {
-        if (Os.isFamily("z/os")) {
-            try {
-                return bos.toString("Cp1047");
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return bos.toString();
-    }
-
-    /**
-     * Creates a new execute object using <code>PumpStreamHandler</code> for
-     * stream handling.
-     */
-    public Execute() {
-        this(new PumpStreamHandler(), null);
-    }
-
-
-    /**
-     * Creates a new execute object.
-     *
-     * @param streamHandler the stream handler used to handle the input and
-     *        output streams of the subprocess.
-     */
-    public Execute(ExecuteStreamHandler streamHandler) {
-        this(streamHandler, null);
-    }
-
-    /**
-     * Creates a new execute object.
-     *
-     * @param streamHandler the stream handler used to handle the input and
-     *        output streams of the subprocess.
-     * @param watchdog a watchdog for the subprocess or <code>null</code> to
-     *        to disable a timeout for the subprocess.
-     */
-    public Execute(ExecuteStreamHandler streamHandler,
-                   ExecuteWatchdog watchdog) {
-        this.streamHandler = streamHandler;
-        this.watchdog = watchdog;
-    }
-
-
-    /**
-     * Returns the commandline used to create a subprocess.
-     *
-     * @return the commandline used to create a subprocess
-     */
-    public String[] getCommandline() {
-        return cmdl;
-    }
-
-
-    /**
-     * Sets the commandline of the subprocess to launch.
-     *
-     * @param commandline the commandline of the subprocess to launch
-     */
-    public void setCommandline(String[] commandline) {
-        cmdl = commandline;
-    }
-
-    /**
-     * Set whether to propagate the default environment or not.
-     *
-     * @param newenv whether to propagate the process environment.
-     */
-    public void setNewenvironment(boolean newenv) {
-        newEnvironment = newenv;
-    }
-
-    /**
-     * Returns the environment used to create a subprocess.
-     *
-     * @return the environment used to create a subprocess
-     */
-    public String[] getEnvironment() {
-        if (env == null || newEnvironment) {
-            return env;
-        }
-        return patchEnvironment();
-    }
-
-
-    /**
-     * Sets the environment variables for the subprocess to launch.
-     *
-     * @param env 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,
-     * or MRJ and setting user.dir works, or JDK 1.3 and there is
-     * official support in java.lang.Runtime.
-     *
-     * @param wd the working directory of the process.
-     */
-    public void setWorkingDirectory(File wd) {
-        if (wd == null || wd.getAbsolutePath().equals(antWorkingDirectory)) {
-            workingDirectory = null;
-        } else {
-            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 {
-        this.project = project;
-    }
-
-    /**
-     * Launch this execution through the VM, where possible, rather than through
-     * the OS's shell. In some cases and operating systems using the shell will
-     * allow the shell to perform additional processing such as associating an
-     * executable with a script, etc
-     *
-     * @param useVMLauncher true if exec should launch through thge VM,
-     *                   false if the shell should be used to launch the
-     *                   command.
-     */
-    public void setVMLauncher(boolean useVMLauncher) {
-        this.useVMLauncher = useVMLauncher;
-    }
-
-    /**
-     * Creates a process that runs a command.
-     *
-     * @param project the Project, only used for logging purposes, may be null.
-     * @param command the command to run
-     * @param env the environment for the command
-     * @param dir the working directory for the command
-     * @param useVM use the built-in exec command for JDK 1.3 if available.
-     *
-     * @since Ant 1.5
-     */
-    public static Process launch(Project project, String[] command,
-                                 String[] env, File dir, boolean useVM)
-        throws IOException {
-        CommandLauncher launcher
-            = vmLauncher != null ? vmLauncher : shellLauncher;
-        if (!useVM) {
-            launcher = shellLauncher;
-        }
-
-        return launcher.exec(project, command, env, dir);
-    }
-
-    /**
-     * Runs a process defined by the command line and returns its exit status.
-     *
-     * @return the exit status of the subprocess or <code>INVALID</code>
-     * @exception java.io.IOException The exception is thrown, if launching
-     *            of the subprocess failed
-     */
-    public int execute() throws IOException {
-        final Process process = launch(project, getCommandline(),
-                                       getEnvironment(), workingDirectory,
-                                       useVMLauncher);
-
-        try {
-            streamHandler.setProcessInputStream(process.getOutputStream());
-            streamHandler.setProcessOutputStream(process.getInputStream());
-            streamHandler.setProcessErrorStream(process.getErrorStream());
-        } catch (IOException e) {
-            process.destroy();
-            throw e;
-        }
-        streamHandler.start();
-
-        // add the process to the list of those to destroy if the VM exits
-        //
-        processDestroyer.add(process);
-
-        if (watchdog != null) {
-            watchdog.start(process);
-        }
-        waitFor(process);
-
-        // remove the process to the list of those to destroy if the VM exits
-        //
-        processDestroyer.remove(process);
-
-        if (watchdog != null) {
-            watchdog.stop();
-        }
-        streamHandler.stop();
-        if (watchdog != null) {
-            watchdog.checkException();
-        }
-        return getExitValue();
-    }
-
-    protected void waitFor(Process process) {
-        try {
-            process.waitFor();
-            setExitValue(process.exitValue());
-        } catch (InterruptedException e) {
-            process.destroy();
-        }
-    }
-
-    protected void setExitValue(int value) {
-        exitValue = value;
-    }
-
-    /**
-     * query the exit value of the process.
-     * @return the exit value, 1 if the process was killed,
-     * or Project.INVALID if no exit value has been received
-     */
-    public int getExitValue() {
-        return exitValue;
-    }
-
-    /**
-     * test for an untimely death of the process
-     * @return true iff a watchdog had to kill the process
-     * @since Ant 1.5
-     */
-    public boolean killedProcess() {
-        return watchdog != null && watchdog.killedProcess();
-    }
-
-    /**
-     * Patch the current environment with the new values from the user.
-     * @return the patched environment
-     */
-    private String[] patchEnvironment() {
-        Vector osEnv = (Vector) getProcEnvironment().clone();
-        for (int i = 0; i < env.length; i++) {
-            int pos = env[i].indexOf('=');
-            // Get key including "="
-            String key = env[i].substring(0, pos + 1);
-            int size = osEnv.size();
-            for (int j = 0; j < size; j++) {
-                if (((String) osEnv.elementAt(j)).startsWith(key)) {
-                    osEnv.removeElementAt(j);
-                    break;
-                }
-            }
-            osEnv.addElement(env[i]);
-        }
-        String[] result = new String[osEnv.size()];
-        osEnv.copyInto(result);
-        return result;
-    }
-
-    /**
-     * A utility method that runs an external command.  Writes the output and
-     * error streams of the command to the project log.
-     *
-     * @param task      The task that the command is part of.  Used for logging
-     * @param cmdline   The command to execute.
-     *
-     * @throws BuildException if the command does not return 0.
-     */
-    public static void runCommand(Task task, String[] cmdline)
-        throws BuildException {
-        try {
-            task.log(Commandline.describeCommand(cmdline),
-                     Project.MSG_VERBOSE);
-            Execute exe = new Execute(new LogStreamHandler(task,
-                                                           Project.MSG_INFO,
-                                                           Project.MSG_ERR));
-            exe.setAntRun(task.getProject());
-            exe.setCommandline(cmdline);
-            int retval = exe.execute();
-            if (retval != 0) {
-                throw new BuildException(cmdline[0]
-                    + " failed with return code " + retval, task.getLocation());
-            }
-        } catch (java.io.IOException exc) {
-            throw new BuildException("Could not launch " + cmdline[0] + ": "
-                + exc, task.getLocation());
-        }
-    }
-
-    /**
-     * A command launcher for a particular JVM/OS platform.  This class is
-     * a general purpose command launcher which can only launch commands in
-     * the current working directory.
-     */
-    private static class CommandLauncher {
-        /**
-         * Launches the given command in a new process.
-         *
-         * @param project       The project that the command is part of
-         * @param cmd           The command to execute
-         * @param env           The environment for the new process.  If null,
-         *                      the environment of the current proccess is used.
-         */
-        public Process exec(Project project, String[] cmd, String[] env)
-             throws IOException {
-            if (project != null) {
-                project.log("Execute:CommandLauncher: " +
-                            Commandline.describeCommand(cmd),
-                            Project.MSG_DEBUG);
-            }
-            return Runtime.getRuntime().exec(cmd, env);
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory.
-         *
-         * @param project       The project that the command is part of
-         * @param cmd           The command to execute
-         * @param env           The environment for the new process.  If null,
-         *                      the environment of the current proccess is used.
-         * @param workingDir    The directory to start the command in.  If null,
-         *                      the current directory is used
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            if (workingDir == null) {
-                return exec(project, cmd, env);
-            }
-            throw new IOException("Cannot execute a process in different "
-                + "directory under this JVM");
-        }
-    }
-
-    /**
-     * A command launcher for JDK/JRE 1.1 under Windows.  Fixes quoting problems
-     * in Runtime.exec().  Can only launch commands in the current working
-     * directory
-     */
-    private static class Java11CommandLauncher extends CommandLauncher {
-        /**
-         * Launches the given command in a new process.  Needs to quote
-         * arguments
-         */
-        public Process exec(Project project, String[] cmd, String[] env)
-             throws IOException {
-            // Need to quote arguments with spaces, and to escape
-            // quote characters
-            String[] newcmd = new String[cmd.length];
-            for (int i = 0; i < cmd.length; i++) {
-                newcmd[i] = Commandline.quoteArgument(cmd[i]);
-            }
-            if (project != null) {
-                project.log("Execute:Java11CommandLauncher: " +
-                            Commandline.describeCommand(newcmd),
-                            Project.MSG_DEBUG);
-            }
-            return Runtime.getRuntime().exec(newcmd, env);
-        }
-    }
-
-    /**
-     * A command launcher for JDK/JRE 1.3 (and higher).  Uses the built-in
-     * Runtime.exec() command
-     */
-    private static class Java13CommandLauncher extends CommandLauncher {
-        public Java13CommandLauncher() throws NoSuchMethodException {
-            // Locate method Runtime.exec(String[] cmdarray,
-            //                            String[] envp, File dir)
-            _execWithCWD = Runtime.class.getMethod("exec",
-                new Class[] {String[].class, String[].class, File.class});
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            try {
-                if (project != null) {
-                    project.log("Execute:Java13CommandLauncher: " +
-                                Commandline.describeCommand(cmd),
-                                Project.MSG_DEBUG);
-                }
-                Object[] arguments = { cmd, env, workingDir };
-                return (Process) _execWithCWD.invoke(Runtime.getRuntime(),
-                                                     arguments);
-            } catch (InvocationTargetException exc) {
-                Throwable realexc = exc.getTargetException();
-                if (realexc instanceof ThreadDeath) {
-                    throw (ThreadDeath) realexc;
-                } else if (realexc instanceof IOException) {
-                    throw (IOException) realexc;
-                } else {
-                    throw new BuildException("Unable to execute command",
-                                             realexc);
-                }
-            } catch (Exception exc) {
-                // IllegalAccess, IllegalArgument, ClassCast
-                throw new BuildException("Unable to execute command", exc);
-            }
-        }
-
-        private Method _execWithCWD;
-    }
-
-    /**
-     * A command launcher that proxies another command launcher.
-     *
-     * Sub-classes override exec(args, env, workdir)
-     */
-    private static class CommandLauncherProxy extends CommandLauncher {
-        CommandLauncherProxy(CommandLauncher launcher) {
-            _launcher = launcher;
-        }
-
-        /**
-         * Launches the given command in a new process.  Delegates this
-         * method to the proxied launcher
-         */
-        public Process exec(Project project, String[] cmd, String[] env)
-            throws IOException {
-            return _launcher.exec(project, cmd, env);
-        }
-
-        private CommandLauncher _launcher;
-    }
-
-    /**
-     * A command launcher for OS/2 that uses 'cmd.exe' when launching
-     * commands in directories other than the current working
-     * directory.
-     *
-     * <p>Unlike Windows NT and friends, OS/2's cd doesn't support the
-     * /d switch to change drives and directories in one go.</p>
-     */
-    private static class OS2CommandLauncher extends CommandLauncherProxy {
-        OS2CommandLauncher(CommandLauncher launcher) {
-            super(launcher);
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory.
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            File commandDir = workingDir;
-            if (workingDir == null) {
-                if (project != null) {
-                    commandDir = project.getBaseDir();
-                } else {
-                    return exec(project, cmd, env);
-                }
-            }
-
-            // Use cmd.exe to change to the specified drive and
-            // directory before running the command
-            final int preCmdLength = 7;
-            final String cmdDir = commandDir.getAbsolutePath();
-            String[] newcmd = new String[cmd.length + preCmdLength];
-            newcmd[0] = "cmd";
-            newcmd[1] = "/c";
-            newcmd[2] = cmdDir.substring(0, 2);
-            newcmd[3] = "&&";
-            newcmd[4] = "cd";
-            newcmd[5] = cmdDir.substring(2);
-            newcmd[6] = "&&";
-            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);
-
-            return exec(project, newcmd, env);
-        }
-    }
-
-    /**
-     * A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when
-     * launching commands in directories other than the current working
-     * directory.
-     */
-    private static class WinNTCommandLauncher extends CommandLauncherProxy {
-        WinNTCommandLauncher(CommandLauncher launcher) {
-            super(launcher);
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory.
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            File commandDir = workingDir;
-            if (workingDir == null) {
-                if (project != null) {
-                    commandDir = project.getBaseDir();
-                } else {
-                    return exec(project, cmd, env);
-                }
-            }
-
-            // Use cmd.exe to change to the specified directory before running
-            // the command
-            final int preCmdLength = 6;
-            String[] newcmd = new String[cmd.length + preCmdLength];
-            newcmd[0] = "cmd";
-            newcmd[1] = "/c";
-            newcmd[2] = "cd";
-            newcmd[3] = "/d";
-            newcmd[4] = commandDir.getAbsolutePath();
-            newcmd[5] = "&&";
-            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);
-
-            return exec(project, newcmd, env);
-        }
-    }
-
-    /**
-     * A command launcher for Mac that uses a dodgy mechanism to change
-     * working directory before launching commands.
-     */
-    private static class MacCommandLauncher extends CommandLauncherProxy {
-        MacCommandLauncher(CommandLauncher launcher) {
-            super(launcher);
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            if (workingDir == null) {
-                return exec(project, cmd, env);
-            }
-
-            System.getProperties().put("user.dir", workingDir.getAbsolutePath());
-            try {
-                return exec(project, cmd, env);
-            } finally {
-                System.getProperties().put("user.dir", antWorkingDirectory);
-            }
-        }
-    }
-
-    /**
-     * A command launcher that uses an auxiliary script to launch commands
-     * in directories other than the current working directory.
-     */
-    private static class ScriptCommandLauncher extends CommandLauncherProxy {
-        ScriptCommandLauncher(String script, CommandLauncher launcher) {
-            super(launcher);
-            _script = script;
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            if (project == null) {
-                if (workingDir == null) {
-                    return exec(project, cmd, env);
-                }
-                throw new IOException("Cannot locate antRun script: "
-                    + "No project provided");
-            }
-
-            // Locate the auxiliary script
-            String antHome = project.getProperty("ant.home");
-            if (antHome == null) {
-                throw new IOException("Cannot locate antRun script: "
-                    + "Property 'ant.home' not found");
-            }
-            String antRun = project.resolveFile(antHome + File.separator + _script).toString();
-
-            // Build the command
-            File commandDir = workingDir;
-            if (workingDir == null && project != null) {
-                commandDir = project.getBaseDir();
-            }
-
-            String[] newcmd = new String[cmd.length + 2];
-            newcmd[0] = antRun;
-            newcmd[1] = commandDir.getAbsolutePath();
-            System.arraycopy(cmd, 0, newcmd, 2, cmd.length);
-
-            return exec(project, newcmd, env);
-        }
-
-        private String _script;
-    }
-
-    /**
-     * A command launcher that uses an auxiliary perl script to launch commands
-     * in directories other than the current working directory.
-     */
-    private static class PerlScriptCommandLauncher
-        extends CommandLauncherProxy {
-        PerlScriptCommandLauncher(String script, CommandLauncher launcher) {
-            super(launcher);
-            _script = script;
-        }
-
-        /**
-         * Launches the given command in a new process, in the given working
-         * directory
-         */
-        public Process exec(Project project, String[] cmd, String[] env,
-                            File workingDir) throws IOException {
-            if (project == null) {
-                if (workingDir == null) {
-                    return exec(project, cmd, env);
-                }
-                throw new IOException("Cannot locate antRun script: "
-                    + "No project provided");
-            }
-
-            // Locate the auxiliary script
-            String antHome = project.getProperty("ant.home");
-            if (antHome == null) {
-                throw new IOException("Cannot locate antRun script: "
-                    + "Property 'ant.home' not found");
-            }
-            String antRun = project.resolveFile(antHome + File.separator + _script).toString();
-
-            // Build the command
-            File commandDir = workingDir;
-            if (workingDir == null && project != null) {
-                commandDir = project.getBaseDir();
-            }
-
-            String[] newcmd = new String[cmd.length + 3];
-            newcmd[0] = "perl";
-            newcmd[1] = antRun;
-            newcmd[2] = commandDir.getAbsolutePath();
-            System.arraycopy(cmd, 0, newcmd, 3, cmd.length);
-
-            return exec(project, newcmd, env);
-        }
-
-        private String _script;
-    }
-}
+package org.apache.beehive.test.tools.tch.ant;
+
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "Ant" and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+//package org.apache.tools.ant.taskdefs;
+import org.apache.tools.ant.taskdefs.*;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.taskdefs.condition.Os;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Vector;
+
+/**
+ * Runs an external program.
+ *
+ *
+ * @since Ant 1.2
+ *
+ * @version $Revision: 1.43.2.7 $
+ */
+public class Execute {
+
+    /** Invalid exit code. **/
+    public static final int INVALID = Integer.MAX_VALUE;
+
+    private String[] cmdl = null;
+    private String[] env = null;
+    private int exitValue = INVALID;
+    private ExecuteStreamHandler streamHandler;
+    private ExecuteWatchdog watchdog;
+    private File workingDirectory = null;
+    private Project project = null;
+    private boolean newEnvironment = false;
+
+    /** Controls whether the VM is used to launch commands, where possible */
+    private boolean useVMLauncher = true;
+
+    private static String antWorkingDirectory = System.getProperty("user.dir");
+    private static CommandLauncher vmLauncher = null;
+    private static CommandLauncher shellLauncher = null;
+    private static Vector procEnvironment = null;
+
+    /** Used to destroy processes when the VM exits. */
+    private static ProcessDestroyer processDestroyer = new ProcessDestroyer();
+
+    /**
+     * Builds a command launcher for the OS and JVM we are running under
+     */
+    static {
+        // Try using a JDK 1.3 launcher
+        try {
+            vmLauncher = new Java13CommandLauncher();
+        } catch (NoSuchMethodException exc) {
+            // Ignore and keep trying
+        }
+
+        if (Os.isFamily("mac")) {
+            // Mac
+            shellLauncher = new MacCommandLauncher(new CommandLauncher());
+        } else if (Os.isFamily("os/2")) {
+            // OS/2
+            shellLauncher = new OS2CommandLauncher(new CommandLauncher());
+        } else if (Os.isFamily("windows")) {
+            // Windows.  Need to determine which JDK we're running in
+
+            CommandLauncher baseLauncher;
+            if (System.getProperty("java.version").startsWith("1.1")) {
+                // JDK 1.1
+                baseLauncher = new Java11CommandLauncher();
+            } else {
+                // JDK 1.2
+                baseLauncher = new CommandLauncher();
+            }
+
+            if (!Os.isFamily("win9x")) {
+                // Windows XP/2000/NT
+                shellLauncher = new WinNTCommandLauncher(baseLauncher);
+            } else {
+                // Windows 98/95 - need to use an auxiliary script
+                shellLauncher
+                    = new ScriptCommandLauncher("bin/antRun.bat", baseLauncher);
+            }
+        } else if (Os.isFamily("netware")) {
+            // NetWare.  Need to determine which JDK we're running in
+            CommandLauncher baseLauncher;
+            if (System.getProperty("java.version").startsWith("1.1")) {
+                // JDK 1.1
+                baseLauncher = new Java11CommandLauncher();
+            } else {
+                // JDK 1.2
+                baseLauncher = new CommandLauncher();
+            }
+
+            shellLauncher
+                = new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher);
+        } else {
+            // Generic
+            shellLauncher = new ScriptCommandLauncher("bin/antRun",
+                new CommandLauncher());
+        }
+    }
+
+    /**
+     * Find the list of environment variables for this process.
+     */
+    public static synchronized Vector getProcEnvironment() {
+        if (procEnvironment != null) {
+            return procEnvironment;
+        }
+
+        procEnvironment = new Vector();
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            Execute exe = new Execute(new PumpStreamHandler(out));
+            exe.setCommandline(getProcEnvCommand());
+            // Make sure we do not recurse forever
+            exe.setNewenvironment(true);
+            int retval = exe.execute();
+            if (retval != 0) {
+                // Just try to use what we got
+            }
+
+            BufferedReader in =
+                new BufferedReader(new StringReader(toString(out)));
+
+            String var = null;
+            String line, lineSep = System.getProperty("line.separator");
+            while ((line = in.readLine()) != null) {
+                if (line.indexOf('=') == -1) {
+                    // Chunk part of previous env var (UNIX env vars can
+                    // contain embedded new lines).
+                    if (var == null) {
+                        var = lineSep + line;
+                    } else {
+                        var += lineSep + line;
+                    }
+                } else {
+                    // New env var...append the previous one if we have it.
+                    if (var != null) {
+                        procEnvironment.addElement(var);
+                    }
+                    var = line;
+                }
+            }
+            // Since we "look ahead" before adding, there's one last env var.
+            if (var != null) {
+                procEnvironment.addElement(var);
+            }
+        } catch (java.io.IOException exc) {
+            exc.printStackTrace();
+            // Just try to see how much we got
+        }
+        return procEnvironment;
+    }
+
+    private static String[] getProcEnvCommand() {
+        if (Os.isFamily("os/2")) {
+            // OS/2 - use same mechanism as Windows 2000
+            String[] cmd = {"cmd", "/c", "set" };
+            return cmd;
+        } else if (Os.isFamily("windows")) {
+            // Determine if we're running under XP/2000/NT or 98/95
+            if (!Os.isFamily("win9x")) {
+                // Windows XP/2000/NT
+                String[] cmd = {"cmd", "/c", "set" };
+                return cmd;
+            } else {
+                // Windows 98/95
+                String[] cmd = {"command.com", "/c", "set" };
+                return cmd;
+            }
+        } else if (Os.isFamily("z/os")) {
+            String[] cmd = {"/bin/env"};
+            return cmd;
+        } else if (Os.isFamily("unix")) {
+            // Generic UNIX
+            // Alternatively one could use: /bin/sh -c env
+            String[] cmd = {"/usr/bin/env"};
+            return cmd;
+        } else if (Os.isFamily("netware")) {
+            String[] cmd = {"env"};
+            return cmd;
+        } else {
+            // MAC OS 9 and previous
+            // TODO: I have no idea how to get it, someone must fix it
+            String[] cmd = null;
+            return cmd;
+        }
+    }
+
+    /**
+     * ByteArrayOutputStream#toString doesn't seem to work reliably on
+     * OS/390, at least not the way we use it in the execution
+     * context.
+     *
+     * @since Ant 1.5
+     */
+    public static String toString(ByteArrayOutputStream bos) {
+        if (Os.isFamily("z/os")) {
+            try {
+                return bos.toString("Cp1047");
+            } catch (java.io.UnsupportedEncodingException e) {
+            }
+        }
+        return bos.toString();
+    }
+
+    /**
+     * Creates a new execute object using <code>PumpStreamHandler</code> for
+     * stream handling.
+     */
+    public Execute() {
+        this(new PumpStreamHandler(), null);
+    }
+
+
+    /**
+     * Creates a new execute object.
+     *
+     * @param streamHandler the stream handler used to handle the input and
+     *        output streams of the subprocess.
+     */
+    public Execute(ExecuteStreamHandler streamHandler) {
+        this(streamHandler, null);
+    }
+
+    /**
+     * Creates a new execute object.
+     *
+     * @param streamHandler the stream handler used to handle the input and
+     *        output streams of the subprocess.
+     * @param watchdog a watchdog for the subprocess or <code>null</code> to
+     *        to disable a timeout for the subprocess.
+     */
+    public Execute(ExecuteStreamHandler streamHandler,
+                   ExecuteWatchdog watchdog) {
+        this.streamHandler = streamHandler;
+        this.watchdog = watchdog;
+    }
+
+
+    /**
+     * Returns the commandline used to create a subprocess.
+     *
+     * @return the commandline used to create a subprocess
+     */
+    public String[] getCommandline() {
+        return cmdl;
+    }
+
+
+    /**
+     * Sets the commandline of the subprocess to launch.
+     *
+     * @param commandline the commandline of the subprocess to launch
+     */
+    public void setCommandline(String[] commandline) {
+        cmdl = commandline;
+    }
+
+    /**
+     * Set whether to propagate the default environment or not.
+     *
+     * @param newenv whether to propagate the process environment.
+     */
+    public void setNewenvironment(boolean newenv) {
+        newEnvironment = newenv;
+    }
+
+    /**
+     * Returns the environment used to create a subprocess.
+     *
+     * @return the environment used to create a subprocess
+     */
+    public String[] getEnvironment() {
+        if (env == null || newEnvironment) {
+            return env;
+        }
+        return patchEnvironment();
+    }
+
+
+    /**
+     * Sets the environment variables for the subprocess to launch.
+     *
+     * @param env 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,
+     * or MRJ and setting user.dir works, or JDK 1.3 and there is
+     * official support in java.lang.Runtime.
+     *
+     * @param wd the working directory of the process.
+     */
+    public void setWorkingDirectory(File wd) {
+        if (wd == null || wd.getAbsolutePath().equals(antWorkingDirectory)) {
+            workingDirectory = null;
+        } else {
+            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 {
+        this.project = project;
+    }
+
+    /**
+     * Launch this execution through the VM, where possible, rather than through
+     * the OS's shell. In some cases and operating systems using the shell will
+     * allow the shell to perform additional processing such as associating an
+     * executable with a script, etc
+     *
+     * @param useVMLauncher true if exec should launch through thge VM,
+     *                   false if the shell should be used to launch the
+     *                   command.
+     */
+    public void setVMLauncher(boolean useVMLauncher) {
+        this.useVMLauncher = useVMLauncher;
+    }
+
+    /**
+     * Creates a process that runs a command.
+     *
+     * @param project the Project, only used for logging purposes, may be null.
+     * @param command the command to run
+     * @param env the environment for the command
+     * @param dir the working directory for the command
+     * @param useVM use the built-in exec command for JDK 1.3 if available.
+     *
+     * @since Ant 1.5
+     */
+    public static Process launch(Project project, String[] command,
+                                 String[] env, File dir, boolean useVM)
+        throws IOException {
+        CommandLauncher launcher
+            = vmLauncher != null ? vmLauncher : shellLauncher;
+        if (!useVM) {
+            launcher = shellLauncher;
+        }
+
+        return launcher.exec(project, command, env, dir);
+    }
+
+    /**
+     * Runs a process defined by the command line and returns its exit status.
+     *
+     * @return the exit status of the subprocess or <code>INVALID</code>
+     * @exception java.io.IOException The exception is thrown, if launching
+     *            of the subprocess failed
+     */
+    public int execute() throws IOException {
+        final Process process = launch(project, getCommandline(),
+                                       getEnvironment(), workingDirectory,
+                                       useVMLauncher);
+
+        try {
+            streamHandler.setProcessInputStream(process.getOutputStream());
+            streamHandler.setProcessOutputStream(process.getInputStream());
+            streamHandler.setProcessErrorStream(process.getErrorStream());
+        } catch (IOException e) {
+            process.destroy();
+            throw e;
+        }
+        streamHandler.start();
+
+        // add the process to the list of those to destroy if the VM exits
+        //
+        processDestroyer.add(process);
+
+        if (watchdog != null) {
+            watchdog.start(process);
+        }
+        waitFor(process);
+
+        // remove the process to the list of those to destroy if the VM exits
+        //
+        processDestroyer.remove(process);
+
+        if (watchdog != null) {
+            watchdog.stop();
+        }
+        streamHandler.stop();
+        if (watchdog != null) {
+            watchdog.checkException();
+        }
+        return getExitValue();
+    }
+
+    protected void waitFor(Process process) {
+        try {
+            process.waitFor();
+            setExitValue(process.exitValue());
+        } catch (InterruptedException e) {
+            process.destroy();
+        }
+    }
+
+    protected void setExitValue(int value) {
+        exitValue = value;
+    }
+
+    /**
+     * query the exit value of the process.
+     * @return the exit value, 1 if the process was killed,
+     * or Project.INVALID if no exit value has been received
+     */
+    public int getExitValue() {
+        return exitValue;
+    }
+
+    /**
+     * test for an untimely death of the process
+     * @return true iff a watchdog had to kill the process
+     * @since Ant 1.5
+     */
+    public boolean killedProcess() {
+        return watchdog != null && watchdog.killedProcess();
+    }
+
+    /**
+     * Patch the current environment with the new values from the user.
+     * @return the patched environment
+     */
+    private String[] patchEnvironment() {
+        Vector osEnv = (Vector) getProcEnvironment().clone();
+        for (int i = 0; i < env.length; i++) {
+            int pos = env[i].indexOf('=');
+            // Get key including "="
+            String key = env[i].substring(0, pos + 1);
+            int size = osEnv.size();
+            for (int j = 0; j < size; j++) {
+                if (((String) osEnv.elementAt(j)).startsWith(key)) {
+                    osEnv.removeElementAt(j);
+                    break;
+                }
+            }
+            osEnv.addElement(env[i]);
+        }
+        String[] result = new String[osEnv.size()];
+        osEnv.copyInto(result);
+        return result;
+    }
+
+    /**
+     * A utility method that runs an external command.  Writes the output and
+     * error streams of the command to the project log.
+     *
+     * @param task      The task that the command is part of.  Used for logging
+     * @param cmdline   The command to execute.
+     *
+     * @throws BuildException if the command does not return 0.
+     */
+    public static void runCommand(Task task, String[] cmdline)
+        throws BuildException {
+        try {
+            task.log(Commandline.describeCommand(cmdline),
+                     Project.MSG_VERBOSE);
+            Execute exe = new Execute(new LogStreamHandler(task,
+                                                           Project.MSG_INFO,
+                                                           Project.MSG_ERR));
+            exe.setAntRun(task.getProject());
+            exe.setCommandline(cmdline);
+            int retval = exe.execute();
+            if (retval != 0) {
+                throw new BuildException(cmdline[0]
+                    + " failed with return code " + retval, task.getLocation());
+            }
+        } catch (java.io.IOException exc) {
+            throw new BuildException("Could not launch " + cmdline[0] + ": "
+                + exc, task.getLocation());
+        }
+    }
+
+    /**
+     * A command launcher for a particular JVM/OS platform.  This class is
+     * a general purpose command launcher which can only launch commands in
+     * the current working directory.
+     */
+    private static class CommandLauncher {
+        /**
+         * Launches the given command in a new process.
+         *
+         * @param project       The project that the command is part of
+         * @param cmd           The command to execute
+         * @param env           The environment for the new process.  If null,
+         *                      the environment of the current proccess is used.
+         */
+        public Process exec(Project project, String[] cmd, String[] env)
+             throws IOException {
+            if (project != null) {
+                project.log("Execute:CommandLauncher: " +
+                            Commandline.describeCommand(cmd),
+                            Project.MSG_DEBUG);
+            }
+            return Runtime.getRuntime().exec(cmd, env);
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory.
+         *
+         * @param project       The project that the command is part of
+         * @param cmd           The command to execute
+         * @param env           The environment for the new process.  If null,
+         *                      the environment of the current proccess is used.
+         * @param workingDir    The directory to start the command in.  If null,
+         *                      the current directory is used
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            if (workingDir == null) {
+                return exec(project, cmd, env);
+            }
+            throw new IOException("Cannot execute a process in different "
+                + "directory under this JVM");
+        }
+    }
+
+    /**
+     * A command launcher for JDK/JRE 1.1 under Windows.  Fixes quoting problems
+     * in Runtime.exec().  Can only launch commands in the current working
+     * directory
+     */
+    private static class Java11CommandLauncher extends CommandLauncher {
+        /**
+         * Launches the given command in a new process.  Needs to quote
+         * arguments
+         */
+        public Process exec(Project project, String[] cmd, String[] env)
+             throws IOException {
+            // Need to quote arguments with spaces, and to escape
+            // quote characters
+            String[] newcmd = new String[cmd.length];
+            for (int i = 0; i < cmd.length; i++) {
+                newcmd[i] = Commandline.quoteArgument(cmd[i]);
+            }
+            if (project != null) {
+                project.log("Execute:Java11CommandLauncher: " +
+                            Commandline.describeCommand(newcmd),
+                            Project.MSG_DEBUG);
+            }
+            return Runtime.getRuntime().exec(newcmd, env);
+        }
+    }
+
+    /**
+     * A command launcher for JDK/JRE 1.3 (and higher).  Uses the built-in
+     * Runtime.exec() command
+     */
+    private static class Java13CommandLauncher extends CommandLauncher {
+        public Java13CommandLauncher() throws NoSuchMethodException {
+            // Locate method Runtime.exec(String[] cmdarray,
+            //                            String[] envp, File dir)
+            _execWithCWD = Runtime.class.getMethod("exec",
+                new Class[] {String[].class, String[].class, File.class});
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            try {
+                if (project != null) {
+                    project.log("Execute:Java13CommandLauncher: " +
+                                Commandline.describeCommand(cmd),
+                                Project.MSG_DEBUG);
+                }
+                Object[] arguments = { cmd, env, workingDir };
+                return (Process) _execWithCWD.invoke(Runtime.getRuntime(),
+                                                     arguments);
+            } catch (InvocationTargetException exc) {
+                Throwable realexc = exc.getTargetException();
+                if (realexc instanceof ThreadDeath) {
+                    throw (ThreadDeath) realexc;
+                } else if (realexc instanceof IOException) {
+                    throw (IOException) realexc;
+                } else {
+                    throw new BuildException("Unable to execute command",
+                                             realexc);
+                }
+            } catch (Exception exc) {
+                // IllegalAccess, IllegalArgument, ClassCast
+                throw new BuildException("Unable to execute command", exc);
+            }
+        }
+
+        private Method _execWithCWD;
+    }
+
+    /**
+     * A command launcher that proxies another command launcher.
+     *
+     * Sub-classes override exec(args, env, workdir)
+     */
+    private static class CommandLauncherProxy extends CommandLauncher {
+        CommandLauncherProxy(CommandLauncher launcher) {
+            _launcher = launcher;
+        }
+
+        /**
+         * Launches the given command in a new process.  Delegates this
+         * method to the proxied launcher
+         */
+        public Process exec(Project project, String[] cmd, String[] env)
+            throws IOException {
+            return _launcher.exec(project, cmd, env);
+        }
+
+        private CommandLauncher _launcher;
+    }
+
+    /**
+     * A command launcher for OS/2 that uses 'cmd.exe' when launching
+     * commands in directories other than the current working
+     * directory.
+     *
+     * <p>Unlike Windows NT and friends, OS/2's cd doesn't support the
+     * /d switch to change drives and directories in one go.</p>
+     */
+    private static class OS2CommandLauncher extends CommandLauncherProxy {
+        OS2CommandLauncher(CommandLauncher launcher) {
+            super(launcher);
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory.
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            File commandDir = workingDir;
+            if (workingDir == null) {
+                if (project != null) {
+                    commandDir = project.getBaseDir();
+                } else {
+                    return exec(project, cmd, env);
+                }
+            }
+
+            // Use cmd.exe to change to the specified drive and
+            // directory before running the command
+            final int preCmdLength = 7;
+            final String cmdDir = commandDir.getAbsolutePath();
+            String[] newcmd = new String[cmd.length + preCmdLength];
+            newcmd[0] = "cmd";
+            newcmd[1] = "/c";
+            newcmd[2] = cmdDir.substring(0, 2);
+            newcmd[3] = "&&";
+            newcmd[4] = "cd";
+            newcmd[5] = cmdDir.substring(2);
+            newcmd[6] = "&&";
+            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);
+
+            return exec(project, newcmd, env);
+        }
+    }
+
+    /**
+     * A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when
+     * launching commands in directories other than the current working
+     * directory.
+     */
+    private static class WinNTCommandLauncher extends CommandLauncherProxy {
+        WinNTCommandLauncher(CommandLauncher launcher) {
+            super(launcher);
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory.
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            File commandDir = workingDir;
+            if (workingDir == null) {
+                if (project != null) {
+                    commandDir = project.getBaseDir();
+                } else {
+                    return exec(project, cmd, env);
+                }
+            }
+
+            // Use cmd.exe to change to the specified directory before running
+            // the command
+            final int preCmdLength = 6;
+            String[] newcmd = new String[cmd.length + preCmdLength];
+            newcmd[0] = "cmd";
+            newcmd[1] = "/c";
+            newcmd[2] = "cd";
+            newcmd[3] = "/d";
+            newcmd[4] = commandDir.getAbsolutePath();
+            newcmd[5] = "&&";
+            System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length);
+
+            return exec(project, newcmd, env);
+        }
+    }
+
+    /**
+     * A command launcher for Mac that uses a dodgy mechanism to change
+     * working directory before launching commands.
+     */
+    private static class MacCommandLauncher extends CommandLauncherProxy {
+        MacCommandLauncher(CommandLauncher launcher) {
+            super(launcher);
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            if (workingDir == null) {
+                return exec(project, cmd, env);
+            }
+
+            System.getProperties().put("user.dir", workingDir.getAbsolutePath());
+            try {
+                return exec(project, cmd, env);
+            } finally {
+                System.getProperties().put("user.dir", antWorkingDirectory);
+            }
+        }
+    }
+
+    /**
+     * A command launcher that uses an auxiliary script to launch commands
+     * in directories other than the current working directory.
+     */
+    private static class ScriptCommandLauncher extends CommandLauncherProxy {
+        ScriptCommandLauncher(String script, CommandLauncher launcher) {
+            super(launcher);
+            _script = script;
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            if (project == null) {
+                if (workingDir == null) {
+                    return exec(project, cmd, env);
+                }
+                throw new IOException("Cannot locate antRun script: "
+                    + "No project provided");
+            }
+
+            // Locate the auxiliary script
+            String antHome = project.getProperty("ant.home");
+            if (antHome == null) {
+                throw new IOException("Cannot locate antRun script: "
+                    + "Property 'ant.home' not found");
+            }
+            String antRun = project.resolveFile(antHome + File.separator + _script).toString();
+
+            // Build the command
+            File commandDir = workingDir;
+            if (workingDir == null && project != null) {
+                commandDir = project.getBaseDir();
+            }
+
+            String[] newcmd = new String[cmd.length + 2];
+            newcmd[0] = antRun;
+            newcmd[1] = commandDir.getAbsolutePath();
+            System.arraycopy(cmd, 0, newcmd, 2, cmd.length);
+
+            return exec(project, newcmd, env);
+        }
+
+        private String _script;
+    }
+
+    /**
+     * A command launcher that uses an auxiliary perl script to launch commands
+     * in directories other than the current working directory.
+     */
+    private static class PerlScriptCommandLauncher
+        extends CommandLauncherProxy {
+        PerlScriptCommandLauncher(String script, CommandLauncher launcher) {
+            super(launcher);
+            _script = script;
+        }
+
+        /**
+         * Launches the given command in a new process, in the given working
+         * directory
+         */
+        public Process exec(Project project, String[] cmd, String[] env,
+                            File workingDir) throws IOException {
+            if (project == null) {
+                if (workingDir == null) {
+                    return exec(project, cmd, env);
+                }
+                throw new IOException("Cannot locate antRun script: "
+                    + "No project provided");
+            }
+
+            // Locate the auxiliary script
+            String antHome = project.getProperty("ant.home");
+            if (antHome == null) {
+                throw new IOException("Cannot locate antRun script: "
+                    + "Property 'ant.home' not found");
+            }
+            String antRun = project.resolveFile(antHome + File.separator + _script).toString();
+
+            // Build the command
+            File commandDir = workingDir;
+            if (workingDir == null && project != null) {
+                commandDir = project.getBaseDir();
+            }
+
+            String[] newcmd = new String[cmd.length + 3];
+            newcmd[0] = "perl";
+            newcmd[1] = antRun;
+            newcmd[2] = commandDir.getAbsolutePath();
+            System.arraycopy(cmd, 0, newcmd, 3, cmd.length);
+
+            return exec(project, newcmd, env);
+        }
+
+        private String _script;
+    }
+}

Propchange: beehive/trunk/controls/test/tools/tch/src/java/org/apache/beehive/test/tools/tch/ant/Execute.java
------------------------------------------------------------------------------
    svn:eol-style = native