You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2014/05/09 09:03:19 UTC
svn commit: r1593493 [17/24] - in /river/jtsk/skunk/qa_refactor/trunk: qa/
qa/src/com/sun/jini/test/impl/end2end/jssewrapper/
qa/src/com/sun/jini/test/impl/joinmanager/
qa/src/com/sun/jini/test/impl/mahalo/
qa/src/com/sun/jini/test/impl/outrigger/match...
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedActivatableServiceDescriptor.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedActivatableServiceDescriptor.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedActivatableServiceDescriptor.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedActivatableServiceDescriptor.java Fri May 9 07:03:18 2014
@@ -1,726 +1,726 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.sun.jini.start;
-
-import com.sun.jini.config.Config;
-
-import net.jini.config.Configuration;
-import net.jini.security.BasicProxyPreparer;
-import net.jini.security.ProxyPreparer;
-
-import java.io.InvalidObjectException;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamException;
-import java.rmi.activation.ActivationException;
-import java.rmi.activation.ActivationGroupID;
-import java.rmi.activation.ActivationID;
-import java.rmi.activation.ActivationSystem;
-import java.rmi.MarshalledObject;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.jini.io.MarshalledInstance;
-
-/**
- * Class used to launch shared, activatable services.
- * Clients construct this object with the details
- * of the service to be launched, then call
- * {@link #create(net.jini.config.Configuration) create(Configuration config) }
- * to launch the service in an existing
- * {@linkplain SharedActivationGroupDescriptor shared activation group}
- * identified by the <code>sharedGroupLog</code> constructor parameter.
- * <P>
- * This class depends on {@link ActivateWrapper} to provide
- * separation of the import codebase
- * (where the service implementation classes are loaded from)
- * from the export codebase
- * (where service clients should load classes from, for example stubs)
- * as well as providing an independent security policy file for each
- * service object. This functionality allows multiple service objects
- * to be placed in the same activation system group, with each object
- * maintaining distinct export codebase and security policy settings.
- * <P>
- * Services need to implement the "activatable"
- * <A HREF="ActivateWrapper.html#serviceConstructor">constructor</A>
- * required by {@link ActivateWrapper}.
- * <P>
- * <A NAME="serviceProxy"></A>
- * A service implementation
- * can return its service proxy (via the <code>proxy</code> field of the
- * {@link Created Created} object returned
- * by {@link #create(net.jini.config.Configuration) create})
- * in the following ways:
- * <DL>
- * <DT><A NAME="innerProxy">Return Inner Proxy</A></DT>
- * <DD><P>
- * The service's inner proxy is the
- * {@link java.rmi.Remote} object returned from
- * {@link java.rmi.activation.ActivationID#activate(boolean)} using
- * {@link ActivateWrapper} to "wrap" and register the desired service
- * with the activation system.
- * A "wrapped" service's inner proxy is returned as follows:
- *
- * <UL>
- * <LI>If the newly created service instance implements {@link
- * net.jini.export.ProxyAccessor}, a proxy is obtained by invoking the {@link
- * net.jini.export.ProxyAccessor#getProxy getProxy} method on that instance. If the
- * obtained proxy is not <code>null</code>, that proxy is returned in a
- * {@link java.rmi.MarshalledObject}; otherwise, an
- * {@link java.io.InvalidObjectException} is thrown.
- *
- * <LI>If the newly created instance does not implement
- * {@link net.jini.export.ProxyAccessor}, the instance is returned in a
- * {@link java.rmi.MarshalledObject}. In this case, the instance must be
- * serializable, and marshalling the instance must produce a suitable
- * proxy for the remote object (for example, the object implements
- * {@link java.io.Serializable} and defines a <code>writeReplace</code>
- * method that returns the object's proxy).
- * </UL>
- *
- * <P></DD>
- * <DT><A NAME="outerProxy">Return Outer Proxy</A></DT>
- * <DD><P>
- * The service's outer proxy is the object returned from invoking
- * {@link ServiceProxyAccessor#getServiceProxy()} on
- * the service's <A HREF="#innerProxy">inner proxy</A>.
- * <P></DD>
- * </DL>
- *
- * The following items are discussed below:
- * <ul>
- * <li><a href="#configEntries">Configuring SharedActivatableServiceDescriptor</a>
- * <li><a href="#logging">Logging</a>
- * </ul>
- *
- * <a name="configEntries">
- * <h3>Configuring SharedActivatableServiceDescriptor</h3>
- * </a>
- *
- * <code>SharedActivatableServiceDescriptor</code>
- * depends on {@link ActivateWrapper}, which can itself be configured. See
- * {@linkplain ActivateWrapper}'s
- * <A HREF="ActivateWrapper.html#configEntries">configuration</A>
- * information for details.
- *<p>
- * This implementation obtains its configuration entries from the
- * {@link net.jini.config.Configuration Configuration} object passed into
- * the {@link #create(net.jini.config.Configuration) create} method.
- * The following configuration entries use the
- * component prefix "<code>com.sun.jini.start</code>":
- * <p>
- *
- * <table summary="Describes the activationIdPreparer configuration entry"
- * border="0" cellpadding="2">
- * <tr valign="top">
- * <th scope="col" summary="layout"> <font size="+1">•</font>
- * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- * activationIdPreparer</code></font>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Type: <td> {@link net.jini.security.ProxyPreparer}
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Default: <td> <code>
- * new {@link net.jini.security.BasicProxyPreparer}()
- * </code>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Description: <td> The proxy preparer for the service's activation
- * ID. The value should not be <code>null</code>.
- *
- * This class calls the
- * {@link java.rmi.activation.ActivationID#activate
- * activate} method on instances of {@link
- * java.rmi.activation.ActivationID} when they need to re/activate the
- * service.
- * </table>
- *
- * <table summary="Describes the activationSystemPreparer configuration
- * entry"
- * border="0" cellpadding="2">
- * <tr valign="top">
- * <th scope="col" summary="layout"> <font size="+1">•</font>
- * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- * activationSystemPreparer</code></font>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Type: <td> {@link net.jini.security.ProxyPreparer}
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Default: <td> <code>
- * new {@link net.jini.security.BasicProxyPreparer}()</code>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Description: <td> The proxy preparer for the proxy for the
- * activation system. The value should not be <code>null</code>.
- *
- * The service starter calls the {@link
- * java.rmi.activation.ActivationSystem#unregisterObject
- * unregisterObject} method on the {@link
- * java.rmi.activation.ActivationSystem} when there is a problem
- * creating a service.
- * </table>
- *
- * <a name="servicePreparer">
- * <table summary="Describes the default service preparer configuration entry"
- * border="0" cellpadding="2">
- * <tr valign="top">
- * <th scope="col" summary="layout"> <font size="+1">•</font>
- * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- * servicePreparer</code></font>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Type: <td> {@link net.jini.security.ProxyPreparer}
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Default: <td> <code>
- * new {@link net.jini.security.BasicProxyPreparer}()
- * </code>
- * <tr valign="top"> <td>   <th scope="row" align="right">
- * Description: <td> The default proxy preparer used to prepare
- * service proxies.
- * This value should not be <code>null</code>. This entry is
- * obtained during the invocation of
- * {@link #create(net.jini.config.Configuration) create} and is used,
- * to prepare the <A HREF="#innerProxy">inner</A> and
- * <A HREF="#outerProxy">outer</A> service proxies returned by
- * the service implementation
- * (see <a href="#serviceProxy">service proxy</a> section for details).
- * This entry is superseded by explicitly passing a
- * {@link ProxyPreparer ProxyPreparer} to one of the constructors that
- * accept a {@linkplain ProxyPreparer proxy preparer} argument.
- * </table>
- *
- *<a name="logging">
- *<h3>Loggers and Logging Levels</h3>
- *</a>
- *
- * The implementation uses the {@link
- * java.util.logging.Logger}, named
- * <code>com.sun.jini.start.service.starter</code>.
- * The following table describes the
- * type of information logged as well as the levels of information logged.
- * <p>
- *
- * <table border="1" cellpadding="5"
- * summary="Describes logging performed by the shared,
- * activatable service descriptor at different
- * logging levels">
- *
- * <caption halign="center" valign="top"><b><code>
- * com.sun.jini.start.service.starter</code></b></caption>
- *
- * <tr> <th scope="col"> Level <th scope="col"> Description
- *
- * <tr> <td> {@link java.util.logging.Level#FINER FINER} <td>
- * for high level
- * service operation tracing
- * <tr> <td> {@link java.util.logging.Level#FINEST FINEST} <td>
- * for low level
- * service operation tracing
- *
- * </table> <p>
- *
- * @author Sun Microsystems, Inc.
- * @since 2.0
- *
- */
-
-public class SharedActivatableServiceDescriptor
- extends NonActivatableServiceDescriptor
-{
- private static final long serialVersionUID = 1L;
-
- /**
- * @serial <code>String</code> representing the directory where
- * the associated shared group identifier information is persisted
- */
- private final String sharedGroupLog;
-
- /**
- * @serial <code>boolean</code> flag passed through as the
- * <code>restart</code> parameter to the
- * {@linkplain java.rmi.activation.ActivationDesc#ActivationDesc(java.rmi.activation.ActivationGroupID, java.lang.String, java.lang.String, java.rmi.MarshalledObject, boolean)
- * ActivationDesc constructor} used to register the service with the
- * activation system.
- */
- private final boolean restart;
-
- /**
- * @serial <code>String</code> containing hostname of desired
- * activation system.
- */
- private final String host;
-
- /**
- * @serial <code>int</code> representing port of desired activation system.
- */
- private final int port;
-
- private static final Logger logger = ServiceStarter.logger;
-
- /*
- * <code>ProxyPreparer</code> reference for preparing the service's proxy
- * returned from the call to
- * {@linkplain java.rmi.activation.ActivationID#activate(boolean) activate}.
- * If this "inner" proxy implements
- * {@linkplain ServiceProxyAccessor ServiceProxyAccessor} it will then be used to invoke
- * {@linkplain ServiceProxyAccessor#getServiceProxy() getServiceProxy}.
- */
- private /*final*/ transient ProxyPreparer innerProxyPreparer;
-
- /**
- * Object returned by
- * {@link SharedActivatableServiceDescriptor#create(net.jini.config.Configuration)
- * SharedActivatableServiceDescriptor.create()}
- * method that returns the associated proxy, activation group
- * identifier, and activation identifier
- * for the created service.
- */
- public static class Created {
- /** The activation group id of the group hosting the service */
- public final ActivationGroupID gid;
- /** The activation id of the service */
- public final ActivationID aid;
- /** The reference to the proxy of the created service */
- public final Object proxy;
- /** Constructs an instance of this class.
- * @param gid activation group id of the created service
- * @param aid activation id of the created service
- * @param proxy reference to the proxy of the created service
- */
- public Created(ActivationGroupID gid, ActivationID aid, Object proxy) {
- this.gid = gid;
- this.aid = aid;
- this.proxy = proxy;
- }//end constructor
- }//end class Created
-
-
- /**
- * Convenience constructor. Equivalent to calling this
- * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
- * with the <code>innerProxyPreparer</code>, <code>outerProxyPreparer</code>
- * and <code>host</code> arguments set to
- * <code>null</code>
- * and the <code>port</code> argument set to
- * the currently configured activation system port.
- * The activation system port defaults to
- * {@link ActivationSystem#SYSTEM_PORT} unless it is overridden by the
- * <code>java.rmi.activation.port</code> system property.
- *
- */
- public SharedActivatableServiceDescriptor(
- // Required Args
- String exportCodebase,
- String policy,
- String importCodebase,
- String implClassName,
- String sharedGroupLog,
- // Optional Args,
- String[] serverConfigArgs,
- boolean restart)
- {
- this(exportCodebase, policy, importCodebase, implClassName,
- sharedGroupLog, serverConfigArgs, null,
- null, restart, null, ServiceStarter.getActivationSystemPort());
- }
-
- /**
- * Convenience constructor. Equivalent to calling this
- * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
- * with the <code>host</code> argument set to
- * <code>null</code> and the <code>port</code> argument set to the
- * currently configured activation system port.
- * The activation system port defaults to
- * {@link ActivationSystem#SYSTEM_PORT} unless it is overridden by the
- * <code>java.rmi.activation.port</code> system property.
- *
- */
- public SharedActivatableServiceDescriptor(
- // Required Args
- String exportCodebase,
- String policy,
- String importCodebase,
- String implClassName,
- String sharedGroupLog,
- // Optional Args,
- String[] serverConfigArgs,
- ProxyPreparer innerProxyPreparer,
- ProxyPreparer outerProxyPreparer,
- boolean restart)
- {
- this(exportCodebase, policy, importCodebase, implClassName,
- sharedGroupLog, serverConfigArgs, innerProxyPreparer,
- outerProxyPreparer, restart, null, ServiceStarter.getActivationSystemPort());
- }
-
- /**
- * Convenience constructor. Equivalent to calling this
- * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
- * with the <code>innerProxyPreparer</code> and <code>outerProxyPreparer</code> arguments set to
- * <code>null</code>.
- */
- public SharedActivatableServiceDescriptor(
- // Required Args
- String exportCodebase,
- String policy,
- String importCodebase,
- String implClassName,
- String sharedGroupLog,
- // Optional Args,
- String[] serverConfigArgs,
- boolean restart,
- String host,
- int port)
- {
- this(exportCodebase, policy, importCodebase, implClassName,
- sharedGroupLog, serverConfigArgs, null, null, restart,
- host, port);
- }
-
- /**
- * Main constructor. Simply assigns given parameters to
- * their associated, internal fields unless otherwise noted.
- *
- * @param exportCodebase location where clients can download required
- * service-related classes (for example, stubs, proxies, etc.).
- * Codebase components must be separated by spaces in which
- * each component is in <code>URL</code> format.
- * @param policy server policy filename or URL
- * @param importCodebase location where server implementation
- * classes can be found.
- * This <code>String</code> assumed (in order) to be either
- * 1) a space delimited set of <code>URL</code>(s)
- * representing a codebase or
- * 2) a <code>File.pathSeparator</code> delimited set
- * of class paths.
- * @param implClassName name of server implementation class
- * @param sharedGroupLog location where the associated shared
- * group identifier information is persisted
- * @param serverConfigArgs service configuration arguments
- * @param innerProxyPreparer <code>ProxyPreparer</code> reference. This object
- * will be used to prepare the service's <A HREF="#innerProxy">inner proxy</A>.
- * If the inner proxy implements
- * {@link ServiceProxyAccessor}
- * it will then be used to invoke
- * {@link ServiceProxyAccessor#getServiceProxy()} in order to get the
- * service's <A HREF="#outerProxy">outer proxy</A>.
- * @param outerProxyPreparer <code>ProxyPreparer</code> reference. This object
- * will be used to prepare the service's
- * <A HREF="#outerProxy">outer proxy</A> before it is returned to the caller of
- * {@link SharedActivatableServiceDescriptor#create(net.jini.config.Configuration)}.
- * @param restart boolean flag passed through as the
- * <code>restart</code> parameter to the
- * {@linkplain java.rmi.activation.ActivationDesc#ActivationDesc(java.rmi.activation.ActivationGroupID, java.lang.String, java.lang.String, java.rmi.MarshalledObject, boolean)
- * ActivationDesc constructor} used to register the service with the
- * activation system.
- * @param host hostname of desired activation system. If <code>null</code>,
- * defaults to the localhost.
- * @param port port of desired activation system. If value is <= 0, then
- * defaults to
- * {@link java.rmi.activation.ActivationSystem#SYSTEM_PORT
- * ActivationSystem.SYSTEM_PORT}.
- */
- public SharedActivatableServiceDescriptor(
- // Required Args
- String exportCodebase,
- String policy,
- String importCodebase,
- String implClassName,
- String sharedGroupLog,
- // Optional Args,
- String[] serverConfigArgs,
- ProxyPreparer innerProxyPreparer,
- ProxyPreparer outerProxyPreparer,
- boolean restart,
- String host,
- int port)
- {
- super(exportCodebase, policy, importCodebase, implClassName,
- serverConfigArgs, outerProxyPreparer);
- if ( sharedGroupLog == null)
- throw new NullPointerException(
- "Shared VM log cannot be null");
- this.sharedGroupLog = sharedGroupLog;
- this.restart = restart;
- this.host = (host == null) ? "" : host;
- this.port =
- (port <= 0) ? ServiceStarter.getActivationSystemPort() : port;
- this.innerProxyPreparer = innerProxyPreparer;
- }
-
- /**
- * Shared group log accessor method.
- *
- * @return the Shared group log associated with this service descriptor.
- */
- final public String getSharedGroupLog() { return sharedGroupLog; }
-
- /**
- * Restart accessor method.
- *
- * @return the restart mode associated with this service descriptor.
- */
- final public boolean getRestart() { return restart; }
-
- /**
- * Activation system host accessor method.
- *
- * @return the activation system host associated with
- * this service descriptor.
- */
- final public String getActivationSystemHost() { return host; }
-
- /**
- * Activation system port accessor method.
- *
- * @return the activation system port associated with this service descriptor.
- */
- final public int getActivationSystemPort() { return port; }
-
- /**
- * <code>ProxyPreparer</code> accessor method.
- *
- * @return the <A HREF="#innerProxy">inner proxy</A> preparer associated with
- * this service descriptor.
- */
- final public ProxyPreparer getInnerProxyPreparer() {
- synchronized (descCreatedLock){
- return innerProxyPreparer;
- }
- }
-
- /**
- * Sets the <A HREF="#innerProxy">inner</A>
- * <code>ProxyPreparer</code> for this descriptor.
- * This needs to
- * be called on the service descriptor prior to calling
- * <code>create()</code>. Useful for (re-)setting the
- * the associated inner <code>ProxyPreparer</code> upon deserialization of
- * the descriptor.
- *
- * @param pp The inner <code>ProxyPreparer</code> object to be
- * associated with this service descriptor.
- *
- * @throws IllegalStateException if called after <code>create()</code> is invoked
- */
- final public void setInnerProxyPreparer(ProxyPreparer pp) {
- synchronized (descCreatedLock) {
- if (descCreated) {
- throw new IllegalStateException("Can't set ProxyPreparer after descriptor creation");
- } else {
- innerProxyPreparer = pp;
- }
- }
- }
-
- /**
- * Method that attempts to create a service based on the service
- * description information provided via constructor parameters.
- * <P>
- * This method:
- * <UL>
- * <LI> creates an <code>ActivateWrapper.ActivateDesc</code> with
- * the provided constructor parameter information for the
- * desired service
- * <LI> retrieves the
- * {@linkplain java.rmi.activation.ActivationGroupID group identifier}
- * associated with the provided shared group log.
- * <LI> invokes
- * {@link ActivateWrapper#register(java.rmi.activation.ActivationGroupID, com.sun.jini.start.ActivateWrapper.ActivateDesc, boolean, java.rmi.activation.ActivationSystem)
- * ActivateWrapper.register()} with the provided information.
- * <LI> obtains an <A HREF="#innerProxy">inner proxy</A> by calling
- * {@link java.rmi.activation.ActivationID#activate(boolean)
- * activate(true)} on the object returned from
- * <code>ActivateWrapper.register()</code>, which also
- * activates the service instance.
- * <LI> obtains the service proxy in the following
- * order of precedence:
- * <UL>
- * <LI>if the <A HREF="#innerProxy">inner proxy</A> implements
- * {@link ServiceProxyAccessor} then the return value of
- * {@link ServiceProxyAccessor#getServiceProxy() getServiceProxy}
- * is used
- * <LI>if the <A HREF="#innerProxy">inner proxy</A> is
- * not <code>null</code> then it is used
- * <LI>Otherwise, <code>null</code> is used
- * </UL>
- *
- * @return a
- * {@link com.sun.jini.start.SharedActivatableServiceDescriptor.Created
- * Created} object that contains the group identifier, activation ID, and
- * proxy associated with the newly created service instance.
- * @throws java.lang.Exception Thrown if there was any problem
- * creating the object.
- *
- */
- public Object create(Configuration config) throws Exception {
- ServiceStarter.ensureSecurityManager();
- logger.entering(SharedActivatableServiceDescriptor.class.getName(),
- "create", new Object[] {config});
-
- if (config == null) {
- throw new NullPointerException(
- "Configuration argument cannot be null");
- }
-
- ProxyPreparer globalServicePreparer =
- (ProxyPreparer) Config.getNonNullEntry(config,
- ServiceStarter.START_PACKAGE,
- "servicePreparer", ProxyPreparer.class,
- new BasicProxyPreparer());
-
- // Needs to be called prior to setting the "descCreated" flag
- if (getServicePreparer() == null) {
- setServicePreparer(globalServicePreparer);
- }
-
- synchronized (descCreatedLock) {
- descCreated = true;
- }
-
- // Get prepared activation system reference
- Created created = null;
- ActivationSystem sys =
- ServiceStarter.getActivationSystem(
- getActivationSystemHost(),
- getActivationSystemPort(),
- config);
- ProxyPreparer activationIDPreparer =
- (ProxyPreparer) Config.getNonNullEntry(config,
- ServiceStarter.START_PACKAGE, "activationIdPreparer",
- ProxyPreparer.class, new BasicProxyPreparer());
- synchronized (descCreatedLock){
- if (innerProxyPreparer == null) {
- innerProxyPreparer = globalServicePreparer;
- }
- }
-
- /* Warn user of inaccessible codebase(s) */
- HTTPDStatus.httpdWarning(getExportCodebase());
-
- ActivationGroupID gid = null;
- ActivationID aid = null;
- Object proxy = null;
- try {
- /* Create the ActivateWrapper descriptor for the desired service */
- MarshalledObject params =
- new MarshalledInstance(getServerConfigArgs()).convertToMarshalledObject();
- ActivateWrapper.ActivateDesc adesc =
- new ActivateWrapper.ActivateDesc(
- getImplClassName(),
- ClassLoaderUtil.getImportCodebaseURLs(getImportCodebase()),
- ClassLoaderUtil.getCodebaseURLs(getExportCodebase()),
- getPolicy(),
- params);
- logger.finest("ActivateDesc: " + adesc);
- // Get hosting activation group
- gid = SharedActivationGroupDescriptor.restoreGroupID(
- getSharedGroupLog());
-
- /* Register the desired service with the activation system */
- aid = ActivateWrapper.register(
- gid, adesc, getRestart(), sys);
- aid = (ActivationID) activationIDPreparer.prepareProxy(aid);
-
- proxy = aid.activate(true);
-
- if(proxy != null) {
- synchronized (descCreatedLock){
- proxy = innerProxyPreparer.prepareProxy(proxy);
- }
- if (proxy instanceof ServiceProxyAccessor) {
- proxy = ((ServiceProxyAccessor)proxy).getServiceProxy();
- if(proxy != null) {
- proxy = getServicePreparer().prepareProxy(proxy);
- } else {
- logger.log(Level.FINE,
- "Service's getServiceProxy() returned null");
- }
- }
- }//endif
- } catch(Exception e) {
- try {
- if (aid != null) sys.unregisterObject(aid);
- } catch (Exception ee) {
- // ignore -- did the best we could.
- logger.log(Level.FINEST,
- "Unable to unregister with activation system", ee);
- }
- if (e instanceof IOException)
- throw (IOException)e;
- else if (e instanceof ActivationException)
- throw (ActivationException)e;
- else if (e instanceof ClassNotFoundException)
- throw (ClassNotFoundException)e;
- else
- throw new RuntimeException("Unexpected Exception", e);
- }
- created = new Created(gid, aid, proxy);
- logger.exiting(SharedActivatableServiceDescriptor.class.getName(),
- "create", created);
- return created;
- }
-
- public String toString() {
- // Would like to call super(), but need different formatting
- ArrayList fields = new ArrayList(12);
- fields.add(getExportCodebase());
- fields.add(getPolicy());
- fields.add(getImportCodebase());
- fields.add(getImplClassName());
- fields.add(
- ((getServerConfigArgs() == null)
- ? null : Arrays.asList(getServerConfigArgs())));
- fields.add(getLifeCycle());
- fields.add(getServicePreparer());
- fields.add(getInnerProxyPreparer());
- fields.add(sharedGroupLog);
- fields.add(Boolean.valueOf(restart));
- fields.add(host);
- fields.add(Integer.valueOf(port));
- return fields.toString();
- }
-
- /**
- * Reads the default serializable field values for this object.
- * Also, verifies that the deserialized values are legal.
- */
- private void readObject(ObjectInputStream in)
- throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- // Verify serialized fields
- if (sharedGroupLog == null) {
- throw new InvalidObjectException("null shared group log");
- }
- if (host == null) {
- throw new InvalidObjectException("null activation host name");
- }
- if (port <= 0) {
- throw new InvalidObjectException("invalid activation port value: " + port);
- }
-
- //Reinitialize transient fields upon de-serialization.
- innerProxyPreparer = null;
- }
-
- /**
- * Throws InvalidObjectException, since data for this class is required.
- */
- private void readObjectNoData() throws ObjectStreamException {
- throw new InvalidObjectException("no data");
- }
-}
-
-
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.jini.start;
+
+import com.sun.jini.config.Config;
+
+import net.jini.config.Configuration;
+import net.jini.security.BasicProxyPreparer;
+import net.jini.security.ProxyPreparer;
+
+import java.io.InvalidObjectException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationGroupID;
+import java.rmi.activation.ActivationID;
+import java.rmi.activation.ActivationSystem;
+import java.rmi.MarshalledObject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.io.MarshalledInstance;
+
+/**
+ * Class used to launch shared, activatable services.
+ * Clients construct this object with the details
+ * of the service to be launched, then call
+ * {@link #create(net.jini.config.Configuration) create(Configuration config) }
+ * to launch the service in an existing
+ * {@linkplain SharedActivationGroupDescriptor shared activation group}
+ * identified by the <code>sharedGroupLog</code> constructor parameter.
+ * <P>
+ * This class depends on {@link ActivateWrapper} to provide
+ * separation of the import codebase
+ * (where the service implementation classes are loaded from)
+ * from the export codebase
+ * (where service clients should load classes from, for example stubs)
+ * as well as providing an independent security policy file for each
+ * service object. This functionality allows multiple service objects
+ * to be placed in the same activation system group, with each object
+ * maintaining distinct export codebase and security policy settings.
+ * <P>
+ * Services need to implement the "activatable"
+ * <A HREF="ActivateWrapper.html#serviceConstructor">constructor</A>
+ * required by {@link ActivateWrapper}.
+ * <P>
+ * <A NAME="serviceProxy"></A>
+ * A service implementation
+ * can return its service proxy (via the <code>proxy</code> field of the
+ * {@link Created Created} object returned
+ * by {@link #create(net.jini.config.Configuration) create})
+ * in the following ways:
+ * <DL>
+ * <DT><A NAME="innerProxy">Return Inner Proxy</A></DT>
+ * <DD><P>
+ * The service's inner proxy is the
+ * {@link java.rmi.Remote} object returned from
+ * {@link java.rmi.activation.ActivationID#activate(boolean)} using
+ * {@link ActivateWrapper} to "wrap" and register the desired service
+ * with the activation system.
+ * A "wrapped" service's inner proxy is returned as follows:
+ *
+ * <UL>
+ * <LI>If the newly created service instance implements {@link
+ * net.jini.export.ProxyAccessor}, a proxy is obtained by invoking the {@link
+ * net.jini.export.ProxyAccessor#getProxy getProxy} method on that instance. If the
+ * obtained proxy is not <code>null</code>, that proxy is returned in a
+ * {@link java.rmi.MarshalledObject}; otherwise, an
+ * {@link java.io.InvalidObjectException} is thrown.
+ *
+ * <LI>If the newly created instance does not implement
+ * {@link net.jini.export.ProxyAccessor}, the instance is returned in a
+ * {@link java.rmi.MarshalledObject}. In this case, the instance must be
+ * serializable, and marshalling the instance must produce a suitable
+ * proxy for the remote object (for example, the object implements
+ * {@link java.io.Serializable} and defines a <code>writeReplace</code>
+ * method that returns the object's proxy).
+ * </UL>
+ *
+ * <P></DD>
+ * <DT><A NAME="outerProxy">Return Outer Proxy</A></DT>
+ * <DD><P>
+ * The service's outer proxy is the object returned from invoking
+ * {@link ServiceProxyAccessor#getServiceProxy()} on
+ * the service's <A HREF="#innerProxy">inner proxy</A>.
+ * <P></DD>
+ * </DL>
+ *
+ * The following items are discussed below:
+ * <ul>
+ * <li><a href="#configEntries">Configuring SharedActivatableServiceDescriptor</a>
+ * <li><a href="#logging">Logging</a>
+ * </ul>
+ *
+ * <a name="configEntries">
+ * <h3>Configuring SharedActivatableServiceDescriptor</h3>
+ * </a>
+ *
+ * <code>SharedActivatableServiceDescriptor</code>
+ * depends on {@link ActivateWrapper}, which can itself be configured. See
+ * {@linkplain ActivateWrapper}'s
+ * <A HREF="ActivateWrapper.html#configEntries">configuration</A>
+ * information for details.
+ *<p>
+ * This implementation obtains its configuration entries from the
+ * {@link net.jini.config.Configuration Configuration} object passed into
+ * the {@link #create(net.jini.config.Configuration) create} method.
+ * The following configuration entries use the
+ * component prefix "<code>com.sun.jini.start</code>":
+ * <p>
+ *
+ * <table summary="Describes the activationIdPreparer configuration entry"
+ * border="0" cellpadding="2">
+ * <tr valign="top">
+ * <th scope="col" summary="layout"> <font size="+1">•</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * activationIdPreparer</code></font>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Type: <td> {@link net.jini.security.ProxyPreparer}
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Default: <td> <code>
+ * new {@link net.jini.security.BasicProxyPreparer}()
+ * </code>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Description: <td> The proxy preparer for the service's activation
+ * ID. The value should not be <code>null</code>.
+ *
+ * This class calls the
+ * {@link java.rmi.activation.ActivationID#activate
+ * activate} method on instances of {@link
+ * java.rmi.activation.ActivationID} when they need to re/activate the
+ * service.
+ * </table>
+ *
+ * <table summary="Describes the activationSystemPreparer configuration
+ * entry"
+ * border="0" cellpadding="2">
+ * <tr valign="top">
+ * <th scope="col" summary="layout"> <font size="+1">•</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * activationSystemPreparer</code></font>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Type: <td> {@link net.jini.security.ProxyPreparer}
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Default: <td> <code>
+ * new {@link net.jini.security.BasicProxyPreparer}()</code>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Description: <td> The proxy preparer for the proxy for the
+ * activation system. The value should not be <code>null</code>.
+ *
+ * The service starter calls the {@link
+ * java.rmi.activation.ActivationSystem#unregisterObject
+ * unregisterObject} method on the {@link
+ * java.rmi.activation.ActivationSystem} when there is a problem
+ * creating a service.
+ * </table>
+ *
+ * <a name="servicePreparer">
+ * <table summary="Describes the default service preparer configuration entry"
+ * border="0" cellpadding="2">
+ * <tr valign="top">
+ * <th scope="col" summary="layout"> <font size="+1">•</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * servicePreparer</code></font>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Type: <td> {@link net.jini.security.ProxyPreparer}
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Default: <td> <code>
+ * new {@link net.jini.security.BasicProxyPreparer}()
+ * </code>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Description: <td> The default proxy preparer used to prepare
+ * service proxies.
+ * This value should not be <code>null</code>. This entry is
+ * obtained during the invocation of
+ * {@link #create(net.jini.config.Configuration) create} and is used,
+ * to prepare the <A HREF="#innerProxy">inner</A> and
+ * <A HREF="#outerProxy">outer</A> service proxies returned by
+ * the service implementation
+ * (see <a href="#serviceProxy">service proxy</a> section for details).
+ * This entry is superseded by explicitly passing a
+ * {@link ProxyPreparer ProxyPreparer} to one of the constructors that
+ * accept a {@linkplain ProxyPreparer proxy preparer} argument.
+ * </table>
+ *
+ *<a name="logging">
+ *<h3>Loggers and Logging Levels</h3>
+ *</a>
+ *
+ * The implementation uses the {@link
+ * java.util.logging.Logger}, named
+ * <code>com.sun.jini.start.service.starter</code>.
+ * The following table describes the
+ * type of information logged as well as the levels of information logged.
+ * <p>
+ *
+ * <table border="1" cellpadding="5"
+ * summary="Describes logging performed by the shared,
+ * activatable service descriptor at different
+ * logging levels">
+ *
+ * <caption halign="center" valign="top"><b><code>
+ * com.sun.jini.start.service.starter</code></b></caption>
+ *
+ * <tr> <th scope="col"> Level <th scope="col"> Description
+ *
+ * <tr> <td> {@link java.util.logging.Level#FINER FINER} <td>
+ * for high level
+ * service operation tracing
+ * <tr> <td> {@link java.util.logging.Level#FINEST FINEST} <td>
+ * for low level
+ * service operation tracing
+ *
+ * </table> <p>
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ *
+ */
+
+public class SharedActivatableServiceDescriptor
+ extends NonActivatableServiceDescriptor
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @serial <code>String</code> representing the directory where
+ * the associated shared group identifier information is persisted
+ */
+ private final String sharedGroupLog;
+
+ /**
+ * @serial <code>boolean</code> flag passed through as the
+ * <code>restart</code> parameter to the
+ * {@linkplain java.rmi.activation.ActivationDesc#ActivationDesc(java.rmi.activation.ActivationGroupID, java.lang.String, java.lang.String, java.rmi.MarshalledObject, boolean)
+ * ActivationDesc constructor} used to register the service with the
+ * activation system.
+ */
+ private final boolean restart;
+
+ /**
+ * @serial <code>String</code> containing hostname of desired
+ * activation system.
+ */
+ private final String host;
+
+ /**
+ * @serial <code>int</code> representing port of desired activation system.
+ */
+ private final int port;
+
+ private static final Logger logger = ServiceStarter.logger;
+
+ /*
+ * <code>ProxyPreparer</code> reference for preparing the service's proxy
+ * returned from the call to
+ * {@linkplain java.rmi.activation.ActivationID#activate(boolean) activate}.
+ * If this "inner" proxy implements
+ * {@linkplain ServiceProxyAccessor ServiceProxyAccessor} it will then be used to invoke
+ * {@linkplain ServiceProxyAccessor#getServiceProxy() getServiceProxy}.
+ */
+ private /*final*/ transient ProxyPreparer innerProxyPreparer;
+
+ /**
+ * Object returned by
+ * {@link SharedActivatableServiceDescriptor#create(net.jini.config.Configuration)
+ * SharedActivatableServiceDescriptor.create()}
+ * method that returns the associated proxy, activation group
+ * identifier, and activation identifier
+ * for the created service.
+ */
+ public static class Created {
+ /** The activation group id of the group hosting the service */
+ public final ActivationGroupID gid;
+ /** The activation id of the service */
+ public final ActivationID aid;
+ /** The reference to the proxy of the created service */
+ public final Object proxy;
+ /** Constructs an instance of this class.
+ * @param gid activation group id of the created service
+ * @param aid activation id of the created service
+ * @param proxy reference to the proxy of the created service
+ */
+ public Created(ActivationGroupID gid, ActivationID aid, Object proxy) {
+ this.gid = gid;
+ this.aid = aid;
+ this.proxy = proxy;
+ }//end constructor
+ }//end class Created
+
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
+ * with the <code>innerProxyPreparer</code>, <code>outerProxyPreparer</code>
+ * and <code>host</code> arguments set to
+ * <code>null</code>
+ * and the <code>port</code> argument set to
+ * the currently configured activation system port.
+ * The activation system port defaults to
+ * {@link ActivationSystem#SYSTEM_PORT} unless it is overridden by the
+ * <code>java.rmi.activation.port</code> system property.
+ *
+ */
+ public SharedActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ String sharedGroupLog,
+ // Optional Args,
+ String[] serverConfigArgs,
+ boolean restart)
+ {
+ this(exportCodebase, policy, importCodebase, implClassName,
+ sharedGroupLog, serverConfigArgs, null,
+ null, restart, null, ServiceStarter.getActivationSystemPort());
+ }
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
+ * with the <code>host</code> argument set to
+ * <code>null</code> and the <code>port</code> argument set to the
+ * currently configured activation system port.
+ * The activation system port defaults to
+ * {@link ActivationSystem#SYSTEM_PORT} unless it is overridden by the
+ * <code>java.rmi.activation.port</code> system property.
+ *
+ */
+ public SharedActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ String sharedGroupLog,
+ // Optional Args,
+ String[] serverConfigArgs,
+ ProxyPreparer innerProxyPreparer,
+ ProxyPreparer outerProxyPreparer,
+ boolean restart)
+ {
+ this(exportCodebase, policy, importCodebase, implClassName,
+ sharedGroupLog, serverConfigArgs, innerProxyPreparer,
+ outerProxyPreparer, restart, null, ServiceStarter.getActivationSystemPort());
+ }
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #SharedActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], net.jini.security.ProxyPreparer, net.jini.security.ProxyPreparer, boolean, java.lang.String, int) constructor}
+ * with the <code>innerProxyPreparer</code> and <code>outerProxyPreparer</code> arguments set to
+ * <code>null</code>.
+ */
+ public SharedActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ String sharedGroupLog,
+ // Optional Args,
+ String[] serverConfigArgs,
+ boolean restart,
+ String host,
+ int port)
+ {
+ this(exportCodebase, policy, importCodebase, implClassName,
+ sharedGroupLog, serverConfigArgs, null, null, restart,
+ host, port);
+ }
+
+ /**
+ * Main constructor. Simply assigns given parameters to
+ * their associated, internal fields unless otherwise noted.
+ *
+ * @param exportCodebase location where clients can download required
+ * service-related classes (for example, stubs, proxies, etc.).
+ * Codebase components must be separated by spaces in which
+ * each component is in <code>URL</code> format.
+ * @param policy server policy filename or URL
+ * @param importCodebase location where server implementation
+ * classes can be found.
+ * This <code>String</code> assumed (in order) to be either
+ * 1) a space delimited set of <code>URL</code>(s)
+ * representing a codebase or
+ * 2) a <code>File.pathSeparator</code> delimited set
+ * of class paths.
+ * @param implClassName name of server implementation class
+ * @param sharedGroupLog location where the associated shared
+ * group identifier information is persisted
+ * @param serverConfigArgs service configuration arguments
+ * @param innerProxyPreparer <code>ProxyPreparer</code> reference. This object
+ * will be used to prepare the service's <A HREF="#innerProxy">inner proxy</A>.
+ * If the inner proxy implements
+ * {@link ServiceProxyAccessor}
+ * it will then be used to invoke
+ * {@link ServiceProxyAccessor#getServiceProxy()} in order to get the
+ * service's <A HREF="#outerProxy">outer proxy</A>.
+ * @param outerProxyPreparer <code>ProxyPreparer</code> reference. This object
+ * will be used to prepare the service's
+ * <A HREF="#outerProxy">outer proxy</A> before it is returned to the caller of
+ * {@link SharedActivatableServiceDescriptor#create(net.jini.config.Configuration)}.
+ * @param restart boolean flag passed through as the
+ * <code>restart</code> parameter to the
+ * {@linkplain java.rmi.activation.ActivationDesc#ActivationDesc(java.rmi.activation.ActivationGroupID, java.lang.String, java.lang.String, java.rmi.MarshalledObject, boolean)
+ * ActivationDesc constructor} used to register the service with the
+ * activation system.
+ * @param host hostname of desired activation system. If <code>null</code>,
+ * defaults to the localhost.
+ * @param port port of desired activation system. If value is <= 0, then
+ * defaults to
+ * {@link java.rmi.activation.ActivationSystem#SYSTEM_PORT
+ * ActivationSystem.SYSTEM_PORT}.
+ */
+ public SharedActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ String sharedGroupLog,
+ // Optional Args,
+ String[] serverConfigArgs,
+ ProxyPreparer innerProxyPreparer,
+ ProxyPreparer outerProxyPreparer,
+ boolean restart,
+ String host,
+ int port)
+ {
+ super(exportCodebase, policy, importCodebase, implClassName,
+ serverConfigArgs, outerProxyPreparer);
+ if ( sharedGroupLog == null)
+ throw new NullPointerException(
+ "Shared VM log cannot be null");
+ this.sharedGroupLog = sharedGroupLog;
+ this.restart = restart;
+ this.host = (host == null) ? "" : host;
+ this.port =
+ (port <= 0) ? ServiceStarter.getActivationSystemPort() : port;
+ this.innerProxyPreparer = innerProxyPreparer;
+ }
+
+ /**
+ * Shared group log accessor method.
+ *
+ * @return the Shared group log associated with this service descriptor.
+ */
+ final public String getSharedGroupLog() { return sharedGroupLog; }
+
+ /**
+ * Restart accessor method.
+ *
+ * @return the restart mode associated with this service descriptor.
+ */
+ final public boolean getRestart() { return restart; }
+
+ /**
+ * Activation system host accessor method.
+ *
+ * @return the activation system host associated with
+ * this service descriptor.
+ */
+ final public String getActivationSystemHost() { return host; }
+
+ /**
+ * Activation system port accessor method.
+ *
+ * @return the activation system port associated with this service descriptor.
+ */
+ final public int getActivationSystemPort() { return port; }
+
+ /**
+ * <code>ProxyPreparer</code> accessor method.
+ *
+ * @return the <A HREF="#innerProxy">inner proxy</A> preparer associated with
+ * this service descriptor.
+ */
+ final public ProxyPreparer getInnerProxyPreparer() {
+ synchronized (descCreatedLock){
+ return innerProxyPreparer;
+ }
+ }
+
+ /**
+ * Sets the <A HREF="#innerProxy">inner</A>
+ * <code>ProxyPreparer</code> for this descriptor.
+ * This needs to
+ * be called on the service descriptor prior to calling
+ * <code>create()</code>. Useful for (re-)setting the
+ * the associated inner <code>ProxyPreparer</code> upon deserialization of
+ * the descriptor.
+ *
+ * @param pp The inner <code>ProxyPreparer</code> object to be
+ * associated with this service descriptor.
+ *
+ * @throws IllegalStateException if called after <code>create()</code> is invoked
+ */
+ final public void setInnerProxyPreparer(ProxyPreparer pp) {
+ synchronized (descCreatedLock) {
+ if (descCreated) {
+ throw new IllegalStateException("Can't set ProxyPreparer after descriptor creation");
+ } else {
+ innerProxyPreparer = pp;
+ }
+ }
+ }
+
+ /**
+ * Method that attempts to create a service based on the service
+ * description information provided via constructor parameters.
+ * <P>
+ * This method:
+ * <UL>
+ * <LI> creates an <code>ActivateWrapper.ActivateDesc</code> with
+ * the provided constructor parameter information for the
+ * desired service
+ * <LI> retrieves the
+ * {@linkplain java.rmi.activation.ActivationGroupID group identifier}
+ * associated with the provided shared group log.
+ * <LI> invokes
+ * {@link ActivateWrapper#register(java.rmi.activation.ActivationGroupID, com.sun.jini.start.ActivateWrapper.ActivateDesc, boolean, java.rmi.activation.ActivationSystem)
+ * ActivateWrapper.register()} with the provided information.
+ * <LI> obtains an <A HREF="#innerProxy">inner proxy</A> by calling
+ * {@link java.rmi.activation.ActivationID#activate(boolean)
+ * activate(true)} on the object returned from
+ * <code>ActivateWrapper.register()</code>, which also
+ * activates the service instance.
+ * <LI> obtains the service proxy in the following
+ * order of precedence:
+ * <UL>
+ * <LI>if the <A HREF="#innerProxy">inner proxy</A> implements
+ * {@link ServiceProxyAccessor} then the return value of
+ * {@link ServiceProxyAccessor#getServiceProxy() getServiceProxy}
+ * is used
+ * <LI>if the <A HREF="#innerProxy">inner proxy</A> is
+ * not <code>null</code> then it is used
+ * <LI>Otherwise, <code>null</code> is used
+ * </UL>
+ *
+ * @return a
+ * {@link com.sun.jini.start.SharedActivatableServiceDescriptor.Created
+ * Created} object that contains the group identifier, activation ID, and
+ * proxy associated with the newly created service instance.
+ * @throws java.lang.Exception Thrown if there was any problem
+ * creating the object.
+ *
+ */
+ public Object create(Configuration config) throws Exception {
+ ServiceStarter.ensureSecurityManager();
+ logger.entering(SharedActivatableServiceDescriptor.class.getName(),
+ "create", new Object[] {config});
+
+ if (config == null) {
+ throw new NullPointerException(
+ "Configuration argument cannot be null");
+ }
+
+ ProxyPreparer globalServicePreparer =
+ (ProxyPreparer) Config.getNonNullEntry(config,
+ ServiceStarter.START_PACKAGE,
+ "servicePreparer", ProxyPreparer.class,
+ new BasicProxyPreparer());
+
+ // Needs to be called prior to setting the "descCreated" flag
+ if (getServicePreparer() == null) {
+ setServicePreparer(globalServicePreparer);
+ }
+
+ synchronized (descCreatedLock) {
+ descCreated = true;
+ }
+
+ // Get prepared activation system reference
+ Created created = null;
+ ActivationSystem sys =
+ ServiceStarter.getActivationSystem(
+ getActivationSystemHost(),
+ getActivationSystemPort(),
+ config);
+ ProxyPreparer activationIDPreparer =
+ (ProxyPreparer) Config.getNonNullEntry(config,
+ ServiceStarter.START_PACKAGE, "activationIdPreparer",
+ ProxyPreparer.class, new BasicProxyPreparer());
+ synchronized (descCreatedLock){
+ if (innerProxyPreparer == null) {
+ innerProxyPreparer = globalServicePreparer;
+ }
+ }
+
+ /* Warn user of inaccessible codebase(s) */
+ HTTPDStatus.httpdWarning(getExportCodebase());
+
+ ActivationGroupID gid = null;
+ ActivationID aid = null;
+ Object proxy = null;
+ try {
+ /* Create the ActivateWrapper descriptor for the desired service */
+ MarshalledObject params =
+ new MarshalledInstance(getServerConfigArgs()).convertToMarshalledObject();
+ ActivateWrapper.ActivateDesc adesc =
+ new ActivateWrapper.ActivateDesc(
+ getImplClassName(),
+ ClassLoaderUtil.getImportCodebaseURLs(getImportCodebase()),
+ ClassLoaderUtil.getCodebaseURLs(getExportCodebase()),
+ getPolicy(),
+ params);
+ logger.log(Level.FINEST, "ActivateDesc: {0}", adesc);
+ // Get hosting activation group
+ gid = SharedActivationGroupDescriptor.restoreGroupID(
+ getSharedGroupLog());
+
+ /* Register the desired service with the activation system */
+ aid = ActivateWrapper.register(
+ gid, adesc, getRestart(), sys);
+ aid = (ActivationID) activationIDPreparer.prepareProxy(aid);
+
+ proxy = aid.activate(true);
+
+ if(proxy != null) {
+ synchronized (descCreatedLock){
+ proxy = innerProxyPreparer.prepareProxy(proxy);
+ }
+ if (proxy instanceof ServiceProxyAccessor) {
+ proxy = ((ServiceProxyAccessor)proxy).getServiceProxy();
+ if(proxy != null) {
+ proxy = getServicePreparer().prepareProxy(proxy);
+ } else {
+ logger.log(Level.FINE,
+ "Service's getServiceProxy() returned null");
+ }
+ }
+ }//endif
+ } catch(Exception e) {
+ try {
+ if (aid != null) sys.unregisterObject(aid);
+ } catch (Exception ee) {
+ // ignore -- did the best we could.
+ logger.log(Level.FINEST,
+ "Unable to unregister with activation system", ee);
+ }
+ if (e instanceof IOException)
+ throw (IOException)e;
+ else if (e instanceof ActivationException)
+ throw (ActivationException)e;
+ else if (e instanceof ClassNotFoundException)
+ throw (ClassNotFoundException)e;
+ else
+ throw new RuntimeException("Unexpected Exception", e);
+ }
+ created = new Created(gid, aid, proxy);
+ logger.exiting(SharedActivatableServiceDescriptor.class.getName(),
+ "create", created);
+ return created;
+ }
+
+ public String toString() {
+ // Would like to call super(), but need different formatting
+ ArrayList fields = new ArrayList(12);
+ fields.add(getExportCodebase());
+ fields.add(getPolicy());
+ fields.add(getImportCodebase());
+ fields.add(getImplClassName());
+ fields.add(
+ ((getServerConfigArgs() == null)
+ ? null : Arrays.asList(getServerConfigArgs())));
+ fields.add(getLifeCycle());
+ fields.add(getServicePreparer());
+ fields.add(getInnerProxyPreparer());
+ fields.add(sharedGroupLog);
+ fields.add(Boolean.valueOf(restart));
+ fields.add(host);
+ fields.add(Integer.valueOf(port));
+ return fields.toString();
+ }
+
+ /**
+ * Reads the default serializable field values for this object.
+ * Also, verifies that the deserialized values are legal.
+ */
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ // Verify serialized fields
+ if (sharedGroupLog == null) {
+ throw new InvalidObjectException("null shared group log");
+ }
+ if (host == null) {
+ throw new InvalidObjectException("null activation host name");
+ }
+ if (port <= 0) {
+ throw new InvalidObjectException("invalid activation port value: " + port);
+ }
+
+ //Reinitialize transient fields upon de-serialization.
+ innerProxyPreparer = null;
+ }
+
+ /**
+ * Throws InvalidObjectException, since data for this class is required.
+ */
+ private void readObjectNoData() throws ObjectStreamException {
+ throw new InvalidObjectException("no data");
+ }
+}
+
+
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/GetThreadPoolAction.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/GetThreadPoolAction.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/GetThreadPoolAction.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/GetThreadPoolAction.java Fri May 9 07:03:18 2014
@@ -1,88 +1,89 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.jini.thread;
-
-import java.security.Permission;
-import java.security.PrivilegedAction;
-
-/**
- * Provides security-checked access to internal thread pools as a
- * java.security.PrivilegedAction, to be used conveniently with an
- * AccessController.doPrivileged or Security.doPrivileged.
- *
- * There are two internal thread pools: one of threads in the system
- * thread group, for executing tasks to be guarded by the security
- * policy for the system thread group, and one of threads in a
- * non-system thread group, for executing tasks with user code that
- * should not be restricted by that policy.
- *
- * If there is a security manager, the run method will check the
- * ThreadPoolPermission for the requested thread pool. If used with a
- * doPrivileged (the typical case), then only the protection domain of
- * the immediate caller of the doPrivileged needs the permission.
- *
- * The thread pools execute an action in a thread without the security
- * context in which the execute method was invoked, without any
- * subject, and with the system class loader as the context class
- * loader. Actions are expected to complete with the same context
- * class loader and other thread-specific state (such as priority)
- * that they were started with.
- *
- * @author Sun Microsystems, Inc.
- **/
-public final class GetThreadPoolAction implements PrivilegedAction {
-
- /** pool of threads for executing tasks in system thread group */
- private static final ThreadPool systemThreadPool =
- new ThreadPool(NewThreadAction.systemThreadGroup);
-
- /** pool of threads for executing tasks with user code */
- private static final ThreadPool userThreadPool =
- new ThreadPool(NewThreadAction.userThreadGroup);
-
- private static final Permission getSystemThreadPoolPermission =
- new ThreadPoolPermission("getSystemThreadPool");
- private static final Permission getUserThreadPoolPermission =
- new ThreadPoolPermission("getUserThreadPool");
-
- private final boolean user;
-
- /**
- * Creates an action that will obtain an internal thread pool.
- * When run, this action verifies that the current access control
- * context has permission to access the thread group used by the
- * indicated pool.
- *
- * @param user if true, will obtain the non-system thread group
- * pool for executing user code; if false, will obtain the system
- * thread group pool
- */
- public GetThreadPoolAction(boolean user) {
- this.user = user;
- }
-
- public Object run() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(user ? getUserThreadPoolPermission :
- getSystemThreadPoolPermission);
- }
- return user ? userThreadPool : systemThreadPool;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.jini.thread;
+
+import java.security.Permission;
+import java.security.PrivilegedAction;
+
+/**
+ * Provides security-checked access to internal thread pools as a
+ * java.security.PrivilegedAction, to be used conveniently with an
+ * AccessController.doPrivileged or Security.doPrivileged.
+ *
+ * There are two internal thread pools: one of threads in the system
+ * thread group, for executing tasks to be guarded by the security
+ * policy for the system thread group, and one of threads in a
+ * non-system thread group, for executing tasks with user code that
+ * should not be restricted by that policy.
+ *
+ * If there is a security manager, the run method will check the
+ * ThreadPoolPermission for the requested thread pool. If used with a
+ * doPrivileged (the typical case), then only the protection domain of
+ * the immediate caller of the doPrivileged needs the permission.
+ *
+ * The thread pools execute an action in a thread without the security
+ * context in which the execute method was invoked, without any
+ * subject, and with the system class loader as the context class
+ * loader. Actions are expected to complete with the same context
+ * class loader and other thread-specific state (such as priority)
+ * that they were started with.
+ *
+ * @author Sun Microsystems, Inc.
+ **/
+public final class GetThreadPoolAction implements PrivilegedAction {
+
+ /** pool of threads for executing tasks in system thread group */
+ private static final ThreadPool systemThreadPool =
+ new ThreadPool(NewThreadAction.systemThreadGroup);
+
+ /** pool of threads for executing tasks with user code */
+ private static final ThreadPool userThreadPool =
+ new ThreadPool(NewThreadAction.userThreadGroup);
+
+ private static final Permission getSystemThreadPoolPermission =
+ new ThreadPoolPermission("getSystemThreadPool");
+ private static final Permission getUserThreadPoolPermission =
+ new ThreadPoolPermission("getUserThreadPool");
+
+ private final boolean user;
+
+ /**
+ * Creates an action that will obtain an internal thread pool.
+ * When run, this action verifies that the current access control
+ * context has permission to access the thread group used by the
+ * indicated pool.
+ *
+ * @param user if true, will obtain the non-system thread group
+ * pool for executing user code; if false, will obtain the system
+ * thread group pool
+ */
+ public GetThreadPoolAction(boolean user) {
+ this.user = user;
+ }
+
+ public Object run() {
+ if (user){
+ getUserThreadPoolPermission.checkGuard(this);
+ return userThreadPool;
+ } else {
+ getSystemThreadPoolPermission.checkGuard(this);
+ return systemThreadPool;
+ }
+ }
+}
Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java Fri May 9 07:03:18 2014
@@ -21,7 +21,8 @@ package com.sun.jini.thread;
import com.sun.jini.action.GetLongAction;
import java.security.AccessController;
import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
@@ -109,9 +110,12 @@ final class ThreadPool implements Execut
* We should consider changing this to ensure that each task is executed in the
* AccessControlContext of the calling thread, to avoid privilege escalation.
*/
- private final AtomicInteger threadCount;
+ private final AtomicInteger workerCount;
private final AtomicInteger waitingThreads;
private final int delayFactor;
+ private final int numberOfThreads;
+ private final int availableProcessors;
+ private volatile boolean shutdown = false;
ThreadPool(ThreadGroup threadGroup){
this(threadGroup, 10);
@@ -121,44 +125,64 @@ final class ThreadPool implements Execut
* Creates a new thread group that executes tasks in threads of
* the given thread group.
*/
- ThreadPool(ThreadGroup threadGroup, int delayFactor) {
+ ThreadPool(final ThreadGroup threadGroup, int delayFactor) {
this.threadGroup = threadGroup;
- queue = new SynchronousQueue<Runnable>(); //Non blocking queue.
- threadCount = new AtomicInteger();
+ queue = new LinkedBlockingQueue<Runnable>();
+ workerCount = new AtomicInteger();
waitingThreads = new AtomicInteger();
this.delayFactor = delayFactor;
+ availableProcessors = Runtime.getRuntime().availableProcessors();
+ numberOfThreads = availableProcessors * 4;
+
+// Thread not started until after constructor completes
+// this escaping occurs safely.
+ Runtime.getRuntime().addShutdownHook(new Thread ("ThreadPool destroy"){
+ public void run (){
+ try {
+ // Allow two seconds prior to shutdown for other
+ // processes to complete.
+ Thread.sleep(2000L);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ shutdown = true;
+ Thread [] threads = new Thread [workerCount.get() + 1 ];
+ int count = threadGroup.enumerate(threads);
+ for (int i = 0; i < count; i++){
+ threads [i].interrupt();
+ }
+ }
+ });
}
// This method must not block - Executor
public void execute(Runnable runnable, String name) {
if (runnable == null) return;
+ if (shutdown) throw new RejectedExecutionException("ThreadPool shutdown");
Runnable task = new Task(runnable, name);
boolean accepted = false;
- try {
- // If there are no threads, maxDelay = 0;
- // If the system is highly loaded, it takes longer for waiting
- // threads to wake up and take the task, so this is designed to
- // prevent a heavily loaded system from unnecessarily creating
- // more threads, while also allowing threads to ramp up quickly
-// long maxDelay = (threadCount.get() < 400 && waitingThreads.get() == 0)
-// ? 0 : (waitingThreads.get() + 1 ) * (threadCount.get()/ numberOfCores);
-// maxDelay = maxDelay * 700 * delayFactor;
-// accepted = queue.offer(task, maxDelay, TimeUnit.MICROSECONDS);
- accepted = queue.offer(task, waitingThreads.get() * delayFactor * 700, TimeUnit.MICROSECONDS);
- } catch (InterruptedException ex) {
- Logger.getLogger(ThreadPool.class.getName()).log(Level.SEVERE, "Calling thread interrupted", ex);
- // restore interrupt.
- Thread.currentThread().interrupt();
- } finally {
- if (!accepted){
- Thread t = AccessController.doPrivileged(
- new NewThreadAction(threadGroup, new Worker(task), name, true));
- t.start();
- threadCount.incrementAndGet();
+ /* Startup ramps up very quickly because there are no waiting
+ * threads.
+ *
+ * Tasks must not be allowed to build up in the queue, in case
+ * of dependencies.
+ */
+ int workers = workerCount.get();
+ if (workers < numberOfThreads
+ || (waitingThreads.get() < 1 && workers < queue.size() / 7)) { // need more threads or we get contention.
+ if (shutdown) {
+ throw new RejectedExecutionException("ThreadPool shutdown");
}
+ Thread t = AccessController.doPrivileged(
+ new NewThreadAction(threadGroup, new Worker(task), name, false));
+ t.start();
+ accepted = true;
+ } else {
+ accepted = queue.offer(task);
}
}
+ @Override
public void execute(Runnable command) {
execute(command, "com.sun.jini.thread.ThreadPool");
}
@@ -214,6 +238,7 @@ final class ThreadPool implements Execut
}
public void run() {
+ workerCount.incrementAndGet();
try {
Runnable task = first;
first = null; // For garbage collection.
@@ -228,10 +253,13 @@ final class ThreadPool implements Execut
* most up to date state
*/
try {
- waitingThreads.getAndIncrement();
task = null;
+ waitingThreads.incrementAndGet();
+ try {
task = queue.poll(idleTimeout, TimeUnit.MILLISECONDS);
- waitingThreads.getAndDecrement();
+ } finally {
+ waitingThreads.decrementAndGet();
+ }
thread.setName(NewThreadAction.NAME_PREFIX + task);
if (task != null) {
task.run();
@@ -240,13 +268,12 @@ final class ThreadPool implements Execut
}
thread.setName(NewThreadAction.NAME_PREFIX + "Idle");
} catch (InterruptedException e){
- waitingThreads.getAndDecrement();
thread.interrupt();
break;
}
}
} finally {
- threadCount.decrementAndGet();
+ workerCount.decrementAndGet();
}
}
}