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