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 }