1 /*
2 * Copyright (c) 2013, 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.testlibrary;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.PrintStream;
29 import java.lang.management.ManagementFactory;
30 import java.lang.management.RuntimeMXBean;
31 import java.lang.reflect.Field;
32 import java.lang.reflect.Method;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.Map;
36 import java.util.concurrent.ExecutionException;
37 import java.util.concurrent.Future;
38 import java.util.concurrent.Phaser;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.TimeoutException;
41
42 import sun.management.VMManagement;
43
44 public final class ProcessTools {
45 private static final class LineForwarder extends StreamPumper.LinePump {
46 private final PrintStream ps;
47 private final String prefix;
48 LineForwarder(String prefix, PrintStream os) {
49 this.ps = os;
50 this.prefix = prefix;
51 }
52 @Override
53 protected void processLine(String line) {
54 ps.println("[" + prefix + "] " + line);
55 }
56 }
57
58 private ProcessTools() {
59 }
60
61 /**
62 * <p>Starts a process from its builder.</p>
63 * <span>The default redirects of STDOUT and STDERR are started</span>
64 * @param name The process name
65 * @param processBuilder The process builder
66 * @return Returns the initialized process
67 * @throws IOException
68 */
69 public static Process startProcess(String name,
70 ProcessBuilder processBuilder)
71 throws IOException {
72 Process p = null;
73 try {
74 p = startProcess(name, processBuilder, -1, TimeUnit.NANOSECONDS);
75 } catch (InterruptedException | TimeoutException e) {
76 // can't ever happen
77 }
78 return p;
79 }
80
81 /**
82 * <p>Starts a process from its builder.</p>
83 * <span>The default redirects of STDOUT and STDERR are started</span>
84 * @param name The process name
85 * @param processBuilder The process builder
86 * @param timeout The timeout for the warmup waiting
87 * @param unit The timeout {@linkplain TimeUnit}
88 * @return Returns the initialized {@linkplain Process}
89 * @throws IOException
90 * @throws InterruptedException
91 * @throws TimeoutException
92 */
93 public static Process startProcess(String name,
94 ProcessBuilder processBuilder,
95 long timeout,
96 TimeUnit unit)
97 throws IOException, InterruptedException, TimeoutException {
98 Process p = processBuilder.start();
99 StreamPumper stdout = new StreamPumper(p.getInputStream());
100 StreamPumper stderr = new StreamPumper(p.getErrorStream());
101
102 stdout.addPump(new LineForwarder(name, System.out));
103 stderr.addPump(new LineForwarder(name, System.err));
104 final Phaser phs = new Phaser(1);
105 Future<Void> stdoutTask = stdout.process();
106 Future<Void> stderrTask = stderr.process();
107
108 try {
109 if (timeout > -1) {
110 phs.awaitAdvanceInterruptibly(0, timeout, unit);
111 }
112 } catch (TimeoutException | InterruptedException e) {
113 System.err.println("Failed to start a process (thread dump follows)");
114 for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
115 printStack(s.getKey(), s.getValue());
116 }
117 stdoutTask.cancel(true);
118 stderrTask.cancel(true);
119 throw e;
120 }
121
122 return p;
123 }
124
125 /**
126 * Pumps stdout and stderr from running the process into a String.
127 *
128 * @param processBuilder
129 * ProcessHandler to run.
130 * @return Output from process.
131 * @throws IOException
132 * If an I/O error occurs.
202 */
203 public static String[] getPlatformSpecificVMArgs() {
204 String osName = System.getProperty("os.name");
205 String dataModel = System.getProperty("sun.arch.data.model");
206
207 if (osName.equals("SunOS") && dataModel.equals("64")) {
208 return new String[] { "-d64" };
209 }
210
211 return new String[] {};
212 }
213
214 /**
215 * Create ProcessBuilder using the java launcher from the jdk to be tested
216 * and with any platform specific arguments prepended
217 */
218 public static ProcessBuilder createJavaProcessBuilder(String... command)
219 throws Exception {
220 String javapath = JDKToolFinder.getJDKTool("java");
221
222 ArrayList<String> args = new ArrayList<>();
223 args.add(javapath);
224 Collections.addAll(args, getPlatformSpecificVMArgs());
225 Collections.addAll(args, command);
226
227 // Reporting
228 StringBuilder cmdLine = new StringBuilder();
229 for (String cmd : args)
230 cmdLine.append(cmd).append(' ');
231 System.out.println("Command line: [" + cmdLine.toString() + "]");
232
233 return new ProcessBuilder(args.toArray(new String[args.size()]));
234 }
235
236 private static void printStack(Thread t, StackTraceElement[] stack) {
237 System.out.println("\t" + t +
238 " stack: (length = " + stack.length + ")");
239 if (t != null) {
240 for (StackTraceElement stack1 : stack) {
241 System.out.println("\t" + stack1);
242 }
301 logMsg.append("--- ProcessLog ---" + nl);
302 logMsg.append("cmd: " + getCommandLine(pb) + nl);
303 logMsg.append("exitvalue: " + exitValue + nl);
304 logMsg.append("stderr: " + stderr + nl);
305 logMsg.append("stdout: " + stdout + nl);
306 return logMsg.toString();
307 }
308
309 /**
310 * @return The full command line for the ProcessBuilder.
311 */
312 public static String getCommandLine(ProcessBuilder pb) {
313 if (pb == null) {
314 return "null";
315 }
316 StringBuilder cmd = new StringBuilder();
317 for (String s : pb.command()) {
318 cmd.append(s).append(" ");
319 }
320 return cmd.toString().trim();
321 }
322 }
|
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.testlibrary;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.PrintStream;
29 import java.lang.management.ManagementFactory;
30 import java.lang.management.RuntimeMXBean;
31 import java.lang.reflect.Field;
32 import java.lang.reflect.Method;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.Map;
38 import java.util.concurrent.BrokenBarrierException;
39 import java.util.concurrent.CyclicBarrier;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.Future;
42 import java.util.concurrent.TimeUnit;
43 import java.util.concurrent.TimeoutException;
44
45 import sun.management.VMManagement;
46
47 public final class ProcessTools {
48 private static final class LineForwarder extends StreamPumper.LinePump {
49 private final PrintStream ps;
50 private final String prefix;
51 LineForwarder(String prefix, PrintStream os) {
52 this.ps = os;
53 this.prefix = prefix;
54 }
55 @Override
56 protected void processLine(String line) {
57 ps.println("[" + prefix + "] " + line);
58 }
59 }
60
61 private ProcessTools() {
62 }
63
64 /**
65 * <p>Starts a process from its builder.</p>
66 * <span>The default redirects of STDOUT and STDERR are started</span>
67 * @param name The process name
68 * @param processBuilder The process builder
69 * @return Returns the initialized process
70 * @throws IOException
71 * @throws BrokenBarrierException
72 */
73 public static Process startProcess(String name,
74 ProcessBuilder processBuilder)
75 throws IOException, BrokenBarrierException {
76 Process p = null;
77 try {
78 p = startProcess(name, processBuilder, -1, TimeUnit.NANOSECONDS);
79 } catch (InterruptedException e) {
80 // can't ever happen
81 } catch (TimeoutException e) {
82 // can't ever happen
83 }
84 return p;
85 }
86
87 /**
88 * <p>Starts a process from its builder.</p>
89 * <span>The default redirects of STDOUT and STDERR are started</span>
90 * @param name The process name
91 * @param processBuilder The process builder
92 * @param timeout The timeout for the warmup waiting
93 * @param unit The timeout {@linkplain TimeUnit}
94 * @return Returns the initialized {@linkplain Process}
95 * @throws IOException
96 * @throws InterruptedException
97 * @throws TimeoutException
98 * @throws BrokenBarrierException
99 */
100 public static Process startProcess(String name,
101 ProcessBuilder processBuilder,
102 long timeout,
103 TimeUnit unit)
104 throws IOException, InterruptedException, TimeoutException, BrokenBarrierException {
105 Process p = processBuilder.start();
106 StreamPumper stdout = new StreamPumper(p.getInputStream());
107 StreamPumper stderr = new StreamPumper(p.getErrorStream());
108
109 stdout.addPump(new LineForwarder(name, System.out));
110 stderr.addPump(new LineForwarder(name, System.err));
111 final CyclicBarrier cb = new CyclicBarrier(1);
112 Future<Void> stdoutTask = stdout.process();
113 Future<Void> stderrTask = stderr.process();
114
115 try {
116 if (timeout > -1) {
117 cb.await(timeout, unit);
118 }
119 } catch (TimeoutException e) {
120 System.err.println("Failed to start a process (thread dump follows)");
121 for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
122 printStack(s.getKey(), s.getValue());
123 }
124 stdoutTask.cancel(true);
125 stderrTask.cancel(true);
126 throw e;
127 } catch (InterruptedException e) {
128 System.err.println("Failed to start a process (thread dump follows)");
129 for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
130 printStack(s.getKey(), s.getValue());
131 }
132 stdoutTask.cancel(true);
133 stderrTask.cancel(true);
134 throw e;
135 } catch (BrokenBarrierException e) {
136 System.err.println("Failed to start a process (thread dump follows)");
137 for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
138 printStack(s.getKey(), s.getValue());
139 }
140 stdoutTask.cancel(true);
141 stderrTask.cancel(true);
142 throw e;
143 }
144
145 return p;
146 }
147
148 /**
149 * Pumps stdout and stderr from running the process into a String.
150 *
151 * @param processBuilder
152 * ProcessHandler to run.
153 * @return Output from process.
154 * @throws IOException
155 * If an I/O error occurs.
225 */
226 public static String[] getPlatformSpecificVMArgs() {
227 String osName = System.getProperty("os.name");
228 String dataModel = System.getProperty("sun.arch.data.model");
229
230 if (osName.equals("SunOS") && dataModel.equals("64")) {
231 return new String[] { "-d64" };
232 }
233
234 return new String[] {};
235 }
236
237 /**
238 * Create ProcessBuilder using the java launcher from the jdk to be tested
239 * and with any platform specific arguments prepended
240 */
241 public static ProcessBuilder createJavaProcessBuilder(String... command)
242 throws Exception {
243 String javapath = JDKToolFinder.getJDKTool("java");
244
245 ArrayList<String> args = new ArrayList<String>();
246 args.add(javapath);
247 Collections.addAll(args, getPlatformSpecificVMArgs());
248 Collections.addAll(args, command);
249
250 // Reporting
251 StringBuilder cmdLine = new StringBuilder();
252 for (String cmd : args)
253 cmdLine.append(cmd).append(' ');
254 System.out.println("Command line: [" + cmdLine.toString() + "]");
255
256 return new ProcessBuilder(args.toArray(new String[args.size()]));
257 }
258
259 private static void printStack(Thread t, StackTraceElement[] stack) {
260 System.out.println("\t" + t +
261 " stack: (length = " + stack.length + ")");
262 if (t != null) {
263 for (StackTraceElement stack1 : stack) {
264 System.out.println("\t" + stack1);
265 }
324 logMsg.append("--- ProcessLog ---" + nl);
325 logMsg.append("cmd: " + getCommandLine(pb) + nl);
326 logMsg.append("exitvalue: " + exitValue + nl);
327 logMsg.append("stderr: " + stderr + nl);
328 logMsg.append("stdout: " + stdout + nl);
329 return logMsg.toString();
330 }
331
332 /**
333 * @return The full command line for the ProcessBuilder.
334 */
335 public static String getCommandLine(ProcessBuilder pb) {
336 if (pb == null) {
337 return "null";
338 }
339 StringBuilder cmd = new StringBuilder();
340 for (String s : pb.command()) {
341 cmd.append(s).append(" ");
342 }
343 return cmd.toString().trim();
344 }
345
346 /**
347 * Executes a process, waits for it to finish, prints the process output
348 * to stdout, and returns the process output.
349 *
350 * The process will have exited before this method returns.
351 *
352 * @param cmds The command line to execute.
353 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
354 */
355 public static OutputAnalyzer executeCommand(String... cmds)
356 throws Throwable {
357 String cmdLine = "";
358 if (cmds.length > 0) {
359 StringBuilder cmdLineBuf = new StringBuilder(cmds[0]);
360 for (int a = 1; a < cmds.length; ++a) {
361 cmdLineBuf.append(" ");
362 cmdLineBuf.append(cmds[a]);
363 }
364 cmdLine = cmdLineBuf.toString();
365 }
366 System.out.println("Command line: [" + cmdLine + "]");
367 OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
368 System.out.println(analyzer.getOutput());
369 return analyzer;
370 }
371
372 /**
373 * Executes a process, waits for it to finish, prints the process output
374 * to stdout and returns the process output.
375 *
376 * The process will have exited before this method returns.
377 *
378 * @param pb The ProcessBuilder to execute.
379 * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
380 */
381 public static OutputAnalyzer executeCommand(ProcessBuilder pb)
382 throws Throwable {
383 Iterator<String> cmds = pb.command().iterator();
384 String cmdLine = "";
385 if (cmds.hasNext()) {
386 StringBuilder cmdLineBuf = new StringBuilder(cmds.next());
387 while (cmds.hasNext()) {
388 cmdLineBuf.append(" ");
389 cmdLineBuf.append(cmds.next());
390 }
391 cmdLine = cmdLineBuf.toString();
392 }
393 System.out.println("Command line: [" + cmdLine + "]");
394 OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
395 System.out.println(analyzer.getOutput());
396 return analyzer;
397 }
398 }
|