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 8085192 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 = RMID.launch(); 169 170 /* Cause activation groups to have a security policy that will 171 * allow security managers to be downloaded and installed 172 */ 173 Properties p = new Properties(); 174 // this test must always set policies/managers in its 175 // activation groups 176 p.put("java.security.policy", 177 TestParams.defaultGroupPolicy); 178 p.put("java.security.manager", 179 TestParams.defaultSecurityManager); 180 181 /* 182 * Create unicast object to be contacted when service is activated. 183 */ 184 callbackObj = new RestartLatecomer(); 185 /* 186 * Create and register descriptors for a restartable and 187 * non-restartable service (respectively) in a group other than 188 * this VM's group. 189 */ 190 System.err.println("Creating descriptors"); 191 192 Object[] stuff = new Object[] { RESTARTABLE, callbackObj }; 193 MarshalledObject restartMobj = new MarshalledObject(stuff); 194 ActivationGroupDesc groupDesc = 195 new ActivationGroupDesc(p, null); 196 197 stuff[0] = ACTIVATABLE; 198 MarshalledObject activateMobj = new MarshalledObject(stuff); 199 ActivationGroupID groupID = 200 ActivationGroup.getSystem().registerGroup(groupDesc); 201 202 ActivationDesc activatableDesc = 203 new ActivationDesc(groupID, "RestartLatecomer", null, 204 activateMobj, false); 205 ActivationDesc restartableDesc = 206 new ActivationDesc(groupID, "RestartLatecomer", null, 207 restartMobj, true); 208 209 210 System.err.println("Register activatable object's descriptor"); 211 ActivateMe activatableObj = 212 (ActivateMe) Activatable.register(activatableDesc); 213 214 System.err.println("Activate object (starts group VM)"); 215 activatableObj.ping(); 216 217 callbackObj.waitFor(ACTIVATABLE); 218 callbackObj.clearResponders(); 219 System.err.println("Callback from activatable object received"); 220 221 System.err.println("Register restartable object's descriptor"); 222 ActivateMe restartableObj = 223 (ActivateMe) Activatable.register(restartableDesc); 224 225 System.err.println("Shutdown object (exits group VM)"); 226 try { 227 activatableObj.shutdown(); 228 } catch (RemoteException ignore) { 229 /* 230 * Since the shutdown method spawns a thread to call 231 * System.exit, the group's VM may exit, closing all 232 * connections, before this call had returned. If that 233 * happens, then a RemoteException will be caught 234 * here. 235 */ 236 } 237 238 System.err.println("Pause for shutdown to happen..."); 239 Thread.sleep(5000); 240 241 /* 242 * Wait for "latecomer" restartable service to be 243 * automatically restarted. 244 */ 245 callbackObj.waitFor(RESTARTABLE); 246 System.err.println( 247 "TEST PASSED: rmid restarted latecomer service"); 248 249 } catch (Exception e) { 250 TestLibrary.bomb(e); 251 } finally { 252 rmid.cleanup(); 253 TestLibrary.unexport(callbackObj); 254 } 255 } 256 257 258 } 259 260 261 interface ActivateMe extends Remote { 262 public void ping() throws RemoteException; 263 public void callback(String responder) throws RemoteException; 264 public void shutdown() throws RemoteException; 265 }