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