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>&lt;impl&gt;(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">&#X2022;</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * servicePreparer</code></font>
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Type: <td> {@link net.jini.security.ProxyPreparer}
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Default: <td> <code>
+ * new {@link net.jini.security.BasicProxyPreparer}()
+ * </code>
+ * <tr valign="top"> <td> &nbsp <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>&lt;impl&gt;(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>&lt;impl&gt;.getServiceProxy()</code>,
+ * if supported, where <code>&lt;impl&gt;</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>&lt;act_ref&gt;.getServiceProxy()</code>,
+ * if supported, where <code>&lt;act_ref&gt;</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">&#X2022;</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * loginContext</code></font>
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Type: <td> {@link javax.security.auth.login.LoginContext}
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Default: <td> <code>null</code>
+ * <tr valign="top"> <td> &nbsp <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">&#X2022;</font>
+ * <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ * serviceDescriptors</code></font>
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Type: <td> {@link ServiceDescriptor}[]
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Default: no default
+ * <tr valign="top"> <td> &nbsp <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