1 /* 2 * Copyright (c) 2002, 2014, 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 /* @test 25 * @bug 4526514 26 * @summary rmid does not handle group restart for latecomer objects 27 * @author Ann Wollrath 28 * 29 * @library ../../../testlibrary 30 * @build TestLibrary RMID ActivationLibrary 31 * RestartLatecomer RestartLatecomer_Stub 32 * @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer 33 */ 34 35 import java.io.*; 36 import java.rmi.*; 37 import java.rmi.activation.*; 38 import java.rmi.server.*; 39 import java.rmi.registry.*; 40 import java.util.Vector; 41 import java.util.Properties; 42 43 public class RestartLatecomer 44 implements ActivateMe, Runnable 45 { 46 47 private ActivationID id; 48 private static Object lock = new Object(); 49 private Vector responders = new Vector(); 50 51 private static final String RESTARTABLE = "restartable"; 52 private static final String ACTIVATABLE = "activatable"; 53 54 55 public RestartLatecomer(ActivationID id, MarshalledObject mobj) 56 throws ActivationException, RemoteException 57 { 58 this.id = id; 59 Activatable.exportObject(this, id, 0); 60 ActivateMe obj; 61 String responder; 62 try { 63 Object[] stuff = (Object[]) mobj.get(); 64 responder = (String) stuff[0]; 65 System.err.println(responder + " service started"); 66 obj = (ActivateMe) stuff[1]; 67 } catch (Exception e) { 68 System.err.println("unable to obtain stub from marshalled object"); 69 return; 70 } 71 72 /* 73 * Call back object in the test VM to notify it that 74 * this object has been activated or restarted. 75 */ 76 obj.callback(responder); 77 } 78 79 public RestartLatecomer() throws RemoteException { 80 UnicastRemoteObject.exportObject(this, 0); 81 } 82 83 private void waitFor(String responder) throws Exception { 84 synchronized (lock) { 85 for (int i = 0; i < 15; i++) { 86 if (responders.contains(responder) != true) { 87 lock.wait(5000); 88 if (responders.contains(responder) == true) { 89 return; 90 } 91 } else { 92 return; 93 } 94 } 95 } 96 97 throw new RuntimeException( 98 "TEST FAILED: service not restarted by timeout"); 99 } 100 101 private void clearResponders() { 102 synchronized (lock) { 103 responders.clear(); 104 } 105 } 106 107 108 /** 109 * Notifies the receiver that the object denoted by "responder" 110 * has activated or restarted. 111 */ 112 public void callback(String responder) { 113 System.err.println( 114 "RestartLatecomer: received callback from " + responder); 115 /* 116 * Notify waiter that callback has been received and 117 * test can proceed. 118 */ 119 synchronized (lock) { 120 responders.add(responder); 121 lock.notifyAll(); 122 } 123 } 124 125 /** 126 * Pings object (to activate it). 127 */ 128 public void ping() { 129 System.err.println("RestartLatecomer: recevied ping"); 130 } 131 132 /** 133 * Spawns a thread to deactivate the object. 134 */ 135 public void shutdown() { 136 System.err.println("RestartLatecomer: received shutdown request"); 137 (new Thread(this,"RestartLatecomer")).start(); 138 } 139 140 public ActivationID getID() { 141 return id; 142 } 143 144 /** 145 * Thread to deactivate object. First attempts to make object 146 * inactive (via the inactive method). If that fails (the 147 * object may still have pending/executing calls), then 148 * unexport the object forcibly. 149 */ 150 public void run() { 151 System.exit(0); 152 } 153 154 public static void main(String[] args) { 155 156 System.out.println("\nRegression test for bug 4526514\n"); 157 158 TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager"); 159 160 RMID rmid = null; 161 RestartLatecomer callbackObj = null; 162 163 try { 164 RMID.removeLog(); 165 rmid = RMID.createRMID(); 166 rmid.start(); 167 168 /* Cause activation groups to have a security policy that will 169 * allow security managers to be downloaded and installed 170 */ 171 Properties p = new Properties(); 172 // this test must always set policies/managers in its 173 // activation groups 174 p.put("java.security.policy", 175 TestParams.defaultGroupPolicy); 176 p.put("java.security.manager", 177 TestParams.defaultSecurityManager); 178 179 /* 180 * Create unicast object to be contacted when service is activated. 181 */ 182 callbackObj = new RestartLatecomer(); 183 /* 184 * Create and register descriptors for a restartable and 185 * non-restartable service (respectively) in a group other than 186 * this VM's group. 187 */ 188 System.err.println("Creating descriptors"); 189 190 Object[] stuff = new Object[] { RESTARTABLE, callbackObj }; 191 MarshalledObject restartMobj = new MarshalledObject(stuff); 192 ActivationGroupDesc groupDesc = 193 new ActivationGroupDesc(p, null); 194 195 stuff[0] = ACTIVATABLE; 196 MarshalledObject activateMobj = new MarshalledObject(stuff); 197 ActivationGroupID groupID = 198 ActivationGroup.getSystem().registerGroup(groupDesc); 199 200 ActivationDesc activatableDesc = 201 new ActivationDesc(groupID, "RestartLatecomer", null, 202 activateMobj, false); 203 ActivationDesc restartableDesc = 204 new ActivationDesc(groupID, "RestartLatecomer", null, 205 restartMobj, true); 206 207 208 System.err.println("Register activatable object's descriptor"); 209 ActivateMe activatableObj = 210 (ActivateMe) Activatable.register(activatableDesc); 211 212 System.err.println("Activate object (starts group VM)"); 213 activatableObj.ping(); 214 215 callbackObj.waitFor(ACTIVATABLE); 216 callbackObj.clearResponders(); 217 System.err.println("Callback from activatable object received"); 218 219 System.err.println("Register restartable object's descriptor"); 220 ActivateMe restartableObj = 221 (ActivateMe) Activatable.register(restartableDesc); 222 223 System.err.println("Shutdown object (exits group VM)"); 224 try { 225 activatableObj.shutdown(); 226 } catch (RemoteException ignore) { 227 /* 228 * Since the shutdown method spawns a thread to call 229 * System.exit, the group's VM may exit, closing all 230 * connections, before this call had returned. If that 231 * happens, then a RemoteException will be caught 232 * here. 233 */ 234 } 235 236 System.err.println("Pause for shutdown to happen..."); 237 Thread.sleep(5000); 238 239 /* 240 * Wait for "latecomer" restartable service to be 241 * automatically restarted. 242 */ 243 callbackObj.waitFor(RESTARTABLE); 244 System.err.println( 245 "TEST PASSED: rmid restarted latecomer service"); 246 247 } catch (Exception e) { 248 TestLibrary.bomb(e); 249 } finally { 250 rmid.cleanup(); 251 TestLibrary.unexport(callbackObj); 252 } 253 } 254 255 256 } 257 258 259 interface ActivateMe extends Remote { 260 public void ping() throws RemoteException; 261 public void callback(String responder) throws RemoteException; 262 public void shutdown() throws RemoteException; 263 }