src/share/classes/sun/rmi/server/Activation.java

Print this page


   1 /*
   2  * Copyright (c) 1997, 2012, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  57 import java.rmi.RemoteException;
  58 import java.rmi.activation.ActivationDesc;
  59 import java.rmi.activation.ActivationException;
  60 import java.rmi.activation.ActivationGroupDesc;
  61 import java.rmi.activation.ActivationGroup;
  62 import java.rmi.activation.ActivationGroupID;
  63 import java.rmi.activation.ActivationID;
  64 import java.rmi.activation.ActivationInstantiator;
  65 import java.rmi.activation.ActivationMonitor;
  66 import java.rmi.activation.ActivationSystem;
  67 import java.rmi.activation.Activator;
  68 import java.rmi.activation.UnknownGroupException;
  69 import java.rmi.activation.UnknownObjectException;
  70 import java.rmi.registry.Registry;
  71 import java.rmi.server.ObjID;
  72 import java.rmi.server.RMIClassLoader;
  73 import java.rmi.server.RMIClientSocketFactory;
  74 import java.rmi.server.RMIServerSocketFactory;
  75 import java.rmi.server.RemoteObject;
  76 import java.rmi.server.RemoteServer;

  77 import java.rmi.server.UnicastRemoteObject;
  78 import java.security.AccessControlException;
  79 import java.security.AccessController;
  80 import java.security.AllPermission;
  81 import java.security.CodeSource;
  82 import java.security.Permission;
  83 import java.security.PermissionCollection;
  84 import java.security.Permissions;
  85 import java.security.Policy;
  86 import java.security.PrivilegedAction;

  87 import java.security.PrivilegedExceptionAction;
  88 import java.security.cert.Certificate;
  89 import java.text.MessageFormat;
  90 import java.util.ArrayList;
  91 import java.util.Arrays;
  92 import java.util.Date;
  93 import java.util.Enumeration;
  94 import java.util.HashMap;
  95 import java.util.HashSet;
  96 import java.util.Iterator;
  97 import java.util.List;
  98 import java.util.Map;
  99 import java.util.MissingResourceException;
 100 import java.util.Properties;
 101 import java.util.ResourceBundle;
 102 import java.util.Set;
 103 import java.util.concurrent.ConcurrentHashMap;
 104 import sun.rmi.log.LogHandler;
 105 import sun.rmi.log.ReliableLog;
 106 import sun.rmi.registry.RegistryImpl;
 107 import sun.rmi.runtime.NewThreadAction;
 108 import sun.rmi.server.UnicastServerRef;
 109 import sun.rmi.transport.LiveRef;

 110 import sun.security.action.GetBooleanAction;
 111 import sun.security.action.GetIntegerAction;
 112 import sun.security.action.GetPropertyAction;
 113 import sun.security.provider.PolicyFile;
 114 import com.sun.rmi.rmid.ExecPermission;
 115 import com.sun.rmi.rmid.ExecOptionPermission;
 116 
 117 /**
 118  * The Activator facilitates remote object activation. A "faulting"
 119  * remote reference calls the activator's <code>activate</code> method
 120  * to obtain a "live" reference to a activatable remote object. Upon
 121  * receiving a request for activation, the activator looks up the
 122  * activation descriptor for the activation identifier, id, determines
 123  * the group in which the object should be activated and invokes the
 124  * activate method on the object's activation group (described by the
 125  * remote interface <code>ActivationInstantiator</code>). The
 126  * activator initiates the execution of activation groups as
 127  * necessary. For example, if an activation group for a specific group
 128  * identifier is not already executing, the activator will spawn a
 129  * child process for the activation group. <p>


 165     private transient ReliableLog log;
 166     /** number of updates since last snapshot */
 167     private transient int numUpdates;
 168 
 169     /** the java command */
 170     // accessed by GroupEntry
 171     private transient String[] command;
 172     /** timeout on wait for child process to be created or destroyed */
 173     private static final long groupTimeout =
 174         getInt("sun.rmi.activation.groupTimeout", 60000);
 175     /** take snapshot after this many updates */
 176     private static final int snapshotInterval =
 177         getInt("sun.rmi.activation.snapshotInterval", 200);
 178     /** timeout on wait for child process to be created */
 179     private static final long execTimeout =
 180         getInt("sun.rmi.activation.execTimeout", 30000);
 181 
 182     private static final Object initLock = new Object();
 183     private static boolean initDone = false;
 184 

























 185     // this should be a *private* method since it is privileged
 186     private static int getInt(String name, int def) {
 187         return AccessController.doPrivileged(new GetIntegerAction(name, def));
 188     }
 189 
 190     private transient Activator activator;
 191     private transient Activator activatorStub;
 192     private transient ActivationSystem system;
 193     private transient ActivationSystem systemStub;
 194     private transient ActivationMonitor monitor;
 195     private transient Registry registry;
 196     private transient volatile boolean shuttingDown = false;
 197     private transient volatile Object startupLock;
 198     private transient Thread shutdownHook;
 199 
 200     private static ResourceBundle resources = null;
 201 
 202     /**
 203      * Create an uninitialized instance of Activation that can be
 204      * populated with log data.  This is only called when the initial
 205      * snapshot is taken during the first incarnation of rmid.
 206      */
 207     private Activation() {}
 208 
 209     /**




















































 210      * Recover activation state from the reliable log and initialize
 211      * activation services.
 212      */
 213     private static void startActivation(int port,
 214                                         RMIServerSocketFactory ssf,
 215                                         String logName,
 216                                         String[] childArgs)
 217         throws Exception
 218     {
 219         ReliableLog log = new ReliableLog(logName, new ActLogHandler());
 220         Activation state = (Activation) log.recover();
 221         state.init(port, ssf, log, childArgs);
 222     }
 223 
 224     /**
 225      * Initialize the Activation instantiation; start activation
 226      * services.
 227      */
 228     private void init(int port,
 229                       RMIServerSocketFactory ssf,


 409 
 410     class ActivationMonitorImpl extends UnicastRemoteObject
 411         implements ActivationMonitor
 412     {
 413         private static final long serialVersionUID = -6214940464757948867L;
 414 
 415         ActivationMonitorImpl(int port, RMIServerSocketFactory ssf)
 416             throws RemoteException
 417         {
 418             super(port, null, ssf);
 419         }
 420 
 421         public void inactiveObject(ActivationID id)
 422             throws UnknownObjectException, RemoteException
 423         {
 424             try {
 425                 checkShutdown();
 426             } catch (ActivationException e) {
 427                 return;
 428             }
 429             RegistryImpl.checkAccess("Activator.inactiveObject");
 430             getGroupEntry(id).inactiveObject(id);
 431         }
 432 
 433         public void activeObject(ActivationID id,
 434                                  MarshalledObject<? extends Remote> mobj)
 435             throws UnknownObjectException, RemoteException
 436         {
 437             try {
 438                 checkShutdown();
 439             } catch (ActivationException e) {
 440                 return;
 441             }
 442             RegistryImpl.checkAccess("ActivationSystem.activeObject");
 443             getGroupEntry(id).activeObject(id, mobj);
 444         }
 445 
 446         public void inactiveGroup(ActivationGroupID id,
 447                                   long incarnation)
 448             throws UnknownGroupException, RemoteException
 449         {
 450             try {
 451                 checkShutdown();
 452             } catch (ActivationException e) {
 453                 return;
 454             }
 455             RegistryImpl.checkAccess("ActivationMonitor.inactiveGroup");
 456             getGroupEntry(id).inactiveGroup(incarnation, false);
 457         }
 458     }
 459 
 460 
 461     class ActivationSystemImpl
 462         extends RemoteServer
 463         implements ActivationSystem
 464     {
 465         private static final long serialVersionUID = 9100152600327688967L;
 466 
 467         // Because ActivationSystemImpl has a fixed ObjID, it can be
 468         // called by clients holding stale remote references.  Each of
 469         // its remote methods, then, must check startupLock (calling
 470         // checkShutdown() is easiest).
 471         ActivationSystemImpl(int port, RMIServerSocketFactory ssf)
 472             throws RemoteException
 473         {
 474             /* Server ref must be created and assigned before remote object
 475              * 'this' can be exported.
 476              */
 477             LiveRef lref = new LiveRef(new ObjID(4), port, null, ssf);
 478             UnicastServerRef uref = new UnicastServerRef(lref);
 479             ref = uref;
 480             uref.exportObject(this, null);
 481         }
 482 
 483         public ActivationID registerObject(ActivationDesc desc)
 484             throws ActivationException, UnknownGroupException, RemoteException
 485         {
 486             checkShutdown();
 487             RegistryImpl.checkAccess("ActivationSystem.registerObject");
 488 
 489             ActivationGroupID groupID = desc.getGroupID();
 490             ActivationID id = new ActivationID(activatorStub);
 491             getGroupEntry(groupID).registerObject(id, desc, true);
 492             return id;
 493         }
 494 
 495         public void unregisterObject(ActivationID id)
 496             throws ActivationException, UnknownObjectException, RemoteException
 497         {
 498             checkShutdown();
 499             RegistryImpl.checkAccess("ActivationSystem.unregisterObject");
 500             getGroupEntry(id).unregisterObject(id, true);
 501         }
 502 
 503         public ActivationGroupID registerGroup(ActivationGroupDesc desc)
 504             throws ActivationException, RemoteException
 505         {
 506             checkShutdown();
 507             RegistryImpl.checkAccess("ActivationSystem.registerGroup");
 508             checkArgs(desc, null);
 509 
 510             ActivationGroupID id = new ActivationGroupID(systemStub);
 511             GroupEntry entry = new GroupEntry(id, desc);
 512             // table insertion must take place before log update
 513             groupTable.put(id, entry);
 514             addLogRecord(new LogRegisterGroup(id, desc));
 515             return id;
 516         }
 517 
 518         public ActivationMonitor activeGroup(ActivationGroupID id,
 519                                              ActivationInstantiator group,
 520                                              long incarnation)
 521             throws ActivationException, UnknownGroupException, RemoteException
 522         {
 523             checkShutdown();
 524             RegistryImpl.checkAccess("ActivationSystem.activeGroup");
 525 
 526             getGroupEntry(id).activeGroup(group, incarnation);
 527             return monitor;
 528         }
 529 
 530         public void unregisterGroup(ActivationGroupID id)
 531             throws ActivationException, UnknownGroupException, RemoteException
 532         {
 533             checkShutdown();
 534             RegistryImpl.checkAccess("ActivationSystem.unregisterGroup");
 535 
 536             // remove entry before unregister so state is updated before
 537             // logged
 538             removeGroupEntry(id).unregisterGroup(true);
 539         }
 540 
 541         public ActivationDesc setActivationDesc(ActivationID id,
 542                                                 ActivationDesc desc)
 543             throws ActivationException, UnknownObjectException, RemoteException
 544         {
 545             checkShutdown();
 546             RegistryImpl.checkAccess("ActivationSystem.setActivationDesc");
 547 
 548             if (!getGroupID(id).equals(desc.getGroupID())) {
 549                 throw new ActivationException(
 550                     "ActivationDesc contains wrong group");
 551             }
 552             return getGroupEntry(id).setActivationDesc(id, desc, true);
 553         }
 554 
 555         public ActivationGroupDesc setActivationGroupDesc(ActivationGroupID id,
 556                                                           ActivationGroupDesc desc)
 557             throws ActivationException, UnknownGroupException, RemoteException
 558         {
 559             checkShutdown();
 560             RegistryImpl.checkAccess(
 561                 "ActivationSystem.setActivationGroupDesc");
 562 
 563             checkArgs(desc, null);
 564             return getGroupEntry(id).setActivationGroupDesc(id, desc, true);
 565         }
 566 
 567         public ActivationDesc getActivationDesc(ActivationID id)
 568             throws ActivationException, UnknownObjectException, RemoteException
 569         {
 570             checkShutdown();
 571             RegistryImpl.checkAccess("ActivationSystem.getActivationDesc");
 572 
 573             return getGroupEntry(id).getActivationDesc(id);
 574         }
 575 
 576         public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID id)
 577             throws ActivationException, UnknownGroupException, RemoteException
 578         {
 579             checkShutdown();
 580             RegistryImpl.checkAccess
 581                 ("ActivationSystem.getActivationGroupDesc");
 582 
 583             return getGroupEntry(id).desc;
 584         }
 585 
 586         /**
 587          * Shutdown the activation system. Destroys all groups spawned by
 588          * the activation daemon and exits the activation daemon.
 589          */
 590         public void shutdown() throws AccessException {
 591             RegistryImpl.checkAccess("ActivationSystem.shutdown");
 592 
 593             Object lock = startupLock;
 594             if (lock != null) {
 595                 synchronized (lock) {
 596                     // nothing
 597                 }
 598             }
 599 
 600             synchronized (Activation.this) {
 601                 if (!shuttingDown) {
 602                     shuttingDown = true;
 603                     (new Shutdown()).start();
 604                 }
 605             }
 606         }
 607     }
 608 
 609     private void checkShutdown() throws ActivationException {
 610         // if the startup critical section is running, wait until it
 611         // completes/fails before continuing with the remote call.


   1 /*
   2  * Copyright (c) 1997, 2013, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  57 import java.rmi.RemoteException;
  58 import java.rmi.activation.ActivationDesc;
  59 import java.rmi.activation.ActivationException;
  60 import java.rmi.activation.ActivationGroupDesc;
  61 import java.rmi.activation.ActivationGroup;
  62 import java.rmi.activation.ActivationGroupID;
  63 import java.rmi.activation.ActivationID;
  64 import java.rmi.activation.ActivationInstantiator;
  65 import java.rmi.activation.ActivationMonitor;
  66 import java.rmi.activation.ActivationSystem;
  67 import java.rmi.activation.Activator;
  68 import java.rmi.activation.UnknownGroupException;
  69 import java.rmi.activation.UnknownObjectException;
  70 import java.rmi.registry.Registry;
  71 import java.rmi.server.ObjID;
  72 import java.rmi.server.RMIClassLoader;
  73 import java.rmi.server.RMIClientSocketFactory;
  74 import java.rmi.server.RMIServerSocketFactory;
  75 import java.rmi.server.RemoteObject;
  76 import java.rmi.server.RemoteServer;
  77 import java.rmi.server.ServerNotActiveException;
  78 import java.rmi.server.UnicastRemoteObject;
  79 import java.security.AccessControlException;
  80 import java.security.AccessController;
  81 import java.security.AllPermission;
  82 import java.security.CodeSource;
  83 import java.security.Permission;
  84 import java.security.PermissionCollection;
  85 import java.security.Permissions;
  86 import java.security.Policy;
  87 import java.security.PrivilegedAction;
  88 import java.security.PrivilegedActionException;
  89 import java.security.PrivilegedExceptionAction;
  90 import java.security.cert.Certificate;
  91 import java.text.MessageFormat;
  92 import java.util.ArrayList;
  93 import java.util.Arrays;
  94 import java.util.Date;
  95 import java.util.Enumeration;
  96 import java.util.HashMap;
  97 import java.util.HashSet;
  98 import java.util.Iterator;
  99 import java.util.List;
 100 import java.util.Map;
 101 import java.util.MissingResourceException;
 102 import java.util.Properties;
 103 import java.util.ResourceBundle;
 104 import java.util.Set;
 105 import java.util.concurrent.ConcurrentHashMap;
 106 import sun.rmi.log.LogHandler;
 107 import sun.rmi.log.ReliableLog;
 108 import sun.rmi.registry.RegistryImpl;
 109 import sun.rmi.runtime.NewThreadAction;
 110 import sun.rmi.server.UnicastServerRef;
 111 import sun.rmi.transport.LiveRef;
 112 import sun.rmi.transport.tcp.TCPTransport;
 113 import sun.security.action.GetBooleanAction;
 114 import sun.security.action.GetIntegerAction;
 115 import sun.security.action.GetPropertyAction;
 116 import sun.security.provider.PolicyFile;
 117 import com.sun.rmi.rmid.ExecPermission;
 118 import com.sun.rmi.rmid.ExecOptionPermission;
 119 
 120 /**
 121  * The Activator facilitates remote object activation. A "faulting"
 122  * remote reference calls the activator's <code>activate</code> method
 123  * to obtain a "live" reference to a activatable remote object. Upon
 124  * receiving a request for activation, the activator looks up the
 125  * activation descriptor for the activation identifier, id, determines
 126  * the group in which the object should be activated and invokes the
 127  * activate method on the object's activation group (described by the
 128  * remote interface <code>ActivationInstantiator</code>). The
 129  * activator initiates the execution of activation groups as
 130  * necessary. For example, if an activation group for a specific group
 131  * identifier is not already executing, the activator will spawn a
 132  * child process for the activation group. <p>


 168     private transient ReliableLog log;
 169     /** number of updates since last snapshot */
 170     private transient int numUpdates;
 171 
 172     /** the java command */
 173     // accessed by GroupEntry
 174     private transient String[] command;
 175     /** timeout on wait for child process to be created or destroyed */
 176     private static final long groupTimeout =
 177         getInt("sun.rmi.activation.groupTimeout", 60000);
 178     /** take snapshot after this many updates */
 179     private static final int snapshotInterval =
 180         getInt("sun.rmi.activation.snapshotInterval", 200);
 181     /** timeout on wait for child process to be created */
 182     private static final long execTimeout =
 183         getInt("sun.rmi.activation.execTimeout", 30000);
 184 
 185     private static final Object initLock = new Object();
 186     private static boolean initDone = false;
 187 
 188     private static final InetAddress remoteClientAddress;
 189     static {
 190         remoteClientAddress = java.security.AccessController.doPrivileged(
 191             new java.security.PrivilegedAction<InetAddress>() {
 192                 public InetAddress run() {
 193                     String remoteClientProp =
 194                         System.getProperty("sun.rmi.activation.remoteClient",
 195                            null);
 196 
 197                     if (remoteClientProp == null) {
 198                         return null;
 199                     }
 200 
 201                     try {
 202                         return InetAddress.getByName(remoteClientProp);
 203                     } catch (Throwable t) {
 204                         System.err.println("Activation: Cannot get the IP " +
 205                             "address of the remote client: " +
 206                             remoteClientProp);
 207                     }
 208 
 209                     return null;
 210                 }});
 211     }
 212 
 213     // this should be a *private* method since it is privileged
 214     private static int getInt(String name, int def) {
 215         return AccessController.doPrivileged(new GetIntegerAction(name, def));
 216     }
 217 
 218     private transient Activator activator;
 219     private transient Activator activatorStub;
 220     private transient ActivationSystem system;
 221     private transient ActivationSystem systemStub;
 222     private transient ActivationMonitor monitor;
 223     private transient Registry registry;
 224     private transient volatile boolean shuttingDown = false;
 225     private transient volatile Object startupLock;
 226     private transient Thread shutdownHook;
 227 
 228     private static ResourceBundle resources = null;
 229 
 230     /**
 231      * Create an uninitialized instance of Activation that can be
 232      * populated with log data.  This is only called when the initial
 233      * snapshot is taken during the first incarnation of rmid.
 234      */
 235     private Activation() {}
 236 
 237     /**
 238      * Check that the caller has access to this interface.
 239      * <p>
 240      * Use the default policy as implemented in RegistryImpl.checkAccess,
 241      * unless the sun.rmi.activation.remoteClient property is set, and in
 242      * that case only allow access from that host.
 243      *
 244      * @param op name of operation used to create a meaningful exception
 245      *           message, the parameter is not used to determine access
 246      */
 247     static void checkAccess(String op) throws AccessException {
 248         if (remoteClientAddress == null) {
 249             /*
 250              * Note, the op arg to checkAccess is only used to build an
 251              * access exception message if needed.
 252              */
 253             RegistryImpl.checkAccess(op);
 254             return;
 255         }
 256 
 257         InetAddress clientHost;
 258 
 259         try {
 260             // Get client host that this operation was made from.
 261             final String clientHostName = TCPTransport.getClientHost();
 262 
 263             try {
 264                 clientHost = java.security.AccessController.doPrivileged(
 265                     new java.security.PrivilegedExceptionAction<InetAddress>() {
 266                         public InetAddress run()
 267                             throws java.net.UnknownHostException
 268                         {
 269                             return InetAddress.getByName(clientHostName);
 270                         }
 271                     });
 272             } catch (PrivilegedActionException pae) {
 273                 throw new AccessException("RMI " + op + " disallowed; " +
 274                     clientHostName + " is an unknown client");
 275             }
 276         } catch (ServerNotActiveException ex) {
 277             throw new AccessException("RMI " + op +
 278                 " is not allowed from the local host");
 279         }
 280 
 281         if (remoteClientAddress.equals(clientHost)) {
 282             return;
 283         }
 284 
 285         throw new AccessException("RMI " + op + " is not allowed from " +
 286             clientHost);
 287     }
 288 
 289     /**
 290      * Recover activation state from the reliable log and initialize
 291      * activation services.
 292      */
 293     private static void startActivation(int port,
 294                                         RMIServerSocketFactory ssf,
 295                                         String logName,
 296                                         String[] childArgs)
 297         throws Exception
 298     {
 299         ReliableLog log = new ReliableLog(logName, new ActLogHandler());
 300         Activation state = (Activation) log.recover();
 301         state.init(port, ssf, log, childArgs);
 302     }
 303 
 304     /**
 305      * Initialize the Activation instantiation; start activation
 306      * services.
 307      */
 308     private void init(int port,
 309                       RMIServerSocketFactory ssf,


 489 
 490     class ActivationMonitorImpl extends UnicastRemoteObject
 491         implements ActivationMonitor
 492     {
 493         private static final long serialVersionUID = -6214940464757948867L;
 494 
 495         ActivationMonitorImpl(int port, RMIServerSocketFactory ssf)
 496             throws RemoteException
 497         {
 498             super(port, null, ssf);
 499         }
 500 
 501         public void inactiveObject(ActivationID id)
 502             throws UnknownObjectException, RemoteException
 503         {
 504             try {
 505                 checkShutdown();
 506             } catch (ActivationException e) {
 507                 return;
 508             }
 509             Activation.checkAccess("Activator.inactiveObject");
 510             getGroupEntry(id).inactiveObject(id);
 511         }
 512 
 513         public void activeObject(ActivationID id,
 514                                  MarshalledObject<? extends Remote> mobj)
 515             throws UnknownObjectException, RemoteException
 516         {
 517             try {
 518                 checkShutdown();
 519             } catch (ActivationException e) {
 520                 return;
 521             }
 522             Activation.checkAccess("ActivationSystem.activeObject");
 523             getGroupEntry(id).activeObject(id, mobj);
 524         }
 525 
 526         public void inactiveGroup(ActivationGroupID id,
 527                                   long incarnation)
 528             throws UnknownGroupException, RemoteException
 529         {
 530             try {
 531                 checkShutdown();
 532             } catch (ActivationException e) {
 533                 return;
 534             }
 535             Activation.checkAccess("ActivationMonitor.inactiveGroup");
 536             getGroupEntry(id).inactiveGroup(incarnation, false);
 537         }
 538     }
 539 
 540 
 541     class ActivationSystemImpl
 542         extends RemoteServer
 543         implements ActivationSystem
 544     {
 545         private static final long serialVersionUID = 9100152600327688967L;
 546 
 547         // Because ActivationSystemImpl has a fixed ObjID, it can be
 548         // called by clients holding stale remote references.  Each of
 549         // its remote methods, then, must check startupLock (calling
 550         // checkShutdown() is easiest).
 551         ActivationSystemImpl(int port, RMIServerSocketFactory ssf)
 552             throws RemoteException
 553         {
 554             /* Server ref must be created and assigned before remote object
 555              * 'this' can be exported.
 556              */
 557             LiveRef lref = new LiveRef(new ObjID(4), port, null, ssf);
 558             UnicastServerRef uref = new UnicastServerRef(lref);
 559             ref = uref;
 560             uref.exportObject(this, null);
 561         }
 562 
 563         public ActivationID registerObject(ActivationDesc desc)
 564             throws ActivationException, UnknownGroupException, RemoteException
 565         {
 566             checkShutdown();
 567             Activation.checkAccess("ActivationSystem.registerObject");
 568 
 569             ActivationGroupID groupID = desc.getGroupID();
 570             ActivationID id = new ActivationID(activatorStub);
 571             getGroupEntry(groupID).registerObject(id, desc, true);
 572             return id;
 573         }
 574 
 575         public void unregisterObject(ActivationID id)
 576             throws ActivationException, UnknownObjectException, RemoteException
 577         {
 578             checkShutdown();
 579             Activation.checkAccess("ActivationSystem.unregisterObject");
 580             getGroupEntry(id).unregisterObject(id, true);
 581         }
 582 
 583         public ActivationGroupID registerGroup(ActivationGroupDesc desc)
 584             throws ActivationException, RemoteException
 585         {
 586             checkShutdown();
 587             Activation.checkAccess("ActivationSystem.registerGroup");
 588             checkArgs(desc, null);
 589 
 590             ActivationGroupID id = new ActivationGroupID(systemStub);
 591             GroupEntry entry = new GroupEntry(id, desc);
 592             // table insertion must take place before log update
 593             groupTable.put(id, entry);
 594             addLogRecord(new LogRegisterGroup(id, desc));
 595             return id;
 596         }
 597 
 598         public ActivationMonitor activeGroup(ActivationGroupID id,
 599                                              ActivationInstantiator group,
 600                                              long incarnation)
 601             throws ActivationException, UnknownGroupException, RemoteException
 602         {
 603             checkShutdown();
 604             Activation.checkAccess("ActivationSystem.activeGroup");
 605 
 606             getGroupEntry(id).activeGroup(group, incarnation);
 607             return monitor;
 608         }
 609 
 610         public void unregisterGroup(ActivationGroupID id)
 611             throws ActivationException, UnknownGroupException, RemoteException
 612         {
 613             checkShutdown();
 614             Activation.checkAccess("ActivationSystem.unregisterGroup");
 615 
 616             // remove entry before unregister so state is updated before
 617             // logged
 618             removeGroupEntry(id).unregisterGroup(true);
 619         }
 620 
 621         public ActivationDesc setActivationDesc(ActivationID id,
 622                                                 ActivationDesc desc)
 623             throws ActivationException, UnknownObjectException, RemoteException
 624         {
 625             checkShutdown();
 626             Activation.checkAccess("ActivationSystem.setActivationDesc");
 627 
 628             if (!getGroupID(id).equals(desc.getGroupID())) {
 629                 throw new ActivationException(
 630                     "ActivationDesc contains wrong group");
 631             }
 632             return getGroupEntry(id).setActivationDesc(id, desc, true);
 633         }
 634 
 635         public ActivationGroupDesc setActivationGroupDesc(ActivationGroupID id,
 636                                                           ActivationGroupDesc desc)
 637             throws ActivationException, UnknownGroupException, RemoteException
 638         {
 639             checkShutdown();
 640             Activation.checkAccess(
 641                 "ActivationSystem.setActivationGroupDesc");
 642 
 643             checkArgs(desc, null);
 644             return getGroupEntry(id).setActivationGroupDesc(id, desc, true);
 645         }
 646 
 647         public ActivationDesc getActivationDesc(ActivationID id)
 648             throws ActivationException, UnknownObjectException, RemoteException
 649         {
 650             checkShutdown();
 651             Activation.checkAccess("ActivationSystem.getActivationDesc");
 652 
 653             return getGroupEntry(id).getActivationDesc(id);
 654         }
 655 
 656         public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID id)
 657             throws ActivationException, UnknownGroupException, RemoteException
 658         {
 659             checkShutdown();
 660             Activation.checkAccess
 661                 ("ActivationSystem.getActivationGroupDesc");
 662 
 663             return getGroupEntry(id).desc;
 664         }
 665 
 666         /**
 667          * Shutdown the activation system. Destroys all groups spawned by
 668          * the activation daemon and exits the activation daemon.
 669          */
 670         public void shutdown() throws AccessException {
 671             Activation.checkAccess("ActivationSystem.shutdown");
 672 
 673             Object lock = startupLock;
 674             if (lock != null) {
 675                 synchronized (lock) {
 676                     // nothing
 677                 }
 678             }
 679 
 680             synchronized (Activation.this) {
 681                 if (!shuttingDown) {
 682                     shuttingDown = true;
 683                     (new Shutdown()).start();
 684                 }
 685             }
 686         }
 687     }
 688 
 689     private void checkShutdown() throws ActivationException {
 690         // if the startup critical section is running, wait until it
 691         // completes/fails before continuing with the remote call.