34 * RMI regression test utility class that uses Runtime.exec to spawn a |
34 * RMI regression test utility class that uses Runtime.exec to spawn a |
35 * java process that will run a named java class. |
35 * java process that will run a named java class. |
36 */ |
36 */ |
37 public class JavaVM { |
37 public class JavaVM { |
38 |
38 |
39 // need to |
|
40 protected Process vm = null; |
39 protected Process vm = null; |
41 |
40 |
42 private String classname = ""; |
41 private String classname = ""; |
43 private String args = ""; |
42 private String args = ""; |
44 private String options = ""; |
43 private String options = ""; |
45 private OutputStream outputStream = System.out; |
44 private OutputStream outputStream = System.out; |
46 private OutputStream errorStream = System.err; |
45 private OutputStream errorStream = System.err; |
47 private String policyFileName = null; |
46 private String policyFileName = null; |
48 |
47 |
|
48 // This is used to shorten waiting time at startup. |
|
49 private volatile boolean started = false; |
|
50 private boolean forcesOutput = true; // default behavior |
|
51 |
49 private static void mesg(Object mesg) { |
52 private static void mesg(Object mesg) { |
50 System.err.println("JAVAVM: " + mesg.toString()); |
53 System.err.println("JAVAVM: " + mesg.toString()); |
51 } |
54 } |
52 |
55 |
53 /** string name of the program execd by JavaVM */ |
56 /** string name of the program execd by JavaVM */ |
77 this(classname, options, args); |
80 this(classname, options, args); |
78 this.outputStream = out; |
81 this.outputStream = out; |
79 this.errorStream = err; |
82 this.errorStream = err; |
80 } |
83 } |
81 |
84 |
|
85 /* This constructor will instantiate a JavaVM object for which caller |
|
86 * can ask for forcing initial version output on child vm process |
|
87 * (if forcesVersionOutput is true), or letting the started vm behave freely |
|
88 * (when forcesVersionOutput is false). |
|
89 */ |
|
90 public JavaVM(String classname, |
|
91 String options, String args, |
|
92 OutputStream out, OutputStream err, |
|
93 boolean forcesVersionOutput) { |
|
94 this(classname, options, args, out, err); |
|
95 this.forcesOutput = forcesVersionOutput; |
|
96 } |
|
97 |
|
98 |
|
99 public void setStarted() { |
|
100 started = true; |
|
101 } |
|
102 |
|
103 // Prepends passed opts array to current options |
82 public void addOptions(String[] opts) { |
104 public void addOptions(String[] opts) { |
83 String newOpts = ""; |
105 String newOpts = ""; |
84 for (int i = 0 ; i < opts.length ; i ++) { |
106 for (int i = 0 ; i < opts.length ; i ++) { |
85 newOpts += " " + opts[i]; |
107 newOpts += " " + opts[i]; |
86 } |
108 } |
87 newOpts += " "; |
109 newOpts += " "; |
88 options = newOpts + options; |
110 options = newOpts + options; |
89 } |
111 } |
|
112 |
|
113 // Prepends passed arguments array to current args |
90 public void addArguments(String[] arguments) { |
114 public void addArguments(String[] arguments) { |
91 String newArgs = ""; |
115 String newArgs = ""; |
92 for (int i = 0 ; i < arguments.length ; i ++) { |
116 for (int i = 0 ; i < arguments.length ; i ++) { |
93 newArgs += " " + arguments[i]; |
117 newArgs += " " + arguments[i]; |
94 } |
118 } |
125 addOptions(new String[] { option }); |
149 addOptions(new String[] { option }); |
126 } |
150 } |
127 |
151 |
128 addOptions(new String[] { getCodeCoverageOptions() }); |
152 addOptions(new String[] { getCodeCoverageOptions() }); |
129 |
153 |
|
154 /* |
|
155 * If forcesOutput is true : |
|
156 * We force the new starting vm to output something so that we can know |
|
157 * when it is effectively started by redirecting standard output through |
|
158 * the next StreamPipe call (the vm is considered started when a first |
|
159 * output has been streamed out). |
|
160 * We do this by prepnding a "-showversion" option in the command line. |
|
161 */ |
|
162 if (forcesOutput) { |
|
163 addOptions(new String[] {"-showversion"}); |
|
164 } |
|
165 |
130 StringTokenizer optionsTokenizer = new StringTokenizer(options); |
166 StringTokenizer optionsTokenizer = new StringTokenizer(options); |
131 StringTokenizer argsTokenizer = new StringTokenizer(args); |
167 StringTokenizer argsTokenizer = new StringTokenizer(args); |
132 int optionsCount = optionsTokenizer.countTokens(); |
168 int optionsCount = optionsTokenizer.countTokens(); |
133 int argsCount = argsTokenizer.countTokens(); |
169 int argsCount = argsTokenizer.countTokens(); |
134 |
170 |
148 System.err.println(""); |
184 System.err.println(""); |
149 |
185 |
150 vm = Runtime.getRuntime().exec(javaCommand); |
186 vm = Runtime.getRuntime().exec(javaCommand); |
151 |
187 |
152 /* output from the execed process may optionally be captured. */ |
188 /* output from the execed process may optionally be captured. */ |
153 StreamPipe.plugTogether(vm.getInputStream(), this.outputStream); |
189 StreamPipe.plugTogether(this, vm.getInputStream(), this.outputStream); |
154 StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream); |
190 StreamPipe.plugTogether(this, vm.getErrorStream(), this.errorStream); |
155 |
191 |
156 try { |
192 try { |
157 Thread.sleep(2000); |
193 if (forcesOutput) { |
158 } catch (Exception ignore) { |
194 // Wait distant vm to start, by using waiting time slices of 100 ms. |
159 } |
195 // Wait at most for 2secs, after it considers the vm to be started. |
160 |
196 final long vmStartSleepTime = 100; |
161 mesg("finished starting vm."); |
197 final int maxTrials = 20; |
|
198 int numTrials = 0; |
|
199 while (!started && numTrials < maxTrials) { |
|
200 numTrials++; |
|
201 Thread.sleep(vmStartSleepTime); |
|
202 } |
|
203 |
|
204 // Outputs running status of distant vm |
|
205 String message = |
|
206 "after " + (numTrials * vmStartSleepTime) + " milliseconds"; |
|
207 if (started) { |
|
208 mesg("distant vm process running, " + message); |
|
209 } |
|
210 else { |
|
211 mesg("unknown running status of distant vm process, " + message); |
|
212 } |
|
213 } |
|
214 else { |
|
215 // Since we have no way to know if the distant vm is started, |
|
216 // we just consider the vm to be started after a 2secs waiting time. |
|
217 Thread.sleep(2000); |
|
218 mesg("distant vm considered to be started after a waiting time of 2 secs"); |
|
219 } |
|
220 } catch (InterruptedException e) { |
|
221 Thread.currentThread().interrupt(); |
|
222 mesg("Thread interrupted while checking if distant vm is started. Giving up check."); |
|
223 mesg("Distant vm state unknown"); |
|
224 return; |
|
225 } |
162 } |
226 } |
163 |
227 |
164 public void destroy() { |
228 public void destroy() { |
165 if (vm != null) { |
229 if (vm != null) { |
166 vm.destroy(); |
230 vm.destroy(); |