1 /* 2 * Copyright (c) 1998, 2006, 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 /** 25 * 26 */ 27 28 import java.io.*; 29 import java.rmi.*; 30 import java.rmi.activation.*; 31 import java.util.Properties; 32 33 /** 34 * Utility class that creates an instance of rmid with a policy 35 * file of name <code>TestParams.defaultPolicy</code>. 36 * 37 * Activation groups should run with the same security manager as the 38 * test. 39 */ 40 public class RMID extends JavaVM { 41 42 public static String MANAGER_OPTION="-Djava.security.manager="; 43 44 /** Test port for rmid */ 45 private final int port; 46 47 /** Initial log name */ 48 protected static String log = "log"; 49 /** rmid's logfile directory; currently must be "." */ 50 protected static String LOGDIR = "."; 51 52 private static void mesg(Object mesg) { 53 System.err.println("RMID: " + mesg.toString()); 54 } 55 56 /** make test options and arguments */ 57 private static String makeOptions(boolean debugExec) { 58 59 String options = " -Dsun.rmi.server.activation.debugExec=" + 60 debugExec; 61 // + 62 //" -Djava.compiler= "; 63 64 // if test params set, want to propagate them 65 if (!TestParams.testSrc.equals("")) { 66 options += " -Dtest.src=" + TestParams.testSrc + " "; 67 } 68 //if (!TestParams.testClasses.equals("")) { 69 // options += " -Dtest.classes=" + TestParams.testClasses + " "; 70 //} 71 options += " -Dtest.classes=" + TestParams.testClasses //; 72 + 73 " -Djava.rmi.server.logLevel=v "; 74 75 // + 76 // " -Djava.security.debug=all "; 77 78 return options; 79 } 80 81 private static String makeArgs(boolean includePortArg, int port) { 82 String propagateManager = null; 83 84 // rmid will run with a security manager set, but no policy 85 // file - it should not need one. 86 if (System.getSecurityManager() == null) { 87 propagateManager = MANAGER_OPTION + 88 TestParams.defaultSecurityManager; 89 } else { 90 propagateManager = MANAGER_OPTION + 91 System.getSecurityManager().getClass().getName(); 92 } 93 94 // getAbsolutePath requires permission to read user.dir 95 String args = 96 " -log " + (new File(LOGDIR, log)).getAbsolutePath(); 97 98 if (includePortArg) { 99 args += " -port " + port; 100 } 101 102 // + 103 // " -C-Djava.compiler= "; 104 105 // if test params set, want to propagate them 106 if (!TestParams.testSrc.equals("")) { 107 args += " -C-Dtest.src=" + TestParams.testSrc; 108 } 109 if (!TestParams.testClasses.equals("")) { 110 args += " -C-Dtest.classes=" + TestParams.testClasses; 111 } 112 args += " " + getCodeCoverageArgs(); 113 return args; 114 } 115 116 /** 117 * Routine that creates an rmid that will run with or without a 118 * policy file. 119 */ 120 public static RMID createRMID() { 121 return createRMID(System.out, System.err, true); 122 } 123 124 public static RMID createRMID(boolean debugExec) { 125 return createRMID(System.out, System.err, debugExec); 126 } 127 128 public static RMID createRMID(OutputStream out, OutputStream err) { 129 return createRMID(out, err, true); 130 } 131 132 public static RMID createRMID(OutputStream out, OutputStream err, 133 boolean debugExec) 134 { 135 return createRMID(out, err, debugExec, true, 136 TestLibrary.RMID_PORT); 137 } 138 139 public static RMID createRMID(OutputStream out, OutputStream err, 140 boolean debugExec, boolean includePortArg, 141 int port) 142 { 143 String options = makeOptions(debugExec); 144 String args = makeArgs(includePortArg, port); 145 RMID rmid = new RMID("sun.rmi.server.Activation", options, args, 146 out, err, port); 147 rmid.setPolicyFile(TestParams.defaultRmidPolicy); 148 149 return rmid; 150 } 151 152 153 /** 154 * Test RMID should be created with the createRMID method. 155 */ 156 protected RMID(String classname, String options, String args, 157 OutputStream out, OutputStream err, int port) 158 { 159 super(classname, options, args, out, err); 160 this.port = port; 161 } 162 163 public static void removeLog() { 164 /* 165 * Remove previous log file directory before 166 * starting up rmid. 167 */ 168 File f = new File(LOGDIR, log); 169 170 if (f.exists()) { 171 mesg("removing rmid's old log file..."); 172 String[] files = f.list(); 173 174 if (files != null) { 175 for (int i=0; i<files.length; i++) { 176 (new File(f, files[i])).delete(); 177 } 178 } 179 180 if (f.delete() != true) { 181 mesg("\t" + " unable to delete old log file."); 182 } 183 } 184 } 185 186 /** 187 * This method is used for adding arguments to rmid (not its VM) 188 * for passing as VM options to its child group VMs. 189 * Returns the extra command line arguments required 190 * to turn on jcov code coverage analysis for rmid child VMs. 191 */ 192 protected static String getCodeCoverageArgs() { 193 return TestLibrary.getExtraProperty("rmid.jcov.args",""); 194 } 195 196 public void start() throws IOException { 197 start(10000); 198 } 199 200 public void slowStart() throws IOException { 201 start(60000); 202 } 203 204 public void start(long waitTime) throws IOException { 205 206 if (getVM() != null) return; 207 208 // if rmid is already running, then the test will fail with 209 // a well recognized exception (port already in use...). 210 211 mesg("starting rmid..."); 212 super.start(); 213 214 int slopFactor = 1; 215 try { 216 slopFactor = Integer.valueOf( 217 TestLibrary.getExtraProperty("jcov.sleep.multiplier","1")); 218 } catch (NumberFormatException ignore) {} 219 waitTime = waitTime * slopFactor; 220 221 // We check several times (as many as provides passed waitTime) to 222 // see if Rmid is currently running. Waiting steps last 100 msecs. 223 final long rmidStartSleepTime = 100; 224 do { 225 // Sleeping for another rmidStartSleepTime time slice. 226 try { 227 Thread.sleep(Math.min(waitTime, rmidStartSleepTime)); 228 } catch (InterruptedException ie) { 229 Thread.currentThread().interrupt(); 230 mesg("Thread interrupted while checking for start of Activation System. Giving up check."); 231 mesg("Activation System state unknown"); 232 return; 233 } 234 waitTime -= rmidStartSleepTime; 235 236 // Checking if rmid is present 237 if (ActivationLibrary.rmidRunning(port)) { 238 mesg("finished starting rmid."); 239 return; 240 } 241 else { 242 mesg("rmid still not started"); 243 } 244 245 } while (waitTime > 0); 246 TestLibrary.bomb("start rmid failed... giving up", null); 247 } 248 249 public void restart() throws IOException { 250 destroy(); 251 start(); 252 } 253 254 /** 255 * Ask rmid to shutdown gracefully using a remote method call. 256 * catch any errors that might occur from rmid not being present 257 * at time of shutdown invocation. 258 * 259 * Shutdown does not nullify possible references to the rmid 260 * process object (destroy does though). 261 */ 262 public static void shutdown() { 263 shutdown(TestLibrary.RMID_PORT); 264 } 265 266 public static void shutdown(int port) { 267 268 try { 269 ActivationSystem system = null; 270 271 try { 272 mesg("getting a reference to the activation system"); 273 system = (ActivationSystem) Naming.lookup("//:" + 274 port + 275 "/java.rmi.activation.ActivationSystem"); 276 mesg("obtained a reference to the activation system"); 277 } catch (RemoteException re) { 278 mesg("could not contact registry while trying to shutdown activation system"); 279 } catch (java.net.MalformedURLException mue) { 280 } 281 282 if (system == null) { 283 TestLibrary.bomb("reference to the activation system was null"); 284 } 285 system.shutdown(); 286 287 } catch (RemoteException re) { 288 mesg("shutting down the activation daemon failed"); 289 } catch (Exception e) { 290 mesg("caught exception trying to shutdown rmid"); 291 mesg(e.getMessage()); 292 e.printStackTrace(); 293 } 294 295 mesg("testlibrary finished shutting down rmid"); 296 } 297 298 /** 299 * Ask rmid to shutdown gracefully but then destroy the rmid 300 * process if it does not exit by itself. This method only works 301 * if rmid is a child process of the current VM. 302 */ 303 public void destroy() { 304 305 // attempt graceful shutdown of the activation system on 306 // TestLibrary.RMID_PORT 307 shutdown(port); 308 309 if (vm != null) { 310 try { 311 /* Waiting for distant RMID process to shutdown. 312 * Waiting is bounded at a hardcoded max of 60 secs (1 min). 313 * Waiting by steps of 200 msecs, thus at most 300 such attempts 314 * for termination of distant RMID process. If process is not 315 * known to be terminated properly after that time, 316 * we give up for a gracefull termination, and thus go for 317 * forcibly destroying the process. 318 */ 319 boolean vmEnded = false; 320 int waitingTrials = 0; 321 final int maxTrials = 300; 322 final long vmProcessEndWaitInterval = 200; 323 int vmExitValue; 324 do { 325 try { 326 Thread.sleep(vmProcessEndWaitInterval); 327 waitingTrials++; 328 vmExitValue = vm.exitValue(); 329 mesg("rmid exited on shutdown request"); 330 vmEnded = true; 331 } catch (IllegalThreadStateException illegal) { 332 mesg("RMID's process still not terminated after more than " + 333 (waitingTrials * vmProcessEndWaitInterval) + " milliseconds"); 334 } 335 } 336 while (!vmEnded && 337 (waitingTrials < maxTrials)); 338 339 if (waitingTrials >= maxTrials) { 340 mesg("RMID's process still not terminated after more than " + 341 (waitingTrials * vmProcessEndWaitInterval) + " milliseconds." + 342 "Givinp up gracefull termination..."); 343 mesg("destroying RMID's process using Process.destroy()"); 344 super.destroy(); 345 } 346 347 } catch (InterruptedException ie) { 348 Thread.currentThread().interrupt(); 349 mesg("Thread interrupted while checking for termination of distant rmid vm. Giving up check."); 350 } catch (Exception e) { 351 mesg("caught unexpected exception trying to destroy rmid: " + 352 e.getMessage()); 353 e.printStackTrace(); 354 } 355 356 // rmid will not restart if its process is not null 357 vm = null; 358 } 359 } 360 }