You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by ni...@apache.org on 2008/12/10 06:15:49 UTC
svn commit: r724983 [2/4] - in
/incubator/river/jtsk/skunk/niclas1/services/start: ./ src/ src/main/
src/main/java/ src/main/java/com/ src/main/java/com/sun/
src/main/java/com/sun/jini/ src/main/java/com/sun/jini/start/
src/main/java/com/sun/jini/start...
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LifeCycle.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LifeCycle.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LifeCycle.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LifeCycle.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+/**
+ * The interface used to manage the lifecycle of shared, non-activatable
+ * services started by the
+ * {@linkplain com.sun.jini.start service starter}. Services
+ * started via a
+ * {@link com.sun.jini.start.NonActivatableServiceDescriptor} get passed a
+ * reference to a <code>LifeCycle</code> object, which can be used by the
+ * server to inform the hosting environment that it can release any resources
+ * associated with the server (presumably because the server is terminating).
+ *
+ * @author Sun Microsystems, Inc.
+ * @see com.sun.jini.start.NonActivatableServiceDescriptor
+ * @see com.sun.jini.start.ServiceStarter
+ * @since 2.0
+ */
+public interface LifeCycle
+{
+
+ /**
+ * Method invoked by a server to inform the <code>LifeCycle</code>
+ * object that it can release any resources associated with the server.
+ *
+ * @param impl Object reference to the implementation object
+ * created by the <code>NonActivatableServiceDescriptor</code>.
+ * This reference must be equal, in the "==" sense, to the
+ * object created by the
+ * <code>NonActivatableServiceDescriptor</code>.
+ * @return true if the invocation was successfully processed and
+ * false otherwise.
+ */
+ public boolean unregister( Object impl );
+}
+
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LoaderSplitPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LoaderSplitPolicyProvider.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LoaderSplitPolicyProvider.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LoaderSplitPolicyProvider.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,299 @@
+/*
+ * 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.collection.WeakIdentityMap;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import net.jini.security.policy.DynamicPolicy;
+
+/**
+ * Security policy provider which handles permission queries and grants by
+ * delegating to different policy providers depending on the class loader
+ * involved. Each <code>LoaderSplitPolicyProvider</code> instance wraps two
+ * underlying policy providers:
+ * <ul>
+ * <li>a class-loader specific policy provider, consulted for permission
+ * queries/grants pertaining to that class loader, any child class loaders that
+ * delegate to it, or the <code>null</code> class loader, and
+ * <li>a default policy provider, consulted for all other operations (aside
+ * from {@link #refresh}, which applies to both policies).
+ * </ul>
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class LoaderSplitPolicyProvider
+ extends Policy implements DynamicPolicy
+{
+ private static final ProtectionDomain myDomain = (ProtectionDomain)
+ AccessController.doPrivileged( new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return LoaderSplitPolicyProvider.class.getProtectionDomain();
+ }
+ } );
+
+ private final ClassLoader loader;
+ private final Policy loaderPolicy;
+ private final Policy defaultPolicy;
+ private final WeakIdentityMap delegateMap = new WeakIdentityMap();
+
+ /**
+ * Creates a new <code>LoaderSplitPolicyProvider</code> instance which
+ * delegates to <code>loaderPolicy</code> any permission query/grant
+ * operations involving protection domains or classes with the given class
+ * loader, any child class loader of the given class loader, or the
+ * <code>null</code> class loader; all other operations are delegated to
+ * <code>defaultPolicy</code> (with the exception of <code>refresh</code>,
+ * which applies to both policies).
+ *
+ * @param loader class loader for which associated permission query/grant
+ * operations should be forwarded to <code>loaderPolicy</code>
+ * @param loaderPolicy class loader-specific security policy provider
+ * @param defaultPolicy default security policy provider
+ * @throws NullPointerException if <code>loader</code>,
+ * <code>loaderPolicy</code> or <code>defaultPolicy</code> is
+ * <code>null</code>
+ */
+ public LoaderSplitPolicyProvider( ClassLoader loader,
+ Policy loaderPolicy,
+ Policy defaultPolicy )
+ {
+ if( loader == null || loaderPolicy == null || defaultPolicy == null )
+ {
+ throw new NullPointerException();
+ }
+ this.loader = loader;
+ this.loaderPolicy = loaderPolicy;
+ this.defaultPolicy = defaultPolicy;
+ ensureDependenciesResolved();
+ }
+
+ /**
+ * Delegates to the corresponding <code>getPermissions</code> method of the
+ * underlying default policy.
+ *
+ * @param source code source for which to look up permissions
+ * @return set of permissions allowed for the given code source
+ */
+ public PermissionCollection getPermissions( CodeSource source )
+ {
+ return defaultPolicy.getPermissions( source );
+ }
+
+ /**
+ * If the given protection domain is the protection domain of this class,
+ * then a newly-created <code>PermissionCollection</code> containing {@link
+ * AllPermission} is returned. If not, delegates to the corresponding
+ * <code>getPermissions</code> method of the underlying policy associated
+ * with the loader of the given class (the loader-specific policy if the
+ * class loader is <code>null</code>, the same as or a child of the loader
+ * specified in the constructor for this instance, or the default loader
+ * otherwise).
+ *
+ * @param domain protection domain for which to look up permissions
+ * @return set of permissions allowed for given protection domain
+ */
+ public PermissionCollection getPermissions( ProtectionDomain domain )
+ {
+ if( domain == myDomain )
+ {
+ PermissionCollection pc = new Permissions();
+ pc.add( new AllPermission() );
+ return pc;
+ }
+ else
+ {
+ return getDelegate( domain.getClassLoader() ).getPermissions( domain );
+ }
+ }
+
+ /**
+ * If the given protection domain is the protection domain of this class,
+ * then <code>true</code> is returned. If not, delegates to the
+ * <code>implies</code> method of the underlying policy associated with the
+ * loader of the given class (the loader-specific policy if the class
+ * loader is <code>null</code>, the same as or a child of the loader
+ * specified in the constructor for this instance, or the default loader
+ * otherwise).
+ *
+ * @param domain protection domain in which to check implication
+ * @param permission permission to test implication of
+ * @return <code>true</code> if permission is implied by permissions of
+ * given protection domain, <code>false</code> otherwise
+ */
+ public boolean implies( ProtectionDomain domain, Permission permission )
+ {
+ return domain == myDomain ||
+ getDelegate( domain.getClassLoader() ).implies( domain,
+ permission );
+ }
+
+ /**
+ * Invokes <code>refresh</code> on both the loader-specific and default
+ * underlying policy providers.
+ */
+ public void refresh()
+ {
+ loaderPolicy.refresh();
+ defaultPolicy.refresh();
+ }
+
+ /**
+ * Returns <code>true</code> if both of the underlying policy providers
+ * implement {@link DynamicPolicy} and return <code>true</code> from calls
+ * to <code>grantSupported</code>; returns <code>false</code> otherwise.
+ *
+ * @return {@inheritDoc}
+ */
+ public boolean grantSupported()
+ {
+ return loaderPolicy instanceof DynamicPolicy &&
+ ( (DynamicPolicy) loaderPolicy ).grantSupported() &&
+ defaultPolicy instanceof DynamicPolicy &&
+ ( (DynamicPolicy) defaultPolicy ).grantSupported();
+ }
+
+ /**
+ * If both underlying policy providers support dynamic grants, delegates to
+ * the <code>grant</code> method of the underlying policy associated with
+ * the loader of the given class (the loader-specific policy if the class
+ * loader is <code>null</code>, the same as or a child of the loader
+ * specified in the constructor for this instance, or the default loader
+ * otherwise). If at least one of the underlying policy providers does not
+ * support dynamic grants, throws an
+ * <code>UnsupportedOperationException</code>.
+ *
+ * @param cl {@inheritDoc}
+ * @param principals {@inheritDoc}
+ * @param permissions {@inheritDoc}
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws SecurityException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void grant( Class cl,
+ Principal[] principals,
+ Permission[] permissions )
+ {
+ if( !grantSupported() )
+ {
+ throw new UnsupportedOperationException( "grants not supported" );
+ }
+ ( (DynamicPolicy) getDelegate( getClassLoader( cl ) ) ).grant(
+ cl, principals, permissions );
+ }
+
+ /**
+ * If both underlying policy providers support dynamic grants, delegates to
+ * the <code>getGrants</code> method of the underlying policy associated
+ * with the loader of the given class (the loader-specific policy if the
+ * class loader is <code>null</code>, the same as or a child of the loader
+ * specified in the constructor for this instance, or the default loader
+ * otherwise). If at least one of the underlying policy providers does not
+ * support dynamic grants, throws an
+ * <code>UnsupportedOperationException</code>.
+ *
+ * @param cl {@inheritDoc}
+ * @param principals {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public Permission[] getGrants( Class cl, Principal[] principals )
+ {
+ if( !grantSupported() )
+ {
+ throw new UnsupportedOperationException( "grants not supported" );
+ }
+ return ( (DynamicPolicy) getDelegate( getClassLoader( cl ) ) ).getGrants(
+ cl, principals );
+ }
+
+ /**
+ * Ensures that any classes depended on by this policy provider are
+ * resolved. This is to preclude lazy resolution of such classes during
+ * operation of the provider, which can result in deadlock as described by
+ * bug 4911907.
+ */
+ private void ensureDependenciesResolved()
+ {
+ // force class resolution by pre-invoking method called by implies()
+ getDelegate( loader );
+ }
+
+ private Policy getDelegate( final ClassLoader ldr )
+ {
+ if( ldr == null )
+ {
+ /* This special case is needed so that implies queries from the
+ * BasicInvocationDispatcher.checkClientPermission method
+ * will be handled by the loader-specific (i.e., service) policy.
+ */
+ return loaderPolicy;
+ }
+ Policy p;
+ synchronized( delegateMap )
+ {
+ p = (Policy) delegateMap.get( ldr );
+ }
+ if( p == null )
+ {
+ p = (Policy) AccessController.doPrivileged( new PrivilegedAction()
+ {
+ public Object run()
+ {
+ for( ClassLoader l = ldr; l != null; l = l.getParent() )
+ {
+ if( l == loader )
+ {
+ return loaderPolicy;
+ }
+ }
+ return defaultPolicy;
+ }
+ } );
+ synchronized( delegateMap )
+ {
+ delegateMap.put( ldr, p );
+ }
+ }
+ return p;
+ }
+
+ private static ClassLoader getClassLoader( final Class cl )
+ {
+ return (ClassLoader) AccessController.doPrivileged(
+ new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return cl.getClassLoader(); }
+ });
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/NonActivatableServiceDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/NonActivatableServiceDescriptor.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/NonActivatableServiceDescriptor.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/NonActivatableServiceDescriptor.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,782 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.net.URLClassLoader;
+import java.rmi.MarshalledObject;
+import java.security.AllPermission;
+import java.security.Permission;
+import java.security.Policy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.config.Configuration;
+import net.jini.export.ProxyAccessor;
+import net.jini.security.BasicProxyPreparer;
+import net.jini.security.ProxyPreparer;
+import net.jini.security.policy.DynamicPolicy;
+import net.jini.security.policy.DynamicPolicyProvider;
+import net.jini.security.policy.PolicyFileProvider;
+
+/**
+ * Class used to launch shared, non-activatable, in-process
+ * 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 the invoking object's VM.
+ * <P>
+ * This class provides 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 VM, with each object maintaining distinct
+ * export codebase and security policy settings.
+ * <P>
+ * <a name="serviceConstructor">
+ * Services need to implement the following "non-activatable
+ * constructor":
+ * <blockquote><pre><impl>(String[] args, {@link LifeCycle LifeCycle} lc)</blockquote></pre>
+ * where,
+ * <UL>
+ * <LI>args - are the service configuration arguments
+ * <LI>lc - is the hosting environment's
+ * {@link LifeCycle} reference.
+ * </UL>
+ *
+ * <a name="serviceProxy">
+ * 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 order of precedence:
+ * <OL>
+ * <LI> if the service class implements
+ * {@link ServiceProxyAccessor ServiceProxyAccessor} then return value of
+ * {@link ServiceProxyAccessor#getServiceProxy() getServiceProxy}
+ * will be used as the service proxy.
+ * <LI> if the service class implements
+ * {@link net.jini.export.ProxyAccessor ProxyAccessor}
+ * then the return value of
+ * {@link net.jini.export.ProxyAccessor#getProxy() getProxy} will be used
+ * as the service proxy.
+ * <LI> Otherwise <code>null</code> will be returned as the service proxy.
+ * </OL>
+ *
+ * The following items are discussed below:
+ * <ul>
+ * <li><a href="#configEntries">Configuring NonActivatableServiceDescriptor</a>
+ * <li><a href="#logging">Logging</a>
+ * </ul>
+ *
+ * <a name="configEntries">
+ * <h3>Configuring NonActivatableServiceDescriptor</h3>
+ * </a>
+ *
+ * <code>NonActivatableServiceDescriptor</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>
+ *
+ * <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
+ * the <a href="#serviceProxy">service proxy</a>.
+ * 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 service proxy 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>
+ *
+ * This 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 non-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#SEVERE SEVERE} <td>
+ * for significant service creation problems
+ * <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
+ */
+// TODO - add discussion about how to provide a service's proxy
+
+public class NonActivatableServiceDescriptor
+ implements ServiceDescriptor, Serializable
+{
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The parameter types for the "activation constructor".
+ */
+ private static final Class[] actTypes = {
+ String[].class, LifeCycle.class
+ };
+
+ /**
+ * @serial <code>String</code> containing export codebase.
+ * That is, location where clients can download required
+ * service-related classes (for example, stubs, proxies, etc.).
+ */
+ private final String codebase;
+
+ /**
+ * @serial <code>String</code> containing server policy filename or URL
+ */
+ private final String policy;
+
+ /**
+ * @serial <code>String</code> containing import codebase location.
+ * That is, location where server implementation
+ * classes can be found.
+ */
+ private final String classpath;
+
+ /**
+ * @serial <code>String</code> containing the
+ * name of server implementation class
+ */
+ private final String implClassName;
+
+ /**
+ * @serial <code>String[]</code> containing server
+ * configuration arguments
+ */
+ private final String[] serverConfigArgs;
+
+ /*
+ * <code>LifeCycle</code> reference for hosting environment
+ */
+ private /*final*/ transient LifeCycle lifeCycle;
+
+ /*
+ * <code>ProxyPreparer</code> reference for preparing the service's proxy
+ */
+ private /*final*/ transient ProxyPreparer servicePreparer;
+
+ /**
+ * Flag indicating when create() has been called
+ */
+ protected transient boolean descCreated = false;
+
+ /**
+ * Lock object for <code>descCreated</code> flag
+ */
+ protected transient Object descCreatedLock = new Object();
+
+ private static LifeCycle NoOpLifeCycle =
+ new LifeCycle()
+ { // default, no-op object
+
+ public boolean unregister( Object impl )
+ {
+ return false;
+ }
+ };
+
+ private static AggregatePolicyProvider globalPolicy = null;
+ private static Policy initialGlobalPolicy = null;
+ private static final Logger logger = ServiceStarter.logger;
+
+ /**
+ * Object returned by
+ * {@link NonActivatableServiceDescriptor#create(net.jini.config.Configuration)
+ * NonActivatableServiceDescriptor.create()}
+ * method that returns the proxy and implementation references
+ * for the created service.
+ */
+ public static class Created
+ {
+ /**
+ * The reference to the proxy of the created service
+ */
+ public final Object proxy;
+ /**
+ * The reference to the implementation of the created service
+ */
+ public final Object impl;
+
+ /**
+ * Constructs an instance of this class.
+ *
+ * @param impl reference to the implementation of the created service
+ * @param proxy reference to the proxy of the created service
+ */
+ public Created( Object impl, Object proxy )
+ {
+ this.proxy = proxy;
+ this.impl = impl;
+ }//end constructor
+ }//end class Created
+
+ /**
+ * 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 serverConfigArgs service configuration arguments. This parameter
+ * is passed as the <code>String[]</code> argument to the
+ * implementation's
+ * <a href="#serviceConstructor">constructor</a>.
+ * @param lifeCycle <code>LifeCycle</code> reference
+ * for hosting environment. This parameter
+ * is passed as the <code>LifeCycle</code> argument to the
+ * implementation's
+ * <a href="#serviceConstructor">constructor</a>. If this argument
+ * is null, then a default, no-op <code>LifeCycle</code> object will
+ * be assigned.
+ * @param preparer <code>ProxyPreparer</code> reference. This object
+ * will be used to prepare the service's proxy object, if any
+ * (see <a href="#serviceProxy">service proxy</a> section for details).
+ * If this argument is null, then the default
+ * <a href="#servicePreparer">service preparer</a> will be used.
+ */
+ public NonActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ // Optional Args
+ String[] serverConfigArgs,
+ LifeCycle lifeCycle,
+ ProxyPreparer preparer )
+ {
+ if( exportCodebase == null || policy == null ||
+ importCodebase == null || implClassName == null )
+ {
+ throw new NullPointerException(
+ "export codebase, policy, import codebase, and"
+ + " implementation cannot be null" );
+ }
+ this.codebase = exportCodebase;
+ this.policy = policy;
+ this.classpath = importCodebase;
+ this.implClassName = implClassName;
+ this.serverConfigArgs = serverConfigArgs;
+ this.lifeCycle =
+ ( lifeCycle == null ) ? NoOpLifeCycle : lifeCycle;
+ this.servicePreparer = preparer;
+ }
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #NonActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], com.sun.jini.start.LifeCycle, net.jini.security.ProxyPreparer) contructor}
+ * with <code>null</code> for the <code>preparer</code>
+ * reference.
+ */
+ public NonActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ // Optional Args
+ String[] serverConfigArgs,
+ LifeCycle lifeCycle )
+ {
+ this( exportCodebase, policy, importCodebase, implClassName,
+ serverConfigArgs, lifeCycle, null );
+ }
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #NonActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], com.sun.jini.start.LifeCycle, net.jini.security.ProxyPreparer) contructor}
+ * with <code>null</code> for the <code>lifeCycle</code> and <code>preparer</code>
+ * references.
+ */
+ public NonActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ // Optional Args
+ String[] serverConfigArgs )
+ {
+ this( exportCodebase, policy, importCodebase, implClassName,
+ serverConfigArgs, null, null );
+ }
+
+ /**
+ * Convenience constructor. Equivalent to calling this
+ * {@link #NonActivatableServiceDescriptor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[], com.sun.jini.start.LifeCycle, net.jini.security.ProxyPreparer) contructor}
+ * with <code>null</code> for the <code>lifeCycle</code>
+ * reference.
+ */
+ public NonActivatableServiceDescriptor(
+ // Required Args
+ String exportCodebase,
+ String policy,
+ String importCodebase,
+ String implClassName,
+ // Optional Args
+ String[] serverConfigArgs,
+ ProxyPreparer preparer )
+ {
+ this( exportCodebase, policy, importCodebase, implClassName,
+ serverConfigArgs, null, preparer );
+ }
+
+ /**
+ * Codebase accessor method.
+ *
+ * @return the export codebase string associated with this service descriptor.
+ */
+ final public String getExportCodebase()
+ {
+ return codebase;
+ }
+
+ /**
+ * Policy accessor method.
+ *
+ * @return the policy string associated with this service descriptor.
+ */
+ final public String getPolicy()
+ {
+ return policy;
+ }
+
+ /**
+ * Classpath accessor method.
+ *
+ * @return the import codebase string associated with this service descriptor.
+ */
+ final public String getImportCodebase()
+ {
+ return classpath;
+ }
+
+ /**
+ * Implementation class accessor method.
+ *
+ * @return the implementation class string associated with
+ * this service descriptor.
+ */
+ final public String getImplClassName()
+ {
+ return implClassName;
+ }
+
+ /**
+ * Service configuration arguments accessor method.
+ *
+ * @return the service configuration arguments associated with
+ * this service descriptor.
+ */
+ final public String[] getServerConfigArgs()
+ {
+ return ( serverConfigArgs != null )
+ ? (String[]) serverConfigArgs.clone()
+ : null;
+ }
+
+ /**
+ * <code>LifeCycle</code> accessor method.
+ *
+ * @return the <code>LifeCycle</code> object associated with
+ * this service descriptor.
+ */
+ final public LifeCycle getLifeCycle()
+ {
+ return lifeCycle;
+ }
+
+ /**
+ * Sets the <code>LifeCycle</code> object 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 <code>LifeCycle</code> upon deserialization
+ * of this descriptor.
+ *
+ * @param lc The <code>LifeCycle</code> object to be
+ * associated with this service descriptor.
+ * @throws IllegalStateException if called after <code>create()</code> is invoked
+ */
+ final public void setLifeCycle( LifeCycle lc )
+ {
+ synchronized( descCreatedLock )
+ {
+ if( descCreated )
+ {
+ throw new IllegalStateException( "Can't set LifeCycle after descriptor creation" );
+ }
+ else
+ {
+ lifeCycle = lc;
+ }
+ }
+ }
+
+ /**
+ * <code>ProxyPreparer</code> accessor method.
+ *
+ * @return the <code>ProxyPreparer</code> object associated with
+ * this service descriptor.
+ */
+ final public ProxyPreparer getServicePreparer()
+ {
+ return servicePreparer;
+ }
+
+ /**
+ * Sets the <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 <code>ProxyPreparer</code> upon deserialization
+ * of this descriptor.
+ *
+ * @param serviceProxyPreparer The <code>ProxyPreparer</code> object to be
+ * associated with this service descriptor.
+ * @throws IllegalStateException if called after <code>create()</code> is invoked
+ */
+ final public void setServicePreparer( ProxyPreparer serviceProxyPreparer )
+ {
+ synchronized( descCreatedLock )
+ {
+ if( descCreated )
+ {
+ throw new IllegalStateException( "Can't set ProxyPreparer after descriptor creation" );
+ }
+ else
+ {
+ servicePreparer = serviceProxyPreparer;
+ }
+ }
+ }
+
+ /**
+ * Attempts to create a service instance based on the service
+ * description information provided via constructor parameters.
+ * <P>
+ * This method:
+ * <UL>
+ * <LI> installs an {@link java.rmi.RMISecurityManager RMISecurityManager}
+ * if no security manager is already in place
+ * <LI> installs an {@link AggregatePolicyProvider AggregatePolicyProvider}
+ * as the VM-global policy object
+ * (upon the first invocation of this method)
+ * <LI> creates an
+ * <code>ActivateWrapper.ExportClassLoader</code> with
+ * the associated service's import codebase, export codebase and
+ * the current thread's context class loader as its arguments
+ * <LI> associates the newly created
+ * <code>ExportClassLoader</code> and the associated service's
+ * policy file with the
+ * {@link AggregatePolicyProvider AggregatePolicyProvider}
+ * <LI> sets the newly created <code>ExportClassLoader</code> as
+ * the current thread's context class loader
+ * <LI> loads the service object's class and calls a constructor
+ * with the following signature:
+ * <blockquote><pre><impl>(String[], LifeCycle)</blockquote></pre>
+ * <LI> obtains the service proxy by calling
+ * {@link ServiceProxyAccessor#getServiceProxy() ServiceProxyAccessor.getServiceProxy()}
+ * or
+ * {@link net.jini.export.ProxyAccessor#getProxy() ProxyAccessor.getProxy()},
+ * respectively, on the implementation instance.
+ * If neither interface is supported, the
+ * proxy reference is set to <code>null</code>
+ * <LI> resets the context class loader to the
+ * context classloader in effect when the method was called
+ * </UL>
+ *
+ * @return a
+ * {@link com.sun.jini.start.NonActivatableServiceDescriptor.Created
+ * Created} instance with the service's proxy and implementation
+ * references.
+ * @throws java.lang.Exception Thrown if there was any problem
+ * creating the object.
+ */
+ public Object create( Configuration config ) throws Exception
+ {
+ ServiceStarter.ensureSecurityManager();
+ logger.entering( NonActivatableServiceDescriptor.class.getName(),
+ "create", new Object[]{ config } );
+ if( config == null )
+ {
+ throw new NullPointerException(
+ "Configuration argument cannot be null" );
+ }
+ synchronized( descCreatedLock )
+ {
+ descCreated = true;
+ }
+
+ if( servicePreparer == null )
+ {
+ servicePreparer =
+ (ProxyPreparer) Config.getNonNullEntry( config,
+ ServiceStarter.START_PACKAGE,
+ "servicePreparer", ProxyPreparer.class,
+ new BasicProxyPreparer() );
+ }
+
+ /* Warn user of inaccessible codebase(s) */
+ HTTPDStatus.httpdWarning( getExportCodebase() );
+
+ Object proxy = null;
+ Object impl = null;
+ //Create custom class loader that preserves codebase annotations
+ Thread curThread = Thread.currentThread();
+ ClassLoader oldClassLoader = curThread.getContextClassLoader();
+ logger.log( Level.FINEST, "Saved current context class loader: {0}",
+ oldClassLoader );
+ URLClassLoader newClassLoader = null;
+ try
+ {
+ newClassLoader =
+ new ActivateWrapper.ExportClassLoader(
+ ClassLoaderUtil.getImportCodebaseURLs( getImportCodebase() ),
+ ClassLoaderUtil.getCodebaseURLs( getExportCodebase() ),
+ oldClassLoader );
+ logger.log( Level.FINEST, "Created ExportClassLoader: {0}",
+ newClassLoader );
+ }
+ catch( IOException ioe )
+ {
+ logger.log( Level.SEVERE, "classloader.problem",
+ new Object[]{ getImportCodebase(), getExportCodebase() } );
+ throw ioe;
+ }
+
+ synchronized( NonActivatableServiceDescriptor.class )
+ {
+ // supplant global policy 1st time through
+ if( globalPolicy == null )
+ {
+ initialGlobalPolicy = Policy.getPolicy();
+ if( !( initialGlobalPolicy instanceof DynamicPolicy ) )
+ {
+ initialGlobalPolicy =
+ new DynamicPolicyProvider( initialGlobalPolicy );
+ }
+ globalPolicy =
+ new AggregatePolicyProvider( initialGlobalPolicy );
+ Policy.setPolicy( globalPolicy );
+ logger.log( Level.FINEST,
+ "Global policy set: {0}", globalPolicy );
+ }
+
+ Policy service_policy =
+ ActivateWrapper.getServicePolicyProvider(
+ new PolicyFileProvider( getPolicy() ) );
+ Policy backstop_policy =
+ ActivateWrapper.getServicePolicyProvider( initialGlobalPolicy );
+ LoaderSplitPolicyProvider split_service_policy =
+ new LoaderSplitPolicyProvider(
+ newClassLoader, service_policy, backstop_policy );
+ /* Grant "this" code enough permission to do its work
+ * under the service policy, which takes effect (below)
+ * after the context loader is (re)set.
+ * Note: Throws UnsupportedOperationException if dynamic grants
+ * aren't supported (because underlying policies don't support it).
+ */
+ split_service_policy.grant(
+ this.getClass(),
+ null, /* Principal[] */
+ new Permission[]{ new AllPermission() } );
+ globalPolicy.setPolicy( newClassLoader, split_service_policy );
+ }
+
+ logger.finest( "Attempting to get implementation class" );
+ Class implClass = null;
+ implClass =
+ Class.forName( getImplClassName(), false, newClassLoader );
+ logger.finest( "Setting context class loader" );
+ curThread.setContextClassLoader( newClassLoader );
+
+ try
+ {
+ logger.finest( "Attempting to get implementation constructor" );
+ Constructor constructor =
+ implClass.getDeclaredConstructor( actTypes );
+ logger.log( Level.FINEST,
+ "Obtained implementation constructor: {0}",
+ constructor );
+ constructor.setAccessible( true );
+ impl =
+ constructor.newInstance(
+ new Object[]{ getServerConfigArgs(), lifeCycle } );
+ logger.log( Level.FINEST,
+ "Obtained implementation instance: {0}", impl );
+ if( impl instanceof ServiceProxyAccessor )
+ {
+ proxy = ( (ServiceProxyAccessor) impl ).getServiceProxy();
+ }
+ else if( impl instanceof ProxyAccessor )
+ {
+ proxy = ( (ProxyAccessor) impl ).getProxy();
+ }
+ else
+ {
+ proxy = null; // just for insurance
+ }
+
+ logger.log( Level.FINEST, "Proxy = {0}", proxy );
+ curThread.setContextClassLoader( oldClassLoader );
+//TODO - factor in code integrity for MO
+ proxy = ( new MarshalledObject( proxy ) ).get();
+ }
+ finally
+ {
+ curThread.setContextClassLoader( oldClassLoader );
+ }
+
+ if( proxy != null )
+ {
+ proxy = servicePreparer.prepareProxy( proxy );
+ }
+ Created created = new Created( impl, proxy );
+ logger.exiting( NonActivatableServiceDescriptor.class.getName(),
+ "create", created );
+ return created;
+ }
+
+ /**
+ * Prints out a field summary
+ */
+ public String toString()
+ {
+ ArrayList fields = new ArrayList( 7 );
+ fields.add( codebase );
+ fields.add( policy );
+ fields.add( classpath );
+ fields.add( implClassName );
+ fields.add(
+ ( ( serverConfigArgs == null )
+ ? null : Arrays.asList( serverConfigArgs ) ) );
+ fields.add( lifeCycle );
+ fields.add( servicePreparer );
+ return fields.toString();
+ }
+
+ /**
+ * Reads the default serializable field values for this object
+ * and resets the tranisient fields to legal values.
+ * Also, verifies that the deserialized values are legal.
+ */
+ private void readObject( ObjectInputStream in )
+ throws IOException, ClassNotFoundException
+ {
+ in.defaultReadObject();
+ // Verify that serialized fields aren't null
+ if( codebase == null )
+ {
+ throw new InvalidObjectException( "null export codebase" );
+ }
+ if( policy == null )
+ {
+ throw new InvalidObjectException( "null policy" );
+ }
+ if( classpath == null )
+ {
+ throw new InvalidObjectException( "null import codebase" );
+ }
+ if( implClassName == null )
+ {
+ throw new InvalidObjectException( "null implementation class name" );
+ }
+
+ //Reinitialize transient fields upon de-serialization.
+ lifeCycle = NoOpLifeCycle;
+ servicePreparer = null;
+ descCreated = false;
+ descCreatedLock = new Object();
+ }
+
+ /**
+ * Throws InvalidObjectException, since data for this class is required.
+ */
+ private void readObjectNoData() throws ObjectStreamException
+ {
+ throw new InvalidObjectException( "no data" );
+ }
+}
+
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ProxyVerifier.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ProxyVerifier.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ProxyVerifier.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ProxyVerifier.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,111 @@
+/*
+ * 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 java.io.Serializable;
+import java.rmi.RemoteException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.core.constraint.MethodConstraints;
+import net.jini.core.constraint.RemoteMethodControl;
+import net.jini.export.proxytrust.TrustEquivalence;
+import net.jini.security.TrustVerifier;
+
+/**
+ * Defines a trust verifier for the smart proxies of a SharedGroup server.
+ */
+final class ProxyVerifier implements TrustVerifier, Serializable
+{
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Logger and configuration component name for SharedGroup
+ */
+ protected static final String START_PROXY = "com.sun.jini.start.proxy";
+
+ /**
+ * Logger for logging information about this instance
+ */
+ private static final Logger logger = Logger.getLogger( START_PROXY );
+
+ /**
+ * The SharedGroup server proxy.
+ */
+ private final RemoteMethodControl serverProxy;
+
+ /**
+ * Returns a verifier for the smart proxies of the specified SharedGroup
+ * server proxy.
+ *
+ * @param serverProxy the SharedGroup server proxy
+ * @throws UnsupportedOperationException if <code>serverProxy</code> does
+ * not implement both {@link RemoteMethodControl} and {@link
+ * TrustEquivalence}
+ */
+ ProxyVerifier( SharedGroupBackEnd serverProxy )
+ {
+ if( !( serverProxy instanceof RemoteMethodControl ) )
+ {
+ throw new UnsupportedOperationException(
+ "No verifier available for non-secure service" );
+ }
+ else if( !( serverProxy instanceof TrustEquivalence ) )
+ {
+ throw new UnsupportedOperationException(
+ "Verifier requires service proxy to implement " +
+ "TrustEquivalence" );
+ }
+ this.serverProxy = (RemoteMethodControl) serverProxy;
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean isTrustedObject(
+ Object obj, TrustVerifier.Context ctx )
+ throws RemoteException
+ {
+ logger.entering( ProxyVerifier.class.getName(), "isTrustedObject",
+ new Object[]{ obj, ctx } );
+ if( obj == null || ctx == null )
+ {
+ throw new NullPointerException( "Arguments must not be null" );
+ }
+
+ RemoteMethodControl otherServerProxy;
+ if( obj instanceof SharedGroupBackEnd )
+ {
+ otherServerProxy = (RemoteMethodControl) obj;
+ }
+ else
+ {
+ logger.log( Level.FINEST, "Object {0} is not a supported type",
+ obj );
+ return false;
+ }
+
+ MethodConstraints mc = otherServerProxy.getConstraints();
+ TrustEquivalence trusted =
+ (TrustEquivalence) serverProxy.setConstraints( mc );
+ boolean result = trusted.checkTrustEquivalence( otherServerProxy );
+ logger.exiting( ProxyVerifier.class.getName(), "isTrustedObject",
+ Boolean.valueOf( result ) );
+ return result;
+ }
+}
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceDescriptor.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceDescriptor.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceDescriptor.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceDescriptor.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,44 @@
+/*
+ * 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 net.jini.config.Configuration;
+
+/**
+ * Interface that all service description objects must implement.
+ *
+ * @see SharedActivationGroupDescriptor
+ * @see SharedActivatableServiceDescriptor
+ * @see NonActivatableServiceDescriptor
+ */
+public interface ServiceDescriptor
+{
+ /**
+ * Creates an object described by the
+ * actual <code>ServiceDescriptor</code> instance.
+ *
+ * @param config The <code>Configuration</code> object
+ * used to configure the creation of the returned object.
+ * @return An object instance appropriate for the given
+ * service descriptor instance.
+ * @throws java.lang.Exception Thrown if there was any problem
+ * creating the object.
+ */
+ public Object create( Configuration config ) throws Exception;
+}
+
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceProxyAccessor.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceProxyAccessor.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceProxyAccessor.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceProxyAccessor.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,61 @@
+/*
+ * 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 java.rmi.RemoteException;
+
+/**
+ * Provides a means to obtain a client-side proxy from a
+ * "base" service object.
+ * <p>
+ * This interface is typically implemented by a service implementation
+ * and/or it's remote activatable reference, if any, to allow the service
+ * to return the object of its choice for a client-side reference.
+ * When a non-activatable service is created,
+ * {@link NonActivatableServiceDescriptor#create(net.jini.config.Configuration)
+ * NonActivatableServiceDescriptor.create()},
+ * returns the result from <code><impl>.getServiceProxy()</code>,
+ * if supported, where <code><impl></code> is the service implementation
+ * instance.
+ * When an activatable service is created,
+ * {@link SharedActivatableServiceDescriptor#create(net.jini.config.Configuration)
+ * SharedActivatableServiceDescriptor.create()},
+ * returns the result of <code><act_ref>.getServiceProxy()</code>,
+ * if supported, where <code><act_ref></code> is the service reference
+ * returned by the call to
+ * {@link java.rmi.activation.ActivationID#activate(boolean) ActivationID.activate()}.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see com.sun.jini.start.NonActivatableServiceDescriptor
+ * @see com.sun.jini.start.SharedActivatableServiceDescriptor
+ * @see java.rmi.activation.ActivationID
+ * @since 2.0
+ */
+public interface ServiceProxyAccessor
+{
+
+ /**
+ * Returns a proxy object for this object. This value should not be
+ * <code>null</code>.
+ *
+ * @return a proxy object reference
+ */
+ public Object getServiceProxy() throws RemoteException;
+}
+
Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceStarter.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceStarter.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceStarter.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceStarter.java Tue Dec 9 21:15:48 2008
@@ -0,0 +1,553 @@
+/*
+ * 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.action.GetIntegerAction;
+import com.sun.jini.config.Config;
+import java.rmi.Naming;
+import java.rmi.RMISecurityManager;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationSystem;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.MissingResourceException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationException;
+import net.jini.config.ConfigurationProvider;
+import net.jini.security.BasicProxyPreparer;
+import net.jini.security.ProxyPreparer;
+
+/**
+ * This class provides the main routine for starting shared groups,
+ * non-activatable services, and activatable services.
+ *
+ * The following implementation-specific items are discussed below:
+ * <ul>
+ * <li><a href="#configEntries">Configuring ServiceStarter</a>
+ * <li><a href="#logging">Logging</a>
+ * </ul>
+ *
+ * <a name="configEntries">
+ * <h3>Configuring ServiceStarter</h3>
+ * </a>
+ *
+ * This implementation of <code>ServiceStarter</code> supports the
+ * following configuration entries, with component
+ * <code>com.sun.jini.start</code>:
+ *
+ * <table summary="Describes the loginContext 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>
+ * loginContext</code></font>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Type: <td> {@link javax.security.auth.login.LoginContext}
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Default: <td> <code>null</code>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Description: <td> If not <code>null</code>, specifies the JAAS
+ * login context to use for performing a JAAS login and supplying the
+ * {@link javax.security.auth.Subject} to use when running the
+ * service starter. If <code>null</code>, no JAAS login is performed.
+ * </table>
+ *
+ * <table summary="Describes the serviceDescriptors 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>
+ * serviceDescriptors</code></font>
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Type: <td> {@link ServiceDescriptor}[]
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Default: no default
+ * <tr valign="top"> <td>   <th scope="row" align="right">
+ * Description: <td> Array of service descriptors to start.
+ * </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 service.starter 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#SEVERE SEVERE} <td>
+ * for problems that prevent service creation from proceeding
+ * <tr> <td> {@link java.util.logging.Level#WARNING WARNING} <td>
+ * for problems with service creation that don't prevent further
+ * processing
+ * <tr> <td> {@link java.util.logging.Level#FINER FINER} <td>
+ * for high level
+ * service creation operation tracing
+ * <tr> <td> {@link java.util.logging.Level#FINEST FINEST} <td>
+ * for low level
+ * service creation operation tracing
+ *
+ * </table> <p>
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class ServiceStarter
+{
+
+ /**
+ * Component name for service starter configuration entries
+ */
+ static final String START_PACKAGE = "com.sun.jini.start";
+
+
+ /**
+ * Configure logger
+ */
+ static /*final*/ Logger logger = null;
+
+ static
+ {
+ try
+ {
+ logger =
+ Logger.getLogger(
+ START_PACKAGE + ".service.starter",
+ START_PACKAGE + ".resources.service" );
+ }
+ catch( Exception e )
+ {
+ logger =
+ Logger.getLogger( START_PACKAGE + ".service.starter" );
+ if( e instanceof MissingResourceException )
+ {
+ logger.info( "Could not load logger's ResourceBundle: "
+ + e );
+ }
+ else if( e instanceof IllegalArgumentException )
+ {
+ logger.info( "Logger exists and uses another resource bundle: "
+ + e );
+ }
+ logger.info( "Defaulting to existing logger" );
+ }
+ }
+
+ /**
+ * Array of strong references to transient services
+ */
+ private static ArrayList transient_service_refs;
+
+ /**
+ * Prevent instantiation
+ */
+ private ServiceStarter()
+ {
+ }
+
+ /**
+ * Trivial class used as the return value by the
+ * <code>create</code> methods. This class aggregates
+ * the results of a service creation attempt:
+ * proxy (if any), exception (if any), associated
+ * descriptor object.
+ */
+ private static class Result
+ {
+ /**
+ * Service proxy object, if any.
+ */
+ public final Object result;
+ /**
+ * Service creation exception, if any.
+ */
+ public final Exception exception;
+ /**
+ * Associated <code>ServiceDescriptor</code> object
+ * used to create the service instance
+ */
+ public final ServiceDescriptor descriptor;
+
+ /**
+ * Trivial constructor. Simply assigns each argument
+ * to the appropriate field.
+ */
+ Result( ServiceDescriptor d, Object o, Exception e )
+ {
+ descriptor = d;
+ result = o;
+ exception = e;
+ }
+
+ // javadoc inherited from super class
+ public String toString()
+ {
+ return this.getClass() + ":[descriptor=" + descriptor + ", "
+ + "result=" + result + ", exception=" + exception + "]";
+ }
+ }
+
+ /**
+ * Generic service creation method that attempts to login via
+ * the provided <code>LoginContext</code> and then call the
+ * <code>create</code> overload without a login context argument.
+ *
+ * @param descs The <code>ServiceDescriptor[]</code> that contains
+ * the descriptors for the services to start.
+ * @param config The associated <code>Configuration</code> object
+ * used to customize the service creation process.
+ * @param loginContext The associated <code>LoginContext</code> object
+ * used to login/logout.
+ * @return Returns a <code>Result[]</code> that is the same length as
+ * <code>descs</code>, which contains the details for each
+ * service creation attempt.
+ * @throws Exception If there was a problem logging in/out or
+ * a problem creating the service.
+ * @see Result
+ * @see ServiceDescriptor
+ * @see net.jini.config.Configuration
+ * @see javax.security.auth.login.LoginContext
+ */
+
+ private static Result[] createWithLogin(
+ final ServiceDescriptor[] descs, final Configuration config,
+ final LoginContext loginContext )
+ throws Exception
+ {
+ logger.entering( ServiceStarter.class.getName(),
+ "createWithLogin", new Object[]{ descs, config, loginContext } );
+ loginContext.login();
+ Result[] results = null;
+ try
+ {
+ results = (Result[]) Subject.doAsPrivileged(
+ loginContext.getSubject(),
+ new PrivilegedExceptionAction()
+ {
+ public Object run()
+ throws Exception
+ {
+ return create( descs, config );
+ }
+ },
+ null );
+ }
+ catch( PrivilegedActionException pae )
+ {
+ throw pae.getException();
+ }
+ finally
+ {
+ try
+ {
+ loginContext.logout();
+ }
+ catch( LoginException le )
+ {
+ logger.log( Level.FINE, "service.logout.exception", le );
+ }
+ }
+ logger.exiting( ServiceStarter.class.getName(),
+ "createWithLogin", results );
+ return results;
+ }
+
+ /**
+ * Generic service creation method that attempts to start the
+ * services defined by the provided <code>ServiceDescriptor[]</code>
+ * argument.
+ *
+ * @param descs The <code>ServiceDescriptor[]</code> that contains
+ * the descriptors for the services to start.
+ * @param config The associated <code>Configuration</code> object
+ * used to customize the service creation process.
+ * @return Returns a <code>Result[]</code> that is the same length as
+ * <code>descs</code>, which contains the details for each
+ * service creation attempt.
+ * @throws Exception If there was a problem creating the service.
+ * @see Result
+ * @see ServiceDescriptor
+ * @see net.jini.config.Configuration
+ */
+ private static Result[] create( final ServiceDescriptor[] descs,
+ final Configuration config )
+ throws Exception
+ {
+ logger.entering( ServiceStarter.class.getName(), "create",
+ new Object[]{ descs, config } );
+ ArrayList proxies = new ArrayList();
+
+ Object result = null;
+ Exception problem = null;
+ ServiceDescriptor desc = null;
+ for( int i = 0; i < descs.length; i++ )
+ {
+ desc = descs[ i ];
+ result = null;
+ problem = null;
+ try
+ {
+ if( desc != null )
+ {
+ result = desc.create( config );
+ }
+ }
+ catch( Exception e )
+ {
+ problem = e;
+ }
+ finally
+ {
+ proxies.add( new Result( desc, result, problem ) );
+ }
+ }
+
+ logger.exiting( ServiceStarter.class.getName(), "create", proxies );
+ return (Result[]) proxies.toArray( new Result[proxies.size()] );
+ }
+
+ /**
+ * Utility routine that sets a security manager if one isn't already
+ * present.
+ */
+ synchronized static void ensureSecurityManager()
+ {
+ if( System.getSecurityManager() == null )
+ {
+ System.setSecurityManager( new RMISecurityManager() );
+ }
+ }
+
+ /**
+ * Utility routine that returns a "prepared" activation system
+ * proxy for a system at the given <code>host</code> and
+ * <code>port</code>.
+ *
+ * @param host The host of the desired activation system
+ * @param port The port of the desired activation system
+ * @param config The <code>Configuration</code> used to
+ * prepare the system proxy.
+ * @return A prepared activation system proxy
+ * @throws ActivationException If there was a problem
+ * communicating with the activation
+ * system.
+ * @see net.jini.config.Configuration
+ */
+ static ActivationSystem getActivationSystem(
+ String host, int port, Configuration config )
+ throws ActivationException, ConfigurationException
+ {
+ if( config == null )
+ {
+ throw new NullPointerException(
+ "Configuration argument cannot be null" );
+ }
+
+ ActivationSystem sys = null;
+ final String h = ( host == null ) ? "" : host;
+ final int p = ( port <= 0 ) ? getActivationSystemPort() : port;
+ try
+ {
+ sys = (ActivationSystem)
+ Naming.lookup( "//" + h + ":" + p +
+ "/java.rmi.activation.ActivationSystem" );
+ ProxyPreparer activationSystemPreparer =
+ (ProxyPreparer) Config.getNonNullEntry( config,
+ START_PACKAGE, "activationSystemPreparer",
+ ProxyPreparer.class, new BasicProxyPreparer() );
+ sys = (ActivationSystem) activationSystemPreparer.prepareProxy( sys );
+ }
+ catch( Exception e )
+ {
+ throw new ActivationException(
+ "ActivationSystem @ " + host + ":" + port +
+ " could not be obtained", e );
+ }
+ return sys;
+ }
+
+ /**
+ * Utility routine that returns a "default" activation system
+ * port. The default port is determined by:
+ * <UL>
+ * <LI> the value of the <code>java.rmi.activation.port</code>
+ * system property, if set
+ * <LI> the value of <code>ActivationSystem.SYSTEM_PORT</code>
+ * </UL>
+ *
+ * @return The activation system port
+ * @see java.rmi.activation.ActivationSystem
+ */
+ static int getActivationSystemPort()
+ {
+ return ( (Integer) java.security.AccessController.doPrivileged(
+ new GetIntegerAction( "java.rmi.activation.port",
+ ActivationSystem.SYSTEM_PORT ) ) ).intValue();
+ }
+
+ /**
+ * Utility routine that maintains strong references to any
+ * transient services in the provided <code>Result[]</code>.
+ * This prevents the transient services from getting garbage
+ * collected.
+ */
+ private static void maintainNonActivatableReferences( Result[] results )
+ {
+ logger.entering( ServiceStarter.class.getName(),
+ "maintainNonActivatableReferences", (Object[]) results );
+ if( results.length == 0 )
+ {
+ return;
+ }
+ transient_service_refs = new ArrayList();
+ for( int i = 0; i < results.length; i++ )
+ {
+ if( results[ i ] != null &&
+ results[ i ].result != null &&
+ NonActivatableServiceDescriptor.class.equals(
+ results[ i ].descriptor.getClass() ) )
+ {
+ logger.log( Level.FINEST, "Storing ref to: {0}",
+ results[ i ].result );
+ transient_service_refs.add( results[ i ].result );
+ }
+ }
+//TODO - kick off daemon thread to maintain refs via LifeCycle object
+ logger.exiting( ServiceStarter.class.getName(),
+ "maintainNonActivatableReferences" );
+ return;
+ }
+
+ /**
+ * Utility routine that prints out warning messages for each service
+ * descriptor that produced an exception or that was null.
+ */
+ private static void checkResultFailures( Result[] results )
+ {
+ logger.entering( ServiceStarter.class.getName(),
+ "checkResultFailures", (Object[]) results );
+ if( results.length == 0 )
+ {
+ return;
+ }
+ for( int i = 0; i < results.length; i++ )
+ {
+ if( results[ i ].exception != null )
+ {
+ logger.log( Level.WARNING,
+ "service.creation.unknown",
+ results[ i ].exception );
+ logger.log( Level.WARNING,
+ "service.creation.unknown.detail",
+ new Object[]{ new Integer( i ),
+ results[ i ].descriptor } );
+ }
+ else if( results[ i ].descriptor == null )
+ {
+ logger.log( Level.WARNING,
+ "service.creation.null", new Integer( i ) );
+ }
+ }
+ logger.exiting( ServiceStarter.class.getName(),
+ "checkResultFailures" );
+ }
+
+
+ /**
+ * The main method for the <code>ServiceStarter</code> application.
+ * The <code>args</code> argument is passed directly to
+ * <code>ConfigurationProvider.getInstance()</code> in order to
+ * obtain a <code>Configuration</code> object. This configuration
+ * object is then queried for the
+ * <code>com.sun.jini.start.serviceDescriptors</code> entry, which
+ * is assumed to be a <code>ServiceDescriptor[]</code>.
+ * The <code>create()</code> method is then called on each of the array
+ * elements.
+ *
+ * @param args <code>String[]</code> passed to
+ * <code>ConfigurationProvider.getInstance()</code> in order
+ * to obtain a <code>Configuration</code> object.
+ * @see ServiceDescriptor
+ * @see SharedActivatableServiceDescriptor
+ * @see SharedActivationGroupDescriptor
+ * @see NonActivatableServiceDescriptor
+ * @see net.jini.config.Configuration
+ * @see net.jini.config.ConfigurationProvider
+ */
+ public static void main( String[] args )
+ {
+ ensureSecurityManager();
+ try
+ {
+ logger.entering( ServiceStarter.class.getName(),
+ "main", (Object[]) args );
+ Configuration config = ConfigurationProvider.getInstance( args );
+ ServiceDescriptor[] descs = (ServiceDescriptor[])
+ config.getEntry( START_PACKAGE, "serviceDescriptors",
+ ServiceDescriptor[].class, null );
+ if( descs == null || descs.length == 0 )
+ {
+ logger.warning( "service.config.empty" );
+ return;
+ }
+ LoginContext loginContext = (LoginContext)
+ config.getEntry( START_PACKAGE, "loginContext",
+ LoginContext.class, null );
+ Result[] results = null;
+ if( loginContext != null )
+ {
+ results = createWithLogin( descs, config, loginContext );
+ }
+ else
+ {
+ results = create( descs, config );
+ }
+ checkResultFailures( results );
+ maintainNonActivatableReferences( results );
+ }
+ catch( ConfigurationException cex )
+ {
+ logger.log( Level.SEVERE, "service.config.exception", cex );
+ }
+ catch( Exception e )
+ {
+ logger.log( Level.SEVERE, "service.creation.exception", e );
+ }
+ logger.exiting( ServiceStarter.class.getName(),
+ "main" );
+ }
+
+}//end class ServiceStarter