1e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes/*
2e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Licensed to the Apache Software Foundation (ASF) under one or more
3e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * contributor license agreements.  See the NOTICE file distributed with
4e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * this work for additional information regarding copyright ownership.
5e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * The ASF licenses this file to You under the Apache License, Version 2.0
6e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * (the "License"); you may not use this file except in compliance with
7e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * the License.  You may obtain a copy of the License at
8e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes *
9e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes *     http://www.apache.org/licenses/LICENSE-2.0
10e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes *
11e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * Unless required by applicable law or agreed to in writing, software
12e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
13e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * See the License for the specific language governing permissions and
15e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes * limitations under the License.
16e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes */
17e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
18e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespackage tests.support;
19e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
20e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.ByteArrayOutputStream;
21e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.File;
22e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.IOException;
23e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.InputStream;
24e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.io.PrintStream;
25e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.util.ArrayList;
26e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.util.List;
27e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport java.util.StringTokenizer;
28e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
29e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughesimport junit.framework.TestCase;
30e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
31e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughespublic class Support_Exec extends TestCase {
32e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
33e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    /**
34e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     * Exec java returns the exitCode, and stdOut and stdErr as strings
35e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     */
36e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static Object[] runJava(List<String> args, String[] envp,
378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput)
38e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
39e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        String executable = System.getProperty("java.home");
40e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (!executable.endsWith(File.separator)) {
41e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            executable += File.separator;
42e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
43e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        executable += "bin" + File.separator + "java";
44e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
45e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // parse hy.test.vmargs if was given
46e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        String testVMArgs = System.getProperty("hy.test.vmargs");
47e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (testVMArgs != null) {
48e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            StringTokenizer st = new StringTokenizer(testVMArgs, " ");
49e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            int i = 0; // add at the beginning but maintain order
50e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            while (st.hasMoreTokens()) {
51e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                args.add(i++, st.nextToken());
52e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
53e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
54e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
55e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return run(executable, args, envp, displayOutput);
56e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
57e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
58e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    /**
59e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     * Exec command returns the exitCode, and stdOut and stdErr as strings
60e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     */
61e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static Object[] run(String command, List<String> args, String[] envp,
628d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput)
63e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
64e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Object[] arr = exec(command, args, envp, displayOutput);
65e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
66e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Process proc = (Process) arr[0];
67e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        StringBuilder output = new StringBuilder();
68e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        InputStream in = proc.getInputStream();
69e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        int result;
70e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        byte[] bytes = new byte[1024];
71e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
72e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        while ((result = in.read(bytes)) != -1) {
73e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            output.append(new String(bytes, 0, result));
74e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            if (displayOutput) {
75e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                System.out.write(bytes, 0, result);
76e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
77e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
78e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
79e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        in.close();
80e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        proc.waitFor();
81e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        int exitCode = proc.exitValue();
82e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        proc.destroy();
83e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return new Object[] {
848d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                Integer.valueOf(exitCode),
858d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                output.toString(),
868d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                ((StringBuilder) arr[1]).toString()
87e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        };
88e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
898d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath
90e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    /**
918d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath     * This function returns the output of the process as a string
92e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     */
93e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static String execJava(String[] args, String[] classpath,
948d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput)
958d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            throws IOException, InterruptedException {
96e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Object[] arr =
978d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                execJavaCommon(args, classpath, null, displayOutput, true);
98e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
99e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return getProcessOutput(arr, displayOutput, true);
100e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
101e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
102e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    /**
103e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     * This function returns the output of the process as a string
104e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes     */
105e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static String execJava(String[] args, String[] classpath,
1068d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            String[] envp, boolean displayOutput)
107e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
108e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Object[] arr =
1098d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                execJavaCommon(args, classpath, envp, displayOutput, false);
110e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
111e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return getProcessOutput(arr, displayOutput, true);
112e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
113e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
114e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    private static String getProcessOutput(Object[] arr, boolean displayOutput,
1158d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean checkStderr)
116e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
117e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Process proc = (Process) arr[0];
118e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        StringBuilder output = new StringBuilder();
119e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        InputStream in = proc.getInputStream();
120e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        int result;
121e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        byte[] bytes = new byte[1024];
122e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
123e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        while ((result = in.read(bytes)) != -1) {
124e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            output.append(new String(bytes, 0, result));
125e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            if (displayOutput) {
126e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                System.out.write(bytes, 0, result);
127e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
128e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
129e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
130e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        in.close();
131e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        proc.waitFor();
132e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (checkStderr) {
133e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            checkStderr(arr);
134e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
135e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        proc.destroy();
136e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
137e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return output.toString();
138e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
139e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
140e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static void checkStderr(Object[] execArgs) {
1418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath        StringBuilder errBuf = (StringBuilder) execArgs[1];
142e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
1438d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath        synchronized (errBuf) {
1448d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            if (errBuf.length() > 0) {
1458d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                fail(errBuf.toString());
146e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
1478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath        }
148e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
149e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
150e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    public static Object[] execJava2(String[] args, String[] classpath,
1518d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput)
152e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
153e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return execJavaCommon(args, classpath, null, displayOutput, true);
154e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
155e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
156e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    private static Object[] execJavaCommon(String[] args, String[] classpath,
1578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            String[] envp,
1588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput,
1598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean appendToSystemClassPath)
160e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
161e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // this function returns the resulting process from the exec
162e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        ArrayList<String> execArgs = null;
163e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        StringBuilder classPathString = new StringBuilder();
164e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        StringBuilder command;
165e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
166e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        execArgs = new ArrayList<String>(3 + args.length);
167e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
168e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // construct the name of executable file
169e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        String executable = System.getProperty("java.home");
170e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (!executable.endsWith(File.separator)) {
171e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            executable += File.separator;
172e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
173e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        executable += "bin" + File.separator + "java";
174e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
175e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // add classpath string
176e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (classpath != null) {
177e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            for (String element : classpath) {
178e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                classPathString.append(File.pathSeparator);
179e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                classPathString.append(element);
180e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
181e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
182e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (appendToSystemClassPath) {
183e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            execArgs.add("-cp");
184e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            execArgs.add(System.getProperty("java.class.path") +
1858d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    classPathString);
186e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        } else {
187e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            if (classpath != null) {
188e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                execArgs.add("-cp");
189e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                execArgs.add(classPathString.toString());
190e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
191e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
192e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
193e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // parse hy.test.vmargs if was given
194e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        String testVMArgs = System.getProperty("hy.test.vmargs");
195e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (testVMArgs != null) {
196e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            StringTokenizer st = new StringTokenizer(testVMArgs, " ");
197e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
198e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            while (st.hasMoreTokens()) {
199e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                execArgs.add(st.nextToken());
200e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
201e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
202e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
203e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // add custom args given as parameter
204e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        for (String arg : args) {
205e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            execArgs.add(arg);
206e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
207e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return exec(executable, execArgs, envp, displayOutput);
208e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
209e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
210e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    private static Object[] exec(String command, List<String> args,
2118d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            String[] envp,
2128d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            boolean displayOutput)
213e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            throws IOException, InterruptedException {
214e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // this function returns the resulting process from the exec
215e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        args.add(0, command);
216e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
217e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        if (displayOutput) {
218e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            StringBuilder commandLine;
219e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            // construct command line string and print it to stdout
220e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            commandLine = new StringBuilder(args.get(0));
221e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            for (int i = 1; i < args.size(); i++) {
222e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                commandLine.append(" ");
223e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                commandLine.append(args.get(i));
224e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
225e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            System.out.println("Exec: " + commandLine.toString());
226e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            System.out.println();
227e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
228e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
229e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        // execute java process
230e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        final Process proc =
2318d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                Runtime.getRuntime().exec(args.toArray(new String[args.size()]),
2328d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        envp);
233e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
234e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        final StringBuilder errBuf = new StringBuilder();
235e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        Thread errThread = new Thread(new Runnable() {
2368d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            public void run() {
2378d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                synchronized (errBuf) {
2388d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    InputStream err;
2398d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    int result;
2408d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    byte[] bytes = new byte[1024];
2418d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath
2428d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    synchronized (proc) {
2438d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        proc.notifyAll();
2448d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    }
245e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
2468d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    err = proc.getErrorStream();
2478d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    try {
2488d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        while ((result = err.read(bytes)) != -1) {
2498d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                            System.err.write(bytes, 0, result);
2508d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                            errBuf.append(new String(bytes));
251e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                        }
2528d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        err.close();
2538d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    } catch (IOException e) {
2548d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        ByteArrayOutputStream out =
2558d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                                new ByteArrayOutputStream();
2568d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        PrintStream printer = new PrintStream(out);
2578d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath
2588d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        e.printStackTrace();
2598d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        e.printStackTrace(printer);
2608d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        printer.close();
2618d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                        errBuf.append(new String(out.toByteArray()));
262e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                    }
263e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                }
2648d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            }
2658d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath        });
266e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes
267e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        synchronized (proc) {
268e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            errThread.start();
269e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            // wait for errThread to start
270e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            int count = 0;
271e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            boolean isFinished = false;
2728d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            while (!isFinished) {
273e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                try {
274e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                    proc.wait();
275e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                    isFinished = true;
276e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                } catch (InterruptedException e) {
2778d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath                    if (++count == 2) {
278e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                        throw e;
279e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                    }
280e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                }
281e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
2828d8858e39800de641b50f6e8e864af9cf68bedeaNarayan Kamath            if (count > 0) {
283e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes                Thread.currentThread().interrupt();
284e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes            }
285e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        }
286e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes        return new Object[] { proc, errBuf };
287e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes    }
288e98fbf8686c5289bf03fe5c3de7ff82d3a77104dElliott Hughes}
289