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