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

Print this page




 121  * activation descriptor for the activation identifier, id, determines
 122  * the group in which the object should be activated and invokes the
 123  * activate method on the object's activation group (described by the
 124  * remote interface <code>ActivationInstantiator</code>). The
 125  * activator initiates the execution of activation groups as
 126  * necessary. For example, if an activation group for a specific group
 127  * identifier is not already executing, the activator will spawn a
 128  * child process for the activation group. <p>
 129  *
 130  * The activator is responsible for monitoring and detecting when
 131  * activation groups fail so that it can remove stale remote references
 132  * from its internal tables. <p>
 133  *
 134  * @author      Ann Wollrath
 135  * @since       1.2
 136  */
 137 public class Activation implements Serializable {
 138 
 139     /** indicate compatibility with JDK 1.2 version of class */
 140     private static final long serialVersionUID = 2921265612698155191L;
 141 
 142     private static final byte MAJOR_VERSION = 1;
 143     private static final byte MINOR_VERSION = 0;
 144 
 145     /** exec policy object */
 146     private static Object execPolicy;
 147     private static Method execPolicyMethod;
 148     private static boolean debugExec;
 149 
 150     /** maps activation id to its respective group id */
 151     private Map<ActivationID,ActivationGroupID> idTable =
 152         new ConcurrentHashMap<>();
 153     /** maps group id to its GroupEntry groups */
 154     private Map<ActivationGroupID,GroupEntry> groupTable =
 155         new ConcurrentHashMap<>();
 156 
 157     private byte majorVersion = MAJOR_VERSION;
 158     private byte minorVersion = MINOR_VERSION;
 159 
 160     /** number of simultaneous group exec's */
 161     private transient int groupSemaphore;


 281     /**
 282      * Previous versions used HashMap instead of ConcurrentHashMap.
 283      * Replace any HashMaps found during deserialization with
 284      * ConcurrentHashMaps.
 285      */
 286     private void readObject(ObjectInputStream ois)
 287         throws IOException, ClassNotFoundException
 288     {
 289         ois.defaultReadObject();
 290         if (! (groupTable instanceof ConcurrentHashMap)) {
 291             groupTable = new ConcurrentHashMap<>(groupTable);
 292         }
 293         if (! (idTable instanceof ConcurrentHashMap)) {
 294             idTable = new ConcurrentHashMap<>(idTable);
 295         }
 296     }
 297 
 298     private static class SystemRegistryImpl extends RegistryImpl {
 299 
 300         private static final String NAME = ActivationSystem.class.getName();

 301         private final ActivationSystem systemStub;
 302 
 303         SystemRegistryImpl(int port,
 304                            RMIClientSocketFactory csf,
 305                            RMIServerSocketFactory ssf,
 306                            ActivationSystem systemStub)
 307             throws RemoteException
 308         {
 309             super(port, csf, ssf);
 310             this.systemStub = systemStub;
 311         }
 312 
 313         /**
 314          * Returns the activation system stub if the specified name
 315          * matches the activation system's class name, otherwise
 316          * returns the result of invoking super.lookup with the specified
 317          * name.
 318          */
 319         public Remote lookup(String name)
 320             throws RemoteException, NotBoundException


 787      *
 788      * WARNING: GroupEntry objects should not be written into log file
 789      * updates.  GroupEntrys are inner classes of Activation and they
 790      * can not be serialized independent of this class.  If the
 791      * complete Activation system is written out as a log update, the
 792      * point of having updates is nullified.
 793      */
 794     private class GroupEntry implements Serializable {
 795 
 796         /** indicate compatibility with JDK 1.2 version of class */
 797         private static final long serialVersionUID = 7222464070032993304L;
 798         private static final int MAX_TRIES = 2;
 799         private static final int NORMAL = 0;
 800         private static final int CREATING = 1;
 801         private static final int TERMINATE = 2;
 802         private static final int TERMINATING = 3;
 803 
 804         ActivationGroupDesc desc = null;
 805         ActivationGroupID groupID = null;
 806         long incarnation = 0;
 807         Map<ActivationID,ObjectEntry> objects =
 808             new HashMap<ActivationID,ObjectEntry>();
 809         Set<ActivationID> restartSet = new HashSet<ActivationID>();
 810 
 811         transient ActivationInstantiator group = null;
 812         transient int status = NORMAL;
 813         transient long waitTime = 0;
 814         transient String groupName = null;
 815         transient Process child = null;
 816         transient boolean removed = false;
 817         transient Watchdog watchdog = null;
 818 
 819         GroupEntry(ActivationGroupID groupID, ActivationGroupDesc desc) {
 820             this.groupID = groupID;
 821             this.desc = desc;
 822         }
 823 
 824         void restartServices() {
 825             Iterator<ActivationID> iter = null;
 826 
 827             synchronized (this) {
 828                 if (restartSet.isEmpty()) {
 829                     return;


1040 
1041         private void childGone() {
1042             if (child != null) {
1043                 child = null;
1044                 watchdog.dispose();
1045                 watchdog = null;
1046                 status = NORMAL;
1047                 notifyAll();
1048             }
1049         }
1050 
1051         private void terminate() {
1052             if (child != null && status != TERMINATING) {
1053                 child.destroy();
1054                 status = TERMINATING;
1055                 waitTime = System.currentTimeMillis() + groupTimeout;
1056                 notifyAll();
1057             }
1058         }
1059 





1060         private void await() {
1061             while (true) {
1062                 switch (status) {
1063                 case NORMAL:
1064                     return;
1065                 case TERMINATE:
1066                     terminate();
1067                 case TERMINATING:
1068                     try {
1069                         child.exitValue();
1070                     } catch (IllegalThreadStateException e) {
1071                         long now = System.currentTimeMillis();
1072                         if (waitTime > now) {
1073                             try {
1074                                 wait(waitTime - now);
1075                             } catch (InterruptedException ee) {
1076                             }
1077                             continue;
1078                         }
1079                         // REMIND: print message that group did not terminate?


1211                         sb.append(argv[j]);
1212                     }
1213                     System.err.println(
1214                         MessageFormat.format(
1215                             getTextResource("rmid.exec.command"),
1216                             sb.toString()));
1217                 }
1218 
1219                 try {
1220                     child = Runtime.getRuntime().exec(argv);
1221                     status = CREATING;
1222                     ++incarnation;
1223                     watchdog = new Watchdog();
1224                     watchdog.start();
1225                     addLogRecord(new LogGroupIncarnation(id, incarnation));
1226 
1227                     // handle child I/O streams before writing to child
1228                     PipeWriter.plugTogetherPair
1229                         (child.getInputStream(), System.out,
1230                          child.getErrorStream(), System.err);
1231 
1232                     MarshalOutputStream out =
1233                         new MarshalOutputStream(child.getOutputStream());
1234                     out.writeObject(id);
1235                     out.writeObject(desc);
1236                     out.writeLong(incarnation);
1237                     out.flush();
1238                     out.close();
1239 
1240 
1241                 } catch (IOException e) {
1242                     terminate();
1243                     throw new ActivationException(
1244                         "unable to create activation group", e);
1245                 }
1246 
1247                 try {
1248                     long now = System.currentTimeMillis();
1249                     long stop = now + execTimeout;
1250                     do {
1251                         wait(stop - now);
1252                         if (group != null) {
1253                             return group;
1254                         }
1255                         now = System.currentTimeMillis();
1256                     } while (status == CREATING && now < stop);
1257                 } catch (InterruptedException e) {
1258                 }


1335                 shouldQuit = true;
1336                 if (canInterrupt) {
1337                     interrupt();
1338                 }
1339             }
1340 
1341             /**
1342              * Marks this thread as no longer needing to restart objects.
1343              */
1344             void noRestart() {
1345                 shouldRestart = false;
1346             }
1347         }
1348     }
1349 
1350     private String[] activationArgs(ActivationGroupDesc desc) {
1351         ActivationGroupDesc.CommandEnvironment cmdenv;
1352         cmdenv = desc.getCommandEnvironment();
1353 
1354         // argv is the literal command to exec
1355         List<String> argv = new ArrayList<String>();
1356 
1357         // Command name/path
1358         argv.add((cmdenv != null && cmdenv.getCommandPath() != null)
1359                     ? cmdenv.getCommandPath()
1360                     : command[0]);
1361 
1362         // Group-specific command options
1363         if (cmdenv != null && cmdenv.getCommandOptions() != null) {
1364             argv.addAll(Arrays.asList(cmdenv.getCommandOptions()));
1365         }
1366 
1367         // Properties become -D parameters
1368         Properties props = desc.getPropertyOverrides();
1369         if (props != null) {
1370             for (Enumeration<?> p = props.propertyNames();
1371                  p.hasMoreElements();)
1372             {
1373                 String name = (String) p.nextElement();
1374                 /* Note on quoting: it would be wrong
1375                  * here, since argv will be passed to


1940                                 File.createTempFile("rmid-err", null, null);
1941                             PrintStream errStream =
1942                                 new PrintStream(new FileOutputStream(file));
1943                             System.setErr(errStream);
1944                             return null;
1945                         }
1946                     });
1947 
1948                 ServerSocket serverSocket =
1949                     ((ServerSocketChannel) inheritedChannel).socket();
1950                 port = serverSocket.getLocalPort();
1951                 ssf = new ActivationServerSocketFactory(serverSocket);
1952 
1953                 System.err.println(new Date());
1954                 System.err.println(getTextResource(
1955                                        "rmid.inherited.channel.info") +
1956                                        ": " + inheritedChannel);
1957             }
1958 
1959             String log = null;
1960             List<String> childArgs = new ArrayList<String>();
1961 
1962             /*
1963              * Parse arguments
1964              */
1965             for (int i = 0; i < args.length; i++) {
1966                 if (args[i].equals("-port")) {
1967                     if (ssf != null) {
1968                         bomb(getTextResource("rmid.syntax.port.badarg"));
1969                     }
1970                     if ((i + 1) < args.length) {
1971                         try {
1972                             port = Integer.parseInt(args[++i]);
1973                         } catch (NumberFormatException nfe) {
1974                             bomb(getTextResource("rmid.syntax.port.badnumber"));
1975                         }
1976                     } else {
1977                         bomb(getTextResource("rmid.syntax.port.missing"));
1978                     }
1979 
1980                 } else if (args[i].equals("-log")) {


2014             String execPolicyClassName = AccessController.doPrivileged(
2015                 new GetPropertyAction("sun.rmi.activation.execPolicy", null));
2016             if (execPolicyClassName == null) {
2017                 if (!stop) {
2018                     DefaultExecPolicy.checkConfiguration();
2019                 }
2020                 execPolicyClassName = "default";
2021             }
2022 
2023             /**
2024              * Initialize method for activation exec policy.
2025              */
2026             if (!execPolicyClassName.equals("none")) {
2027                 if (execPolicyClassName.equals("") ||
2028                     execPolicyClassName.equals("default"))
2029                 {
2030                     execPolicyClassName = DefaultExecPolicy.class.getName();
2031                 }
2032 
2033                 try {
2034                     Class<?> execPolicyClass =
2035                         RMIClassLoader.loadClass(execPolicyClassName);
2036                     execPolicy = execPolicyClass.newInstance();
2037                     execPolicyMethod =
2038                         execPolicyClass.getMethod("checkExecCommand",
2039                                                   ActivationGroupDesc.class,
2040                                                   String[].class);
2041                 } catch (Exception e) {
2042                     if (debugExec) {
2043                         System.err.println(
2044                             getTextResource("rmid.exec.policy.exception"));
2045                         e.printStackTrace();
2046                     }
2047                     bomb(getTextResource("rmid.exec.policy.invalid"));
2048                 }
2049             }
2050 
2051             if (stop == true) {
2052                 final int finalPort = port;
2053                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
2054                     public Void run() {
2055                         System.setProperty("java.rmi.activation.port",


2106             }
2107             if (Activation.resources == null) {
2108                 // throwing an Error is a bit extreme, methinks
2109                 return ("[missing resource file: " + key + "]");
2110             }
2111         }
2112 
2113         String val = null;
2114         try {
2115             val = Activation.resources.getString (key);
2116         } catch (MissingResourceException mre) {
2117         }
2118 
2119         if (val == null) {
2120             return ("[missing resource: " + key + "]");
2121         } else {
2122             return val;
2123         }
2124     }
2125 




2126     /*
2127      * Dijkstra semaphore operations to limit the number of subprocesses
2128      * rmid attempts to make at once.
2129      */
2130     /**
2131      * Acquire the group semaphore and return a group name.  Each
2132      * Pstartgroup must be followed by a Vstartgroup.  The calling thread
2133      * will wait until there are fewer than <code>N</code> other threads
2134      * holding the group semaphore.  The calling thread will then acquire
2135      * the semaphore and return.
2136      */
2137     private synchronized String Pstartgroup() throws ActivationException {
2138         while (true) {
2139             checkShutdown();
2140             // Wait until positive, then decrement.
2141             if (groupSemaphore > 0) {
2142                 groupSemaphore--;
2143                 return "Group-" + groupCounter++;
2144             }
2145 




 121  * activation descriptor for the activation identifier, id, determines
 122  * the group in which the object should be activated and invokes the
 123  * activate method on the object's activation group (described by the
 124  * remote interface <code>ActivationInstantiator</code>). The
 125  * activator initiates the execution of activation groups as
 126  * necessary. For example, if an activation group for a specific group
 127  * identifier is not already executing, the activator will spawn a
 128  * child process for the activation group. <p>
 129  *
 130  * The activator is responsible for monitoring and detecting when
 131  * activation groups fail so that it can remove stale remote references
 132  * from its internal tables. <p>
 133  *
 134  * @author      Ann Wollrath
 135  * @since       1.2
 136  */
 137 public class Activation implements Serializable {
 138 
 139     /** indicate compatibility with JDK 1.2 version of class */
 140     private static final long serialVersionUID = 2921265612698155191L;

 141     private static final byte MAJOR_VERSION = 1;
 142     private static final byte MINOR_VERSION = 0;
 143 
 144     /** exec policy object */
 145     private static Object execPolicy;
 146     private static Method execPolicyMethod;
 147     private static boolean debugExec;
 148 
 149     /** maps activation id to its respective group id */
 150     private Map<ActivationID,ActivationGroupID> idTable =
 151         new ConcurrentHashMap<>();
 152     /** maps group id to its GroupEntry groups */
 153     private Map<ActivationGroupID,GroupEntry> groupTable =
 154         new ConcurrentHashMap<>();
 155 
 156     private byte majorVersion = MAJOR_VERSION;
 157     private byte minorVersion = MINOR_VERSION;
 158 
 159     /** number of simultaneous group exec's */
 160     private transient int groupSemaphore;


 280     /**
 281      * Previous versions used HashMap instead of ConcurrentHashMap.
 282      * Replace any HashMaps found during deserialization with
 283      * ConcurrentHashMaps.
 284      */
 285     private void readObject(ObjectInputStream ois)
 286         throws IOException, ClassNotFoundException
 287     {
 288         ois.defaultReadObject();
 289         if (! (groupTable instanceof ConcurrentHashMap)) {
 290             groupTable = new ConcurrentHashMap<>(groupTable);
 291         }
 292         if (! (idTable instanceof ConcurrentHashMap)) {
 293             idTable = new ConcurrentHashMap<>(idTable);
 294         }
 295     }
 296 
 297     private static class SystemRegistryImpl extends RegistryImpl {
 298 
 299         private static final String NAME = ActivationSystem.class.getName();
 300         private static final long serialVersionUID = 4877330021609408794L;
 301         private final ActivationSystem systemStub;
 302 
 303         SystemRegistryImpl(int port,
 304                            RMIClientSocketFactory csf,
 305                            RMIServerSocketFactory ssf,
 306                            ActivationSystem systemStub)
 307             throws RemoteException
 308         {
 309             super(port, csf, ssf);
 310             this.systemStub = systemStub;
 311         }
 312 
 313         /**
 314          * Returns the activation system stub if the specified name
 315          * matches the activation system's class name, otherwise
 316          * returns the result of invoking super.lookup with the specified
 317          * name.
 318          */
 319         public Remote lookup(String name)
 320             throws RemoteException, NotBoundException


 787      *
 788      * WARNING: GroupEntry objects should not be written into log file
 789      * updates.  GroupEntrys are inner classes of Activation and they
 790      * can not be serialized independent of this class.  If the
 791      * complete Activation system is written out as a log update, the
 792      * point of having updates is nullified.
 793      */
 794     private class GroupEntry implements Serializable {
 795 
 796         /** indicate compatibility with JDK 1.2 version of class */
 797         private static final long serialVersionUID = 7222464070032993304L;
 798         private static final int MAX_TRIES = 2;
 799         private static final int NORMAL = 0;
 800         private static final int CREATING = 1;
 801         private static final int TERMINATE = 2;
 802         private static final int TERMINATING = 3;
 803 
 804         ActivationGroupDesc desc = null;
 805         ActivationGroupID groupID = null;
 806         long incarnation = 0;
 807         Map<ActivationID,ObjectEntry> objects = new HashMap<>();
 808         Set<ActivationID> restartSet = new HashSet<>();

 809 
 810         transient ActivationInstantiator group = null;
 811         transient int status = NORMAL;
 812         transient long waitTime = 0;
 813         transient String groupName = null;
 814         transient Process child = null;
 815         transient boolean removed = false;
 816         transient Watchdog watchdog = null;
 817 
 818         GroupEntry(ActivationGroupID groupID, ActivationGroupDesc desc) {
 819             this.groupID = groupID;
 820             this.desc = desc;
 821         }
 822 
 823         void restartServices() {
 824             Iterator<ActivationID> iter = null;
 825 
 826             synchronized (this) {
 827                 if (restartSet.isEmpty()) {
 828                     return;


1039 
1040         private void childGone() {
1041             if (child != null) {
1042                 child = null;
1043                 watchdog.dispose();
1044                 watchdog = null;
1045                 status = NORMAL;
1046                 notifyAll();
1047             }
1048         }
1049 
1050         private void terminate() {
1051             if (child != null && status != TERMINATING) {
1052                 child.destroy();
1053                 status = TERMINATING;
1054                 waitTime = System.currentTimeMillis() + groupTimeout;
1055                 notifyAll();
1056             }
1057         }
1058 
1059        /*
1060         * Fallthrough from TERMINATE to TERMINATING
1061         * is intentional
1062         */
1063         @SuppressWarnings("fallthrough")
1064         private void await() {
1065             while (true) {
1066                 switch (status) {
1067                 case NORMAL:
1068                     return;
1069                 case TERMINATE:
1070                     terminate();
1071                 case TERMINATING:
1072                     try {
1073                         child.exitValue();
1074                     } catch (IllegalThreadStateException e) {
1075                         long now = System.currentTimeMillis();
1076                         if (waitTime > now) {
1077                             try {
1078                                 wait(waitTime - now);
1079                             } catch (InterruptedException ee) {
1080                             }
1081                             continue;
1082                         }
1083                         // REMIND: print message that group did not terminate?


1215                         sb.append(argv[j]);
1216                     }
1217                     System.err.println(
1218                         MessageFormat.format(
1219                             getTextResource("rmid.exec.command"),
1220                             sb.toString()));
1221                 }
1222 
1223                 try {
1224                     child = Runtime.getRuntime().exec(argv);
1225                     status = CREATING;
1226                     ++incarnation;
1227                     watchdog = new Watchdog();
1228                     watchdog.start();
1229                     addLogRecord(new LogGroupIncarnation(id, incarnation));
1230 
1231                     // handle child I/O streams before writing to child
1232                     PipeWriter.plugTogetherPair
1233                         (child.getInputStream(), System.out,
1234                          child.getErrorStream(), System.err);
1235                     try (MarshalOutputStream out = 
1236                             new MarshalOutputStream(child.getOutputStream())) {

1237                         out.writeObject(id);
1238                         out.writeObject(desc);
1239                         out.writeLong(incarnation);
1240                         out.flush();
1241                     }
1242 
1243 
1244                 } catch (IOException e) {
1245                     terminate();
1246                     throw new ActivationException(
1247                         "unable to create activation group", e);
1248                 }
1249 
1250                 try {
1251                     long now = System.currentTimeMillis();
1252                     long stop = now + execTimeout;
1253                     do {
1254                         wait(stop - now);
1255                         if (group != null) {
1256                             return group;
1257                         }
1258                         now = System.currentTimeMillis();
1259                     } while (status == CREATING && now < stop);
1260                 } catch (InterruptedException e) {
1261                 }


1338                 shouldQuit = true;
1339                 if (canInterrupt) {
1340                     interrupt();
1341                 }
1342             }
1343 
1344             /**
1345              * Marks this thread as no longer needing to restart objects.
1346              */
1347             void noRestart() {
1348                 shouldRestart = false;
1349             }
1350         }
1351     }
1352 
1353     private String[] activationArgs(ActivationGroupDesc desc) {
1354         ActivationGroupDesc.CommandEnvironment cmdenv;
1355         cmdenv = desc.getCommandEnvironment();
1356 
1357         // argv is the literal command to exec
1358         List<String> argv = new ArrayList<>();
1359 
1360         // Command name/path
1361         argv.add((cmdenv != null && cmdenv.getCommandPath() != null)
1362                     ? cmdenv.getCommandPath()
1363                     : command[0]);
1364 
1365         // Group-specific command options
1366         if (cmdenv != null && cmdenv.getCommandOptions() != null) {
1367             argv.addAll(Arrays.asList(cmdenv.getCommandOptions()));
1368         }
1369 
1370         // Properties become -D parameters
1371         Properties props = desc.getPropertyOverrides();
1372         if (props != null) {
1373             for (Enumeration<?> p = props.propertyNames();
1374                  p.hasMoreElements();)
1375             {
1376                 String name = (String) p.nextElement();
1377                 /* Note on quoting: it would be wrong
1378                  * here, since argv will be passed to


1943                                 File.createTempFile("rmid-err", null, null);
1944                             PrintStream errStream =
1945                                 new PrintStream(new FileOutputStream(file));
1946                             System.setErr(errStream);
1947                             return null;
1948                         }
1949                     });
1950 
1951                 ServerSocket serverSocket =
1952                     ((ServerSocketChannel) inheritedChannel).socket();
1953                 port = serverSocket.getLocalPort();
1954                 ssf = new ActivationServerSocketFactory(serverSocket);
1955 
1956                 System.err.println(new Date());
1957                 System.err.println(getTextResource(
1958                                        "rmid.inherited.channel.info") +
1959                                        ": " + inheritedChannel);
1960             }
1961 
1962             String log = null;
1963             List<String> childArgs = new ArrayList<>();
1964 
1965             /*
1966              * Parse arguments
1967              */
1968             for (int i = 0; i < args.length; i++) {
1969                 if (args[i].equals("-port")) {
1970                     if (ssf != null) {
1971                         bomb(getTextResource("rmid.syntax.port.badarg"));
1972                     }
1973                     if ((i + 1) < args.length) {
1974                         try {
1975                             port = Integer.parseInt(args[++i]);
1976                         } catch (NumberFormatException nfe) {
1977                             bomb(getTextResource("rmid.syntax.port.badnumber"));
1978                         }
1979                     } else {
1980                         bomb(getTextResource("rmid.syntax.port.missing"));
1981                     }
1982 
1983                 } else if (args[i].equals("-log")) {


2017             String execPolicyClassName = AccessController.doPrivileged(
2018                 new GetPropertyAction("sun.rmi.activation.execPolicy", null));
2019             if (execPolicyClassName == null) {
2020                 if (!stop) {
2021                     DefaultExecPolicy.checkConfiguration();
2022                 }
2023                 execPolicyClassName = "default";
2024             }
2025 
2026             /**
2027              * Initialize method for activation exec policy.
2028              */
2029             if (!execPolicyClassName.equals("none")) {
2030                 if (execPolicyClassName.equals("") ||
2031                     execPolicyClassName.equals("default"))
2032                 {
2033                     execPolicyClassName = DefaultExecPolicy.class.getName();
2034                 }
2035 
2036                 try {
2037                     Class<?> execPolicyClass = getRMIClass(execPolicyClassName);
2038                         
2039                     execPolicy = execPolicyClass.newInstance();
2040                     execPolicyMethod =
2041                         execPolicyClass.getMethod("checkExecCommand",
2042                                                   ActivationGroupDesc.class,
2043                                                   String[].class);
2044                 } catch (Exception e) {
2045                     if (debugExec) {
2046                         System.err.println(
2047                             getTextResource("rmid.exec.policy.exception"));
2048                         e.printStackTrace();
2049                     }
2050                     bomb(getTextResource("rmid.exec.policy.invalid"));
2051                 }
2052             }
2053 
2054             if (stop == true) {
2055                 final int finalPort = port;
2056                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
2057                     public Void run() {
2058                         System.setProperty("java.rmi.activation.port",


2109             }
2110             if (Activation.resources == null) {
2111                 // throwing an Error is a bit extreme, methinks
2112                 return ("[missing resource file: " + key + "]");
2113             }
2114         }
2115 
2116         String val = null;
2117         try {
2118             val = Activation.resources.getString (key);
2119         } catch (MissingResourceException mre) {
2120         }
2121 
2122         if (val == null) {
2123             return ("[missing resource: " + key + "]");
2124         } else {
2125             return val;
2126         }
2127     }
2128 
2129     @SuppressWarnings("deprecation")
2130     private static Class<?> getRMIClass(String execPolicyClassName) throws Exception  {
2131         return RMIClassLoader.loadClass(execPolicyClassName);
2132     }
2133     /*
2134      * Dijkstra semaphore operations to limit the number of subprocesses
2135      * rmid attempts to make at once.
2136      */
2137     /**
2138      * Acquire the group semaphore and return a group name.  Each
2139      * Pstartgroup must be followed by a Vstartgroup.  The calling thread
2140      * will wait until there are fewer than <code>N</code> other threads
2141      * holding the group semaphore.  The calling thread will then acquire
2142      * the semaphore and return.
2143      */
2144     private synchronized String Pstartgroup() throws ActivationException {
2145         while (true) {
2146             checkShutdown();
2147             // Wait until positive, then decrement.
2148             if (groupSemaphore > 0) {
2149                 groupSemaphore--;
2150                 return "Group-" + groupCounter++;
2151             }
2152