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