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.lang.management.ManagementFactory;
  29 import java.lang.management.RuntimeMXBean;
  30 import java.lang.reflect.Field;
  31 import java.lang.reflect.Method;
  32 import java.util.ArrayList;
  33 import java.util.Collections;
  34 
  35 import sun.management.VMManagement;
  36 
  37 public final class ProcessTools {
  38 
  39     private ProcessTools() {
  40     }
  41 
  42     /**
  43      * Pumps stdout and stderr from running the process into a String.
  44      *
  45      * @param processHandler
  46      *            ProcessHandler to run.
  47      * @return Output from process.
  48      * @throws IOException
  49      *             If an I/O error occurs.
  50      */
  51     public static OutputBuffer getOutput(ProcessBuilder processBuilder)
  52             throws IOException {
  53         return getOutput(processBuilder.start());
  54     }
  55 
  56     /**
  57      * Pumps stdout and stderr the running process into a String.
  58      *
  59      * @param process
  60      *            Process to pump.
  61      * @return Output from process.
  62      * @throws IOException
  63      *             If an I/O error occurs.
  64      */
  65     public static OutputBuffer getOutput(Process process) throws IOException {
  66         ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
  67         ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
  68         StreamPumper outPumper = new StreamPumper(process.getInputStream(),
  69                 stdoutBuffer);
  70         StreamPumper errPumper = new StreamPumper(process.getErrorStream(),
  71                 stderrBuffer);
  72         Thread outPumperThread = new Thread(outPumper);
  73         Thread errPumperThread = new Thread(errPumper);
  74 
  75         outPumperThread.setDaemon(true);
  76         errPumperThread.setDaemon(true);
  77 
  78         outPumperThread.start();
  79         errPumperThread.start();
  80 
  81         try {
  82             process.waitFor();
  83             outPumperThread.join();
  84             errPumperThread.join();
  85         } catch (InterruptedException e) {
  86             Thread.currentThread().interrupt();
  87             return null;
  88         }
  89 
  90         return new OutputBuffer(stdoutBuffer.toString(),
  91                 stderrBuffer.toString());
  92     }
  93 
  94     /**
  95      * Get the process id of the current running Java process
  96      *
  97      * @return Process id
  98      */
  99     public static int getProcessId() throws Exception {
 100 
 101         // Get the current process id using a reflection hack
 102         RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
 103         Field jvm = runtime.getClass().getDeclaredField("jvm");
 104 
 105         jvm.setAccessible(true);
 106         VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
 107 
 108         Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
 109 
 110         pid_method.setAccessible(true);
 111 
 112         int pid = (Integer) pid_method.invoke(mgmt);
 113 
 114         return pid;
 115     }
 116 
 117     /**
 118      * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
 119      *
 120      * @return String[] with platform specific arguments, empty if there are
 121      *         none
 122      */
 123     public static String[] getPlatformSpecificVMArgs() {
 124         String osName = System.getProperty("os.name");
 125         String dataModel = System.getProperty("sun.arch.data.model");
 126 
 127         if (osName.equals("SunOS") && dataModel.equals("64")) {
 128             return new String[] { "-d64" };
 129         }
 130 
 131         return new String[] {};
 132     }
 133 
 134     /**
 135      * Create ProcessBuilder using the java launcher from the jdk to be tested
 136      * and with any platform specific arguments prepended
 137      */
 138     public static ProcessBuilder createJavaProcessBuilder(String... command)
 139             throws Exception {
 140         String javapath = JdkFinder.getJavaLauncher(false);
 141 
 142         ArrayList<String> args = new ArrayList<>();
 143         args.add(javapath);
 144         Collections.addAll(args, getPlatformSpecificVMArgs());
 145         Collections.addAll(args, command);
 146 
 147         return new ProcessBuilder(args.toArray(new String[args.size()]));
 148 
 149     }
 150 
 151 }