1 /* 2 * Copyright (c) 1998, 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 import java.io.File; 25 import java.io.IOException; 26 import java.io.OutputStream; 27 import java.util.Arrays; 28 import java.util.StringTokenizer; 29 30 /** 31 * RMI regression test utility class that uses Runtime.exec to spawn a 32 * java process that will run a named java class. 33 */ 34 public class JavaVM { 35 36 protected Process vm = null; 37 38 private String classname = ""; 39 private String args = ""; 40 private String options = ""; 41 private OutputStream outputStream = System.out; 42 private OutputStream errorStream = System.err; 43 private String policyFileName = null; 44 private StreamPipe outPipe; 45 private StreamPipe errPipe; 46 47 private static void mesg(Object mesg) { 48 System.err.println("JAVAVM: " + mesg.toString()); 49 } 50 51 /** string name of the program execd by JavaVM */ 52 private static String javaProgram = "java"; 53 54 static { 55 try { 56 javaProgram = TestLibrary.getProperty("java.home", "") + 57 File.separator + "bin" + File.separator + javaProgram; 58 } catch (SecurityException se) { 59 } 60 } 61 62 public JavaVM(String classname, 63 String options, String args) { 64 this.classname = classname; 65 this.options = options; 66 this.args = args; 67 } 68 69 public JavaVM(String classname, 70 String options, String args, 71 OutputStream out, OutputStream err) { 72 this(classname, options, args); 73 this.outputStream = out; 74 this.errorStream = err; 75 } 76 77 // Prepends passed opts array to current options 78 public void addOptions(String[] opts) { 79 String newOpts = ""; 80 for (int i = 0 ; i < opts.length ; i ++) { 81 newOpts += " " + opts[i]; 82 } 83 newOpts += " "; 84 options = newOpts + options; 85 } 86 87 // Prepends passed arguments array to current args 88 public void addArguments(String[] arguments) { 89 String newArgs = ""; 90 for (int i = 0 ; i < arguments.length ; i ++) { 91 newArgs += " " + arguments[i]; 92 } 93 newArgs += " "; 94 args = newArgs + args; 95 } 96 97 public void setPolicyFile(String policyFileName) { 98 this.policyFileName = policyFileName; 99 } 100 101 /** 102 * This method is used for setting VM options on spawned VMs. 103 * It returns the extra command line options required 104 * to turn on jcov code coverage analysis. 105 */ 106 protected static String getCodeCoverageOptions() { 107 return TestLibrary.getExtraProperty("jcov.options",""); 108 } 109 110 /** 111 * Exec the VM as specified in this object's constructor. 112 */ 113 public void start() throws IOException { 114 115 if (vm != null) 116 throw new IllegalStateException("JavaVM already started"); 117 118 /* 119 * If specified, add option for policy file 120 */ 121 if (policyFileName != null) { 122 String option = "-Djava.security.policy=" + policyFileName; 123 addOptions(new String[] { option }); 124 } 125 126 addOptions(new String[] { getCodeCoverageOptions() }); 127 128 StringTokenizer optionsTokenizer = new StringTokenizer(options); 129 StringTokenizer argsTokenizer = new StringTokenizer(args); 130 int optionsCount = optionsTokenizer.countTokens(); 131 int argsCount = argsTokenizer.countTokens(); 132 133 String javaCommand[] = new String[optionsCount + argsCount + 2]; 134 int count = 0; 135 136 javaCommand[count++] = JavaVM.javaProgram; 137 while (optionsTokenizer.hasMoreTokens()) { 138 javaCommand[count++] = optionsTokenizer.nextToken(); 139 } 140 javaCommand[count++] = classname; 141 while (argsTokenizer.hasMoreTokens()) { 142 javaCommand[count++] = argsTokenizer.nextToken(); 143 } 144 145 mesg("command = " + Arrays.asList(javaCommand).toString()); 146 147 vm = Runtime.getRuntime().exec(javaCommand); 148 149 /* output from the execed process may optionally be captured. */ 150 outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream); 151 errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream); 152 } 153 154 public void destroy() { 155 if (vm != null) { 156 vm.destroy(); 157 } 158 vm = null; 159 } 160 161 /** 162 * Waits for the subprocess to exit, joins the pipe threads to ensure that 163 * all output is collected, and returns its exit status. 164 */ 165 public int waitFor() throws InterruptedException { 166 if (vm == null) 167 throw new IllegalStateException("can't wait for JavaVM that isn't running"); 168 169 int status = vm.waitFor(); 170 outPipe.join(); 171 errPipe.join(); 172 return status; 173 } 174 175 /** 176 * Starts the subprocess, waits for it to exit, and returns its exit status. 177 */ 178 public int execute() throws IOException, InterruptedException { 179 start(); 180 return waitFor(); 181 } 182 }