1 /* 2 * Copyright (c) 1998, 2012, 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.File; 29 import java.rmi.Naming; 30 import java.rmi.NoSuchObjectException; 31 import java.rmi.NotBoundException; 32 import java.rmi.Remote; 33 import java.rmi.activation.Activatable; 34 import java.rmi.activation.ActivationID; 35 import java.rmi.activation.ActivationSystem; 36 import java.rmi.registry.LocateRegistry; 37 38 /** 39 * Class of test utility/library methods related to Activatable 40 * objects. 41 */ 42 public class ActivationLibrary { 43 /** time safeDestroy should wait before failing on shutdown rmid */ 44 private static final int SAFE_WAIT_TIME; 45 static { 46 int slopFactor = 1; 47 try { 48 slopFactor = Integer.valueOf( 49 TestLibrary.getExtraProperty("jcov.sleep.multiplier","1")); 50 } catch (NumberFormatException ignore) {} 51 SAFE_WAIT_TIME = 60000 * slopFactor; 52 } 53 54 private static final String SYSTEM_NAME = 55 ActivationSystem.class.getName(); 56 57 private static void mesg(Object mesg) { 58 System.err.println("ACTIVATION_LIBRARY: " + mesg.toString()); 59 } 60 61 /** 62 * Deactivate an activated Activatable 63 */ 64 public static void deactivate(Remote remote, 65 ActivationID id) { 66 // We do as much as 50 deactivation trials, each separated by 67 // at least 100 milliseconds sleep time (max sleep time of 5 secs). 68 final long deactivateSleepTime = 100; 69 long stopTime = System.currentTimeMillis() + deactivateSleepTime * 50; 70 while (System.currentTimeMillis() < stopTime) { 71 try { 72 if (Activatable.inactive(id) == true) { 73 mesg("inactive successful"); 74 return; 75 } else { 76 mesg("inactive trial failed. Sleeping " + 77 deactivateSleepTime + 78 " milliseconds before next trial"); 79 Thread.sleep(deactivateSleepTime); 80 } 81 } catch (InterruptedException e) { 82 Thread.currentThread().interrupt(); 83 mesg("Thread interrupted while trying to deactivate activatable. Exiting deactivation"); 84 return; 85 } catch (Exception e) { 86 try { 87 // forcibly unexport the object 88 mesg("Unexpected exception. Have to forcibly unexport the object." + 89 " Exception was :"); 90 e.printStackTrace(); 91 Activatable.unexportObject(remote, true); 92 } catch (NoSuchObjectException ex) { 93 } 94 return; 95 } 96 } 97 98 mesg("unable to inactivate after several attempts"); 99 mesg("unexporting object forcibly instead"); 100 101 try { 102 Activatable.unexportObject(remote, true); 103 } catch (NoSuchObjectException e) { 104 } 105 } 106 107 /** 108 * Simple method call to see if rmid is running. 109 * 110 * This method intentionally avoids performing a lookup on the 111 * activation system. 112 */ 113 public static boolean rmidRunning(int port) { 114 int allowedNotReady = 50; 115 int connectionRefusedExceptions = 0; 116 117 /* We wait as much as a total of 7.5 secs trying to see Rmid running. 118 * We do this by pausing steps of 100 milliseconds (so up to 75 steps), 119 * right after trying to lookup and find RMID running in the other vm. 120 */ 121 final long rmidWaitingStepTime = 100; 122 for (int i = 0; i <= 74; i++) { 123 124 try { 125 LocateRegistry.getRegistry(port).lookup(SYSTEM_NAME); 126 mesg("Activation System available after " + 127 (i * rmidWaitingStepTime) + " milliseconds"); 128 return true; 129 130 } catch (java.rmi.ConnectException e) { 131 mesg("Remote connection refused after " + 132 (i * rmidWaitingStepTime) + " milliseconds"); 133 134 // ignore connect exceptions until we decide rmid is not up 135 if ((connectionRefusedExceptions ++) >= allowedNotReady) { 136 return false; 137 } 138 139 } catch (java.rmi.NoSuchObjectException nsoe) { 140 /* Activation System still unavailable. 141 * Ignore this since we are just waiting for its availibility. 142 * Just signal unavailibility. 143 */ 144 mesg("Activation System still unavailable after more than " + 145 (i * rmidWaitingStepTime) + " milliseconds"); 146 147 } catch (NotBoundException e) { 148 return false; 149 150 } catch (Exception e) { 151 /* print out other types of exceptions as an FYI. 152 * test should not fail as rmid is likely to be in an 153 * undetermined state at this point. 154 */ 155 mesg("caught an exception trying to" + 156 " start rmid, last exception was: " + 157 e.getMessage()); 158 e.printStackTrace(); 159 } 160 161 // Waiting for another 100 milliseconds. 162 try { 163 Thread.sleep(100); 164 } catch (InterruptedException e) { 165 Thread.currentThread().interrupt(); 166 mesg("Thread interrupted while checking if Activation System is running. Exiting check"); 167 return false; 168 } 169 } 170 return false; 171 } 172 173 /** cleanup after rmid */ 174 public static void rmidCleanup(RMID rmid) { 175 if (rmid != null) { 176 if (!ActivationLibrary.safeDestroy(rmid, SAFE_WAIT_TIME)) { 177 TestLibrary.bomb("rmid not destroyed in: " + 178 SAFE_WAIT_TIME + 179 " milliseconds"); 180 } 181 } 182 RMID.removeLog(); 183 } 184 185 /** 186 * Invoke shutdown on rmid in a way that will not cause a test 187 * to hang. 188 * 189 * @return whether or not shutdown completed succesfully in the 190 * timeAllowed 191 */ 192 private static boolean safeDestroy(RMID rmid, long timeAllowed) { 193 DestroyThread destroyThread = new DestroyThread(rmid); 194 destroyThread.start(); 195 196 try { 197 destroyThread.join(timeAllowed); 198 } catch (InterruptedException ie) { 199 Thread.currentThread().interrupt(); 200 } 201 202 return destroyThread.shutdownSucceeded(); 203 } 204 205 /** 206 * Thread class to handle the destruction of rmid 207 */ 208 private static class DestroyThread extends Thread { 209 private final RMID rmid; 210 private final int port; 211 private boolean succeeded = false; 212 213 DestroyThread(RMID rmid) { 214 this.rmid = rmid; 215 this.port = rmid.getPort(); 216 this.setDaemon(true); 217 } 218 219 public void run() { 220 if (ActivationLibrary.rmidRunning(port)) { 221 rmid.destroy(); 222 synchronized (this) { 223 // flag that the test was able to shutdown rmid 224 succeeded = true; 225 } 226 mesg("finished destroying rmid"); 227 } else { 228 mesg("tried to shutdown when rmid was not running"); 229 } 230 } 231 232 public synchronized boolean shutdownSucceeded() { 233 return succeeded; 234 } 235 } 236 }