1 /* 2 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.test.lib; 25 26 import java.io.ByteArrayOutputStream; 27 import java.io.IOException; 28 import java.lang.management.ManagementFactory; 29 import java.lang.management.RuntimeMXBean; 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 34 /** 35 * @deprecated This class is deprecated. Use the one from 36 * {@code <root>/test/lib/share/classes/jdk/test/lib/process} 37 */ 38 @Deprecated 39 public final class ProcessTools { 40 41 private ProcessTools() { 42 } 43 44 /** 45 * Pumps stdout and stderr from running the process into a String. 46 * 47 * @param processBuilder ProcessBuilder to run. 48 * @return Output from process. 49 * @throws IOException If an I/O error occurs. 50 */ 51 public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException { 52 return getOutput(processBuilder.start()); 53 } 54 55 /** 56 * Pumps stdout and stderr the running process into a String. 57 * 58 * @param process Process to pump. 59 * @return Output from process. 60 * @throws IOException If an I/O error occurs. 61 */ 62 public static OutputBuffer getOutput(Process process) throws IOException { 63 ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); 64 ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); 65 StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); 66 StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); 67 Thread outPumperThread = new Thread(outPumper); 68 Thread errPumperThread = new Thread(errPumper); 69 70 outPumperThread.setDaemon(true); 71 errPumperThread.setDaemon(true); 72 73 outPumperThread.start(); 74 errPumperThread.start(); 75 76 try { 77 process.waitFor(); 78 outPumperThread.join(); 79 errPumperThread.join(); 80 } catch (InterruptedException e) { 81 Thread.currentThread().interrupt(); 82 return null; 83 } 84 85 return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); 86 } 87 88 /** 89 * Get the process id of the current running Java process 90 * 91 * @return Process id 92 */ 93 public static long getProcessId() throws Exception { 94 return ProcessHandle.current().getPid(); 95 } 96 97 /** 98 * Get the string containing input arguments passed to the VM 99 * 100 * @return arguments 101 */ 102 public static String getVmInputArguments() { 103 RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); 104 105 List<String> args = runtime.getInputArguments(); 106 StringBuilder result = new StringBuilder(); 107 for (String arg : args) 108 result.append(arg).append(' '); 109 110 return result.toString(); 111 } 112 113 /** 114 * Gets the array of strings containing input arguments passed to the VM 115 * 116 * @return arguments 117 */ 118 public static String[] getVmInputArgs() { 119 RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); 120 List<String> args = runtime.getInputArguments(); 121 return args.toArray(new String[args.size()]); 122 } 123 124 /** 125 * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) 126 * 127 * @return String[] with platform specific arguments, empty if there are none 128 */ 129 public static String[] getPlatformSpecificVMArgs() { 130 131 if (Platform.is64bit() && Platform.isSolaris()) { 132 return new String[] { "-d64" }; 133 } 134 135 return new String[] {}; 136 } 137 138 /** 139 * Create ProcessBuilder using the java launcher from the jdk to be tested and 140 * with any platform specific arguments prepended 141 */ 142 public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { 143 return createJavaProcessBuilder(false, command); 144 } 145 146 public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception { 147 String javapath = JDKToolFinder.getJDKTool("java"); 148 149 ArrayList<String> args = new ArrayList<>(); 150 args.add(javapath); 151 Collections.addAll(args, getPlatformSpecificVMArgs()); 152 153 args.add("-cp"); 154 args.add(System.getProperty("java.class.path")); 155 156 if (addTestVmAndJavaOptions) { 157 Collections.addAll(args, Utils.getTestJavaOpts()); 158 } 159 160 Collections.addAll(args, command); 161 162 // Reporting 163 StringBuilder cmdLine = new StringBuilder(); 164 for (String cmd : args) { 165 cmdLine.append(cmd).append(' '); 166 } 167 System.out.println("Command line: [" + cmdLine.toString() + "]"); 168 169 return new ProcessBuilder(args.toArray(new String[args.size()])); 170 } 171 172 /** 173 * Executes a test jvm process, waits for it to finish and returns the process output. 174 * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. 175 * The java from the test.jdk is used to execute the command. 176 * 177 * The command line will be like: 178 * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds 179 * 180 * @param cmds User specifed arguments. 181 * @return The output from the process. 182 */ 183 public static OutputAnalyzer executeTestJvm(String... cmds) throws Throwable { 184 ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds)); 185 return executeProcess(pb); 186 } 187 188 /** 189 * Executes a test jvm process, waits for it to finish and returns the process output. 190 * The default jvm options from the test's run command, jtreg, test.vm.opts and test.java.opts, are added. 191 * The java from the test.jdk is used to execute the command. 192 * 193 * The command line will be like: 194 * {test.jdk}/bin/java {test.fromRun.opts} {test.vm.opts} {test.java.opts} cmds 195 * 196 * @param cmds User specifed arguments. 197 * @return The output from the process. 198 */ 199 public static OutputAnalyzer executeTestJvmAllArgs(String... cmds) throws Throwable { 200 List<String> argsList = new ArrayList<>(); 201 String[] testArgs = getVmInputArgs(); 202 Collections.addAll(argsList, testArgs); 203 Collections.addAll(argsList, Utils.addTestJavaOpts(cmds)); 204 ProcessBuilder pb = createJavaProcessBuilder(argsList.toArray(new String[argsList.size()])); 205 return executeProcess(pb); 206 } 207 208 /** 209 * Executes a process, waits for it to finish and returns the process output. 210 * The process will have exited before this method returns. 211 * @param pb The ProcessBuilder to execute. 212 * @return The {@linkplain OutputAnalyzer} instance wrapping the process. 213 */ 214 public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { 215 OutputAnalyzer output = null; 216 Process p = null; 217 boolean failed = false; 218 try { 219 p = pb.start(); 220 output = new OutputAnalyzer(p); 221 p.waitFor(); 222 223 return output; 224 } catch (Throwable t) { 225 if (p != null) { 226 p.destroyForcibly().waitFor(); 227 } 228 229 failed = true; 230 System.out.println("executeProcess() failed: " + t); 231 throw t; 232 } finally { 233 if (failed) { 234 System.err.println(getProcessLog(pb, output)); 235 } 236 } 237 } 238 239 /** 240 * Executes a process, waits for it to finish and returns the process output. 241 * @param cmds The command line to execute. 242 * @return The output from the process. 243 */ 244 public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { 245 return executeProcess(new ProcessBuilder(cmds)); 246 } 247 248 /** 249 * Used to log command line, stdout, stderr and exit code from an executed process. 250 * @param pb The executed process. 251 * @param output The output from the process. 252 */ 253 public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) { 254 String stderr = output == null ? "null" : output.getStderr(); 255 String stdout = output == null ? "null" : output.getStdout(); 256 String exitValue = output == null ? "null": Integer.toString(output.getExitValue()); 257 StringBuilder logMsg = new StringBuilder(); 258 final String nl = System.getProperty("line.separator"); 259 logMsg.append("--- ProcessLog ---" + nl); 260 logMsg.append("cmd: " + getCommandLine(pb) + nl); 261 logMsg.append("exitvalue: " + exitValue + nl); 262 logMsg.append("stderr: " + stderr + nl); 263 logMsg.append("stdout: " + stdout + nl); 264 return logMsg.toString(); 265 } 266 267 /** 268 * @return The full command line for the ProcessBuilder. 269 */ 270 public static String getCommandLine(ProcessBuilder pb) { 271 if (pb == null) { 272 return "null"; 273 } 274 StringBuilder cmd = new StringBuilder(); 275 for (String s : pb.command()) { 276 cmd.append(s).append(" "); 277 } 278 return cmd.toString().trim(); 279 } 280 }