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 ActivationLibrary
  36  *     RestartLatecomer RestartLatecomer_Stub
  37  * @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer
  38  */
  39 
  40 import java.io.*;
  41 import java.rmi.*;
  42 import java.rmi.activation.*;
  43 import java.rmi.server.*;
  44 import java.rmi.registry.*;
  45 import java.util.Vector;
  46 import java.util.Properties;
  47 
  48 public 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 
 264 interface ActivateMe extends Remote {
 265     public void ping() throws RemoteException;
 266     public void callback(String responder) throws RemoteException;
 267     public void shutdown() throws RemoteException;
 268 }