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