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