river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject svn commit: r724983 [1/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...
Date Wed, 10 Dec 2008 05:15:49 GMT
Author: niclas
Date: Tue Dec  9 21:15:48 2008
New Revision: 724983

URL: http://svn.apache.org/viewvc?rev=724983&view=rev
Log:
A first cut at the modularization of River Experiment. More refactorings to follow. Seems I need a multi-part commit, as SVN is complaining about individual files.

Added:
    incubator/river/jtsk/skunk/niclas1/services/start/
    incubator/river/jtsk/skunk/niclas1/services/start/pom.xml
    incubator/river/jtsk/skunk/niclas1/services/start/src/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ActivateWrapper.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/AggregatePolicyProvider.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ClassLoaderUtil.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/DestroySharedGroup.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/HTTPDStatus.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LifeCycle.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/LoaderSplitPolicyProvider.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/NonActivatableServiceDescriptor.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ProxyVerifier.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceDescriptor.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceProxyAccessor.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ServiceStarter.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedActivatableServiceDescriptor.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedActivationGroupDescriptor.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedActivationPolicyPermission.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedGroup.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedGroupBackEnd.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/SharedGroupImpl.java
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/build.xml
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/package.html
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/resources/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/resources/service.properties
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/resources/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/resources/configentry/
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/resources/configentry/start
    incubator/river/jtsk/skunk/niclas1/services/start/src/main/resources/start.mf
    incubator/river/jtsk/skunk/niclas1/services/start/src/test/
    incubator/river/jtsk/skunk/niclas1/services/start/src/test/java/
    incubator/river/jtsk/skunk/niclas1/services/start/src/test/resources/

Added: incubator/river/jtsk/skunk/niclas1/services/start/pom.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/pom.xml?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/pom.xml (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/pom.xml Tue Dec  9 21:15:48 2008
@@ -0,0 +1,43 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.river.service</groupId>
+    <artifactId>master-services</artifactId>
+    <version>10.0-SNAPSHOT</version>
+  </parent>
+  <groupId>org.apache.river.service</groupId>
+  <artifactId>river-start</artifactId>
+  <name>Apache River - Service - Start</name>
+  <packaging>jar</packaging>
+  <version>10.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-activation</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-config</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-id</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-jeri</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.shared</groupId>
+      <artifactId>river-system</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>

Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ActivateWrapper.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ActivateWrapper.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ActivateWrapper.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ActivateWrapper.java Tue Dec  9 21:15:48 2008
@@ -0,0 +1,696 @@
+/*
+ * 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.InvalidObjectException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.rmi.MarshalException;
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.activation.ActivationDesc;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationGroupID;
+import java.rmi.activation.ActivationID;
+import java.rmi.activation.ActivationSystem;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.Policy;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import net.jini.export.ProxyAccessor;
+import net.jini.id.Uuid;
+import net.jini.id.UuidFactory;
+import net.jini.loader.pref.PreferredClassLoader;
+import net.jini.security.policy.DynamicPolicy;
+import net.jini.security.policy.DynamicPolicyProvider;
+import net.jini.security.policy.PolicyFileProvider;
+
+/**
+ * A wrapper for activatable objects, providing separation of the import
+ * codebase (where the server classes are loaded from by the activation
+ * group) from the export codebase (where clients should load classes from
+ * for stubs, etc.) as well as providing an independent security policy file
+ * for each activatable object. This functionality allows multiple
+ * activatable objects to be placed in the same activation group, with each
+ * object maintaining a distinct codebase and policy.
+ * <p>
+ * This wrapper class is assumed to be available directly in the activation
+ * group VM; that is, it is assumed to be in the application classloader,
+ * the extension classloader, or the boot classloader, rather than being
+ * downloaded. Since this class also needs considerable permissions, the
+ * easiest thing to do is to make it an installed extension.
+ * <p>
+ * This wrapper class performs a security check to control what
+ * policy files can be used with a given codebase.
+ * It does this by querying the VM's (global) policy for
+ * {@link com.sun.jini.start.SharedActivationPolicyPermission}
+ * grants. The service's associated
+ * {@link com.sun.jini.start.ActivateWrapper.ActivateDesc#importLocation
+ * ActivateDesc.importLocation} is used as
+ * the {@link java.security.CodeSource}
+ * for selecting the appropriate permission set to
+ * check against. If multiple codebases are used, then all the codebases must
+ * have the necessary <code>SharedActivationPolicyPermission</code> grants.
+ * <p>
+ * An example of how to use this wrapper:
+ * <pre>
+ * URL[] importURLs = new URL[] {new URL("http://myhost:8080/service.jar")};
+ * URL[] exportURLs = new URL[] {new URL("http://myhost:8080/service-dl.jar")};
+ * ActivationID aid
+ *     = ActivateWrapper.register(
+ * 		gid,
+ * 		new ActivateWrapper.ActivateDesc(
+ * 			"foo.bar.ServiceImpl",
+ * 			importURLs,
+ * 			exportURLs,
+ * 			"http://myhost:8080/service.policy",
+ * 			new MarshalledObject(
+ *                          new String[] { "/tmp/service.config" })
+ *              ),
+ * 		true,
+ *              activationSystem);
+ * </pre>
+ * <A NAME="serviceConstructor">
+ * Clients of this wrapper service need to implement the following "activation
+ * constructor":
+ * <blockquote><pre>
+ * &lt;impl&gt;(ActivationID activationID, MarshalledObject data)
+ * </blockquote></pre>
+ * where,
+ * <UL>
+ * <LI>activationID - is the object's activation identifier
+ * <LI>data         - is the object's activation data
+ * </UL>
+ *
+ * Clients of this wrapper service can also implement
+ * {@link net.jini.export.ProxyAccessor}, which allows the service
+ * implementation to provide a remote reference of its choosing.
+ * <P>
+ * <A NAME="configEntries">
+ * This implementation of <code>ActivateWrapper</code>
+ * supports the
+ * following {@link java.security.Security} property:
+ *
+ * <table summary="Describes the com.sun.jini.start.servicePolicyProvider
+ * security property"
+ * 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>
+ * com.sun.jini.start.servicePolicyProvider</code></font>
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Default: <td> <code>
+ * "net.jini.security.policy.DynamicPolicyProvider"
+ * </code>
+ * <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ * Description: <td> The fully qualified class name of a
+ * dynamic policy provider (see {@link net.jini.security.policy.DynamicPolicy})
+ * which will be used to "wrap" all service policy files.
+ * The implementation class needs to:
+ * <UL>
+ * <LI> implement the following constructor:
+ * <blockquote><pre>
+ *   public &lt;impl&gt;(Policy servicePolicy)
+ *           </blockquote></pre>
+ * where,
+ * <UL>
+ * <LI>servicePolicy - is the service policy object to be wrapped
+ * </UL>
+ * <LI> implement {@link net.jini.security.policy.DynamicPolicy}
+ * <LI> be a public, non-interface, non-abstract class
+ * </UL>
+ *
+ * <P>
+ * A custom service policy provider can be very useful when trying to
+ * debug security related issues.
+ * <code>com.sun.jini.tool.DebugDynamicPolicyProvider</code> is an example
+ * policy provider that provides this functionality and can be located
+ * via the following URL:
+ * <A HREF="http://starterkit-examples.jini.org/">
+ * http://starterkit-examples.jini.org/
+ * </A><BR>
+ * <I>Note:</I>The custom policy implementation is assumed to be
+ * available from the system classloader of the virtual machine
+ * hosting the service. Its codebase should also be granted
+ * {@link java.security.AllPermission}.
+ * </table>
+ *
+ * @author Sun Microsystems, Inc.
+ * @see com.sun.jini.start.SharedActivationPolicyPermission
+ * @see java.rmi.activation.ActivationID
+ * @see java.rmi.MarshalledObject
+ * @see java.rmi.Remote
+ * @see java.security.CodeSource
+ * @see net.jini.export.ProxyAccessor
+ */
+
+public class ActivateWrapper implements Remote, Serializable
+{
+
+    /**
+     * Configure logger
+     */
+    static final Logger logger = Logger.getLogger( "com.sun.jini.start.wrapper" );
+    /**
+     * The <code>Policy</code> object that aggregates the individual
+     * service policy objects.
+     */
+    private static AggregatePolicyProvider globalPolicy;
+
+    /**
+     * The <code>Policy</code> object in effect at startup.
+     */
+    private static Policy initialGlobalPolicy;
+
+    /**
+     * The "wrapped" activatable object.
+     *
+     * @serial
+     */
+    private /*final*/ Object impl;
+
+    /**
+     * The parameter types for the "activation constructor".
+     */
+    private static final Class[] actTypes = {
+        ActivationID.class, MarshalledObject.class
+    };
+
+    /**
+     * Fully qualified name of custom, service policy provider
+     */
+    private static String servicePolicyProvider =
+        ( (String) AccessController.doPrivileged(
+            new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    return Security.getProperty(
+                        "com.sun.jini.start." +
+                        "servicePolicyProvider" );
+                }
+            } ) );
+
+    /**
+     * The parameter types for the
+     * "custom, service policy constructor".
+     */
+    private static final Class[] policyTypes = {
+        Policy.class
+    };
+
+    /**
+     * Descriptor for registering a "wrapped" activatable object. This
+     * descriptor gets stored as the <code>MarshalledObject</code>
+     * initialization data in the <code>ActivationDesc</code>.
+     */
+    public static class ActivateDesc implements Serializable
+    {
+
+        private static final long serialVersionUID = 2L;
+
+        /**
+         * The activatable object's class name.
+         *
+         * @serial
+         */
+        public final String className;
+        /**
+         * The codebase where the server classes are loaded from by the
+         * activation group.
+         *
+         * @serial
+         */
+        public final URL[] importLocation;
+        /**
+         * The codebase where clients should load classes from for stubs, etc.
+         *
+         * @serial
+         */
+        public final URL[] exportLocation;
+        /**
+         * The security policy filename or URL.
+         *
+         * @serial
+         */
+        public final String policy;
+        /**
+         * The activatable object's initialization data.
+         *
+         * @serial
+         */
+        public final MarshalledObject data;
+
+        /**
+         * Trivial constructor.
+         */
+        public ActivateDesc( String className,
+                             URL[] importLocation,
+                             URL[] exportLocation,
+                             String policy,
+                             MarshalledObject data )
+        {
+//TODO - clone non-String objects?
+            this.className = className;
+            this.importLocation = importLocation;
+            this.exportLocation = exportLocation;
+            this.policy = policy;
+            this.data = data;
+        }
+
+        // Javadoc inherited from supertype
+        public String toString()
+        {
+            return "[className=" + className + ","
+                   + "importLocation="
+                   + ( ( importLocation == null )
+                       ? null : Arrays.asList( importLocation ) )
+                   + ","
+                   + "exportLocation="
+                   + ( ( exportLocation == null )
+                       ? null : Arrays.asList( exportLocation ) )
+                   + ","
+                   + "policy=" + policy + ","
+                   + "data=" + data + "]";
+        }
+    }
+
+    /**
+     * A simple subclass of <code>PreferredClassLoader</code> that overrides
+     * <code>getURLs</code> to
+     * return the <code>URL</code>s of the provided export codebase.
+     * <code>getURLs</code>
+     * is called by the RMI subsystem in order to annotate objects
+     * leaving the virtual machine.
+     */
+    /* 
+     * Implementation note. Subclasses of this class that override 
+     * getClassAnnotation might need to override getURLs because getURLs
+     * uses a "cached" version of the export annotation.
+     */
+    static class ExportClassLoader extends PreferredClassLoader
+    {
+        /**
+         * Cached value of the provided export codebase <code>URL</code>s
+         */
+        private final URL[] exportURLs;
+
+        /**
+         * Id field used to make toString() unique
+         */
+        private final Uuid id = UuidFactory.generate();
+
+        /**
+         * Trivial constructor that calls
+         * <pre>
+         * super(importURLs, parent, urlsToPath(exportURLs), false);
+         * </pre>
+         * and assigns <code>exportURLs</code> to an internal field.
+         */
+        public ExportClassLoader( URL[] importURLs, URL[] exportURLs,
+                                  ClassLoader parent )
+        {
+            super( importURLs, parent, urlsToPath( exportURLs ), false );
+            // Not safe to call getClassAnnotation() w/i cons if subclassed,
+            // so need to redo "super" logic here.
+            if( exportURLs == null )
+            {
+                this.exportURLs = importURLs;
+            }
+            else
+            {
+                this.exportURLs = exportURLs;
+            }
+        }
+
+        //Javadoc inherited from super type
+        public URL[] getURLs()
+        {
+            return (URL[]) exportURLs.clone();
+        }
+
+        // Javadoc inherited from supertype
+        public String toString()
+        {
+            URL[] urls = super.getURLs();
+            return this.getClass().getName()
+                   + "[importURLs="
+                   + ( urls == null ? null : Arrays.asList( urls ) )
+                   + ","
+                   + "exportURLs="
+                   + ( exportURLs == null ? null : Arrays.asList( exportURLs ) )
+                   + ","
+                   + "parent=" + getParent()
+                   + ","
+                   + "id=" + id
+                   + "]";
+        }
+    }
+
+    /**
+     * Activatable constructor. This constructor:
+     * <UL>
+     * <LI>Retrieves an <code>ActivateDesc</code> from the
+     * provided <code>data</code> parameter.
+     * <LI>creates an <code>ExportClassLoader</code> using the
+     * import and export codebases obtained from the provided
+     * <code>ActivateDesc</code>,
+     * <LI>checks the import codebase(s) for the required
+     * <code>SharedActivationPolicyPermission</code>
+     * <LI>associates the newly created <code>ExportClassLoader</code>
+     * and the corresponding policy file obtained from the
+     * <code>ActivateDesc</code> with the
+     * <code>AggregatePolicyProvider</code>
+     * <LI>loads the "wrapped" activatable object's class and
+     * calls its activation constructor with the context classloader
+     * set to the newly created <code>ExportClassLoader</code>.
+     * <LI> resets the context class loader to the original
+     * context classloader
+     * </UL>
+     * The first instance of this class will also replace the VM's
+     * existing <code>Policy</code> object, if any,
+     * with a <code>AggregatePolicyProvider</code>.
+     *
+     * @param id   The <code>ActivationID</code> of this object
+     * @param data The activation data for this object
+     * @see com.sun.jini.start.ActivateWrapper.ExportClassLoader
+     * @see com.sun.jini.start.ActivateWrapper.ActivateDesc
+     * @see com.sun.jini.start.AggregatePolicyProvider
+     * @see com.sun.jini.start.SharedActivationPolicyPermission
+     * @see java.security.Policy
+     */
+    public ActivateWrapper( ActivationID id, MarshalledObject data )
+        throws Exception
+    {
+        try
+        {
+            logger.entering( ActivateWrapper.class.getName(),
+                             "ActivateWrapper", new Object[]{ id, data } );
+
+            ActivateDesc desc = (ActivateDesc) data.get();
+            logger.log( Level.FINEST, "ActivateDesc: {0}", desc );
+
+            Thread t = Thread.currentThread();
+            ClassLoader ccl = t.getContextClassLoader();
+            logger.log( Level.FINEST, "Saved current context class loader: {0}",
+                        ccl );
+
+            ExportClassLoader cl = null;
+            try
+            {
+                cl = new ExportClassLoader( desc.importLocation,
+                                            desc.exportLocation,
+                                            ccl );
+                logger.log( Level.FINEST, "Created ExportClassLoader: {0}", cl );
+            }
+            catch( Exception e )
+            {
+                logger.throwing( ActivateWrapper.class.getName(),
+                                 "ActivateWrapper", e );
+                throw e;
+            }
+
+            checkPolicyPermission( desc.policy, desc.importLocation );
+
+            synchronized( ActivateWrapper.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 =
+                    getServicePolicyProvider(
+                        new PolicyFileProvider( desc.policy ) );
+                Policy backstop_policy =
+                    getServicePolicyProvider( initialGlobalPolicy );
+                LoaderSplitPolicyProvider split_service_policy =
+                    new LoaderSplitPolicyProvider(
+                        cl, 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( cl, split_service_policy );
+                logger.log( Level.FINEST,
+                            "Added policy to set: {0}", desc.policy );
+            }
+
+            boolean initialize = false;
+            Class ac = Class.forName( desc.className, initialize, cl );
+            logger.log( Level.FINEST, "Obtained implementation class: {0}", ac );
+
+            t.setContextClassLoader( cl );
+
+            try
+            {
+                logger.log( Level.FINEST,
+                            "Set new context class loader: {0}", cl );
+                Constructor constructor =
+                    ac.getDeclaredConstructor( actTypes );
+                logger.log( Level.FINEST,
+                            "Obtained implementation constructor: {0}",
+                            constructor );
+                constructor.setAccessible( true );
+                impl =
+                    constructor.newInstance( new Object[]{ id, desc.data } );
+                logger.log( Level.FINEST,
+                            "Obtained implementation instance: {0}", impl );
+            }
+            finally
+            {
+                t.setContextClassLoader( ccl );
+                logger.log( Level.FINEST, "Context class loader reset to: {0}",
+                            ccl );
+            }
+        }
+        catch( Exception e )
+        {
+            logger.throwing( ActivateWrapper.class.getName(),
+                             "ActivateWrapper", e );
+            throw e;
+        }
+        logger.exiting( ActivateWrapper.class.getName(),
+                        "ActivateWrapper" );
+    }
+
+
+    /**
+     * Return a reference to service being wrapped in place
+     * of this object.
+     */
+    private Object writeReplace() throws ObjectStreamException
+    {
+        Object impl_proxy = impl;
+        if( impl instanceof ProxyAccessor )
+        {
+            impl_proxy = ( (ProxyAccessor) impl ).getProxy();
+            logger.log( Level.FINEST,
+                        "Obtained implementation proxy: {0}", impl_proxy );
+            if( impl_proxy == null )
+            {
+                throw new InvalidObjectException(
+                    "Implementation's getProxy() returned null" );
+            }
+        }
+        return impl_proxy;
+    }
+
+    /**
+     * Analog to
+     * {@link java.rmi.activation.Activatable#register(java.rmi.activation.ActivationDesc)
+     * Activatable.register()} for activatable objects that want
+     * to use this wrapper mechanism.
+     *
+     * @return activation ID of the registered service
+     * @throws ActivationException if there was a problem registering
+     *                             the activatable class with the activation system
+     * @throws RemoteException     if there was a problem communicating
+     *                             with the activation system
+     */
+    public static ActivationID register( ActivationGroupID gid,
+                                         ActivateDesc desc,
+                                         boolean restart,
+                                         ActivationSystem sys )
+        throws ActivationException, RemoteException
+    {
+        logger.entering( ActivateWrapper.class.getName(),
+                         "register", new Object[]{ gid, desc, Boolean.valueOf( restart ), sys } );
+
+        MarshalledObject data;
+        try
+        {
+            data = new MarshalledObject( desc );
+        }
+        catch( Exception e )
+        {
+            MarshalException me =
+                new MarshalException( "marshalling ActivateDesc", e );
+            logger.throwing( ActivateWrapper.class.getName(),
+                             "register", me );
+            throw me;
+        }
+
+        ActivationDesc adesc =
+            new ActivationDesc( gid,
+                                ActivateWrapper.class.getName(),
+                                null,
+                                data,
+                                restart
+            );
+        logger.log( Level.FINEST,
+                    "Registering descriptor with activation: {0}", adesc );
+
+        ActivationID aid = sys.registerObject( adesc );
+
+        logger.exiting( ActivateWrapper.class.getName(),
+                        "register", aid );
+        return aid;
+    }
+
+    /**
+     * Checks that all the provided <code>URL</code>s have permission to
+     * use the given policy.
+     */
+    private static void checkPolicyPermission( String policy, URL[] urls )
+    {
+        logger.entering( ActivateWrapper.class.getName(),
+                         "checkPolicyPermission", new Object[]{ policy, urlsToPath( urls ) } );
+        // Create desired permission object
+        Permission perm = new SharedActivationPolicyPermission( policy );
+        Certificate[] certs = null;
+        CodeSource cs = null;
+        ProtectionDomain pd = null;
+        // Loop over all codebases
+        for( int i = 0; i < urls.length; i++ )
+        {
+            // Create ProtectionDomain for given codesource
+            cs = new CodeSource( urls[ i ], certs );
+            pd = new ProtectionDomain( cs, null, null, null );
+            logger.log( Level.FINEST,
+                        "Checking protection domain: {0}", pd );
+
+            // Check if current domain allows desired permission
+            if( !pd.implies( perm ) )
+            {
+                SecurityException se = new SecurityException(
+                    "ProtectionDomain " + pd
+                    + " does not have required permission: " + perm );
+                logger.throwing( ActivateWrapper.class.getName(),
+                                 "checkPolicyPermission", se );
+                throw se;
+            }
+        }
+        logger.exiting( ActivateWrapper.class.getName(),
+                        "checkPolicyPermission" );
+    }
+
+    /**
+     * Utility method that converts a <code>URL[]</code>
+     * into a corresponding, space-separated string with
+     * the same array elements.
+     *
+     * Note that if the array has zero elements, the return value is
+     * null, not the empty string.
+     */
+    private static String urlsToPath( URL[] urls )
+    {
+//TODO - check if spaces in file paths are properly escaped (i.e.% chars)	
+        if( urls == null )
+        {
+            return null;
+        }
+        else if( urls.length == 0 )
+        {
+            return "";
+        }
+        else if( urls.length == 1 )
+        {
+            return urls[ 0 ].toExternalForm();
+        }
+        else
+        {
+            StringBuffer path = new StringBuffer( urls[ 0 ].toExternalForm() );
+            for( int i = 1; i < urls.length; i++ )
+            {
+                path.append( ' ' );
+                path.append( urls[ i ].toExternalForm() );
+            }
+            return path.toString();
+        }
+    }
+
+    static Policy getServicePolicyProvider( Policy service_policy ) throws Exception
+    {
+        Policy servicePolicyWrapper = null;
+        if( servicePolicyProvider != null )
+        {
+            Class sp = Class.forName( servicePolicyProvider );
+            logger.log( Level.FINEST,
+                        "Obtained custom service policy implementation class: {0}", sp );
+            Constructor constructor =
+                sp.getConstructor( policyTypes );
+            logger.log( Level.FINEST,
+                        "Obtained custom service policy implementation constructor: {0}",
+                        constructor );
+            servicePolicyWrapper = (Policy)
+                constructor.newInstance( new Object[]{ service_policy } );
+            logger.log( Level.FINEST,
+                        "Obtained custom service policy implementation instance: {0}",
+                        servicePolicyWrapper );
+        }
+        else
+        {
+            servicePolicyWrapper = new DynamicPolicyProvider( service_policy );
+            logger.log( Level.FINEST,
+                        "Using default service policy implementation instance: {0}",
+		servicePolicyWrapper);
+	}
+	return servicePolicyWrapper;
+    }
+
+
+}

Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/AggregatePolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/AggregatePolicyProvider.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/AggregatePolicyProvider.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/AggregatePolicyProvider.java Tue Dec  9 21:15:48 2008
@@ -0,0 +1,641 @@
+/*
+ * 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.lang.reflect.Method;
+import java.security.AccessControlContext;
+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.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.Security;
+import java.security.SecurityPermission;
+import java.util.Map;
+import java.util.WeakHashMap;
+import net.jini.security.SecurityContext;
+import net.jini.security.policy.DynamicPolicy;
+import net.jini.security.policy.PolicyInitializationException;
+import net.jini.security.policy.SecurityContextSource;
+
+/**
+ * Security policy provider which supports associating security sub-policies
+ * with context class loaders.  Permission queries and grants (if supported),
+ * as well as <code>implies</code> and <code>refresh</code> operations are
+ * delegated to the currently active sub-policy.
+ * <p>
+ * The currently active sub-policy is determined as follows: if the current
+ * thread does not override the {@link Thread#getContextClassLoader
+ * getContextClassLoader} method, then that method is called to obtain the
+ * context class loader.  If the context class loader is associated with a
+ * sub-policy (via a previous call to <code>setPolicy</code>), then that
+ * sub-policy is the currently active sub-policy.  If no such association
+ * exists, then the same check is performed on each non-<code>null</code>
+ * parent of the context class loader, proceeding up the chain of class loader
+ * delegation, until a sub-policy association is found, in which case the
+ * associated sub-policy is the currently active sub-policy.  If no sub-policy
+ * association is found for the context class loader or any of its parents,
+ * then a fallback sub-policy, the main policy, is the currently active
+ * sub-policy.  Also, if the current thread overrides the
+ * <code>getContextClassLoader</code> method, then
+ * <code>getContextClassLoader</code> is not called and the main policy is the
+ * currently active sub-policy.
+ *
+ * @author Sun Microsystems, Inc.
+ * @since 2.0
+ */
+public class AggregatePolicyProvider
+    extends Policy implements DynamicPolicy, SecurityContextSource
+{
+    private static final String mainPolicyClassProperty =
+        "com.sun.jini.start.AggregatePolicyProvider.mainPolicyClass";
+    private static final String defaultMainPolicyClass =
+        "net.jini.security.policy.DynamicPolicyProvider";
+
+    private static final Map trustGetCCL = new WeakHashMap();
+    private static final ProtectionDomain myDomain = (ProtectionDomain)
+        AccessController.doPrivileged( new PrivilegedAction()
+        {
+            public Object run()
+            {
+                return AggregatePolicyProvider.class.getProtectionDomain();
+            }
+        } );
+
+    private WeakIdentityMap subPolicies = new WeakIdentityMap();
+    private WeakIdentityMap subPolicyCache = new WeakIdentityMap();
+    private Policy mainPolicy;
+
+    /**
+     * Creates a new <code>AggregatePolicyProvider</code> instance, containing
+     * a main policy created as follows: if the
+     * <code>com.sun.jini.start.AggregatePolicyProvider.mainPolicyClass</code>
+     * security property is set, then its value is interpreted as the class
+     * name of the main policy provider; otherwise, a default class name of
+     * <code>"net.jini.security.policy.DynamicPolicyProvider"</code>
+     * is used.  The main policy is then instantiated using the no-arg public
+     * constructor of the named class.  If the main policy class is not found,
+     * is not instantiable via a public no-arg constructor, or if invocation of
+     * its constructor fails, then a <code>PolicyInitializationException</code>
+     * is thrown.
+     * <p>
+     * Note that this constructor requires the appropriate
+     * <code>"getProperty"</code> {@link SecurityPermission} to read the
+     * <code>com.sun.jini.start.AggregatePolicyProvider.mainPolicyClass</code>
+     * security property, and may require <code>"accessClassInPackage.*"</code>
+     * {@link RuntimePermission}s, depending on the package of the main policy
+     * class.
+     *
+     * @throws PolicyInitializationException if unable to construct the main
+     *                                       policy
+     * @throws SecurityException             if there is a security manager and the
+     *                                       calling context does not have <code>SecurityPermission</code>
+     *                                       for reading the
+     *                                       <code>com.sun.jini.start.AggregatePolicyProvider.mainPolicy</code>
+     *                                       security property, or if the calling context does not have
+     *                                       adequate permissions to access the main policy class
+     */
+    public AggregatePolicyProvider() throws PolicyInitializationException
+    {
+        String cname = Security.getProperty( mainPolicyClassProperty );
+        if( cname == null )
+        {
+            cname = defaultMainPolicyClass;
+        }
+        try
+        {
+            mainPolicy = (Policy) Class.forName( cname ).newInstance();
+        }
+        catch( SecurityException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            throw new PolicyInitializationException(
+                "unable to construct main policy", e );
+        }
+        ensureDependenciesResolved();
+    }
+
+    /**
+     * Creates a new <code>AggregatePolicyProvider</code> instance with the
+     * given main policy, which must be non-<code>null</code>.
+     *
+     * @param mainPolicy main policy
+     * @throws NullPointerException if main policy is <code>null</code>
+     */
+    public AggregatePolicyProvider( Policy mainPolicy )
+    {
+        if( mainPolicy == null )
+        {
+            throw new NullPointerException();
+        }
+        this.mainPolicy = mainPolicy;
+        ensureDependenciesResolved();
+    }
+
+    /**
+     * Delegates to the corresponding <code>getPermissions</code> method of the
+     * currently active sub-policy to return the set of permissions allowed for
+     * code from the specified code source, as a newly-created mutable
+     * <code>PermissionCollection</code> which supports heterogeneous
+     * permission types.
+     *
+     * @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 getCurrentSubPolicy().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.  Otherwise, delegates to the corresponding
+     * <code>getPermissions</code> method of the currently active sub-policy to
+     * return the set of permissions allowed for code in the specified
+     * protection domain, as a newly-created mutable
+     * <code>PermissionCollection</code> which supports heterogeneous
+     * permission types.
+     *
+     * @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 getCurrentSubPolicy().getPermissions( domain );
+        }
+    }
+
+    /**
+     * If the given protection domain is the protection domain of this class,
+     * then <code>true</code> is returned.  Otherwise, delegates to the
+     * <code>implies</code> method of the currently active sub-policy to
+     * determine if the given permission is implied by the permissions for the
+     * specified protection domain.
+     *
+     * @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 ) ||
+               getCurrentSubPolicy().implies( domain, permission );
+    }
+
+    /**
+     * Refreshes the currently active sub-policy by delegating to its
+     * <code>refresh</code> method.
+     */
+    public void refresh()
+    {
+        getCurrentSubPolicy().refresh();
+    }
+
+    /**
+     * Changes sub-policy association with given class loader.  If
+     * <code>subPolicy</code> is non-<code>null</code>, then it is used as a
+     * new sub-policy to associate with the given class loader, overriding any
+     * previous sub-policy associated with the loader.  If
+     * <code>subPolicy</code> is <code>null</code>, then any previous
+     * association between a sub-policy and the given class loader is removed.
+     * If loader is <code>null</code>, then <code>subPolicy</code> is used as
+     * the new main policy, and must be non-<code>null</code>.  If there is a
+     * security manager, its <code>checkPermission</code> method is called with
+     * the <code>"setPolicy"</code> {@link SecurityPermission}.
+     *
+     * @param loader    class loader with which to associate sub-policy, or
+     *                  <code>null</code> if setting main policy
+     * @param subPolicy sub-policy to associate with given class loader, or
+     *                  <code>null</code> if removing sub-policy association
+     * @throws NullPointerException if both <code>loader</code> and
+     *                              <code>subPolicy</code> are <code>null</code>
+     * @throws SecurityException    if there is a security manager and the
+     *                              calling context does not have the <code>"setPolicy"
+     *                              SecurityPermission</code>
+     */
+    public void setPolicy( ClassLoader loader, Policy subPolicy )
+    {
+        SecurityManager sm = System.getSecurityManager();
+        if( sm != null )
+        {
+            sm.checkPermission( new SecurityPermission( "setPolicy" ) );
+        }
+        synchronized( subPolicies )
+        {
+            subPolicyCache.clear();
+            if( loader != null )
+            {
+                if( subPolicy != null )
+                {
+                    subPolicies.put( loader, subPolicy );
+                    subPolicyCache.put( loader, subPolicy );
+                }
+                else
+                {
+                    subPolicies.remove( loader );
+                }
+            }
+            else
+            {
+                if( subPolicy == null )
+                {
+                    throw new NullPointerException();
+                }
+                mainPolicy = subPolicy;
+            }
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if the currently active sub-policy supports
+     * dynamic grants; this is determined by delegating to the
+     * <code>grantSupported</code> method of the currently active sub-policy if
+     * it implements the {@link DynamicPolicy} interface.  If the currently
+     * active sub-policy does not implement <code>DynamicPolicy</code>, then
+     * <code>false</code> is returned.
+     *
+     * @return <code>true</code> if the currently active sub-policy supports
+     *         dynamic grants, or <code>false</code> otherwise
+     */
+    public boolean grantSupported()
+    {
+        Policy p = getCurrentSubPolicy();
+        return ( p instanceof DynamicPolicy &&
+                 ( (DynamicPolicy) p ).grantSupported() );
+    }
+
+    /**
+     * If the currently active sub-policy supports dynamic permission grants,
+     * delegates to the corresponding <code>grant</code> method of the
+     * currently active sub-policy to grant the specified permissions to all
+     * protection domains (including ones not yet created) which are associated
+     * with the class loader of the given class and possess at least the given
+     * set of principals.
+     *
+     * @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 )
+    {
+        Policy p = getCurrentSubPolicy();
+        if( p instanceof DynamicPolicy )
+        {
+            ( (DynamicPolicy) p ).grant( cl, principals, permissions );
+        }
+        else
+        {
+            throw new UnsupportedOperationException( "grants not supported" );
+        }
+    }
+
+    /**
+     * If the currently active sub-policy supports dynamic permission grants,
+     * delegates to the corresponding <code>getGrants</code> method of the
+     * currently active sub-policy to return a new array containing the set of
+     * permissions dynamically granted to protection domains which are
+     * associated with the class loader of the given class and possess at least
+     * the given set of principals.
+     *
+     * @param cl         {@inheritDoc}
+     * @param principals {@inheritDoc}
+     * @return {@inheritDoc}
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public Permission[] getGrants( Class cl, Principal[] principals )
+    {
+        Policy p = getCurrentSubPolicy();
+        if( p instanceof DynamicPolicy )
+        {
+            return ( (DynamicPolicy) p ).getGrants( cl, principals );
+        }
+        else
+        {
+            throw new UnsupportedOperationException( "grants not supported" );
+        }
+    }
+
+    /**
+     * Returns a snapshot of the current security context, which can be used to
+     * restore the context at a later time.
+     * <p>
+     * The security context returned by this method contains the security
+     * context of the currently active sub-policy (or an equivalent of the
+     * default security context described in the documentation for {@link
+     * net.jini.security.Security#getContext
+     * Security.getContext}, if the currently active sub-policy does not
+     * implement {@link SecurityContextSource}), as well as the current context
+     * class loader.  The privileged action wrappers it creates restore the
+     * saved context class loader before delegating to the action wrappers of
+     * the underlying sub-policy security context.  The
+     * <code>getAccessControlContext</code> method of the returned security
+     * context delegates to the corresponding method of the sub-policy security
+     * context.
+     *
+     * @return {@inheritDoc}
+     */
+    public SecurityContext getContext()
+    {
+        Policy p = getCurrentSubPolicy();
+        SecurityContext sc = ( p instanceof SecurityContextSource ) ?
+                             ( (SecurityContextSource) p ).getContext() :
+                             new DefaultSecurityContext();
+        return new AggregateSecurityContext( sc );
+    }
+
+    /**
+     * 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()
+    {
+        // get any non-null class loader
+        ClassLoader ldr = getClass().getClassLoader();
+        if( ldr == null )
+        {
+            ldr = ClassLoader.getSystemClassLoader();
+        }
+
+        // force class resolution by pre-invoking methods called by implies()
+        trustGetContextClassLoader0( Thread.class );
+        getContextClassLoader();
+        synchronized( subPolicies )
+        {
+            lookupSubPolicy( ldr );
+        }
+    }
+
+    /**
+     * Returns currently active sub-policy.
+     */
+    private Policy getCurrentSubPolicy()
+    {
+        final Thread t = Thread.currentThread();
+        if( !trustGetContextClassLoader( t ) )
+        {
+            return mainPolicy;
+        }
+        ClassLoader ccl = getContextClassLoader();
+        synchronized( subPolicies )
+        {
+            Policy policy = (Policy) subPolicyCache.get( ccl );
+            if( policy == null )
+            {
+                policy = lookupSubPolicy( ccl );
+                subPolicyCache.put( ccl, policy );
+            }
+            return policy;
+        }
+    }
+
+    /**
+     * Returns sub-policy associated with the given class loader.  This method
+     * should only be called when already synchronized on subPolicies.
+     */
+    private Policy lookupSubPolicy( final ClassLoader ldr )
+    {
+        assert Thread.holdsLock( subPolicies );
+        return (Policy) AccessController.doPrivileged(
+            new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    for( ClassLoader l = ldr; l != null; l = l.getParent() )
+                    {
+                        Policy p = (Policy) subPolicies.get( l );
+                        if( p != null )
+                        {
+                            return p;
+                        }
+                    }
+                    return mainPolicy;
+                }
+            } );
+    }
+
+    /**
+     * Returns current context class loader.
+     */
+    static ClassLoader getContextClassLoader()
+    {
+        return (ClassLoader) AccessController.doPrivileged(
+            new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    return Thread.currentThread().getContextClassLoader();
+                }
+            } );
+    }
+
+    /**
+     * Returns true if the given thread does not override
+     * Thread.getContextClassLoader(), false otherwise.
+     */
+    private static boolean trustGetContextClassLoader( Thread t )
+    {
+        Class cl = t.getClass();
+        if( cl == Thread.class )
+        {
+            return true;
+        }
+
+        Boolean b;
+        synchronized( trustGetCCL )
+        {
+            b = (Boolean) trustGetCCL.get( cl );
+        }
+        if( b == null )
+        {
+            b = trustGetContextClassLoader0( cl );
+            synchronized( trustGetCCL )
+            {
+                trustGetCCL.put( cl, b );
+            }
+        }
+        return b.booleanValue();
+    }
+
+    private static Boolean trustGetContextClassLoader0( final Class cl )
+    {
+        return (Boolean) AccessController.doPrivileged( new PrivilegedAction()
+        {
+            public Object run()
+            {
+                try
+                {
+                    Method m = cl.getMethod(
+                        "getContextClassLoader", new Class[0] );
+                    return Boolean.valueOf( m.getDeclaringClass() == Thread.class );
+                }
+                catch( NoSuchMethodException ex )
+                {
+                    throw new InternalError(
+                        "Thread.getContextClassLoader() not found" );
+                }
+            }
+        } );
+    }
+
+    /**
+     * Stand-in "default" security context for sub-policies that do not
+     * implement SecurityContextSource.
+     */
+    private static class DefaultSecurityContext implements SecurityContext
+    {
+
+        private final AccessControlContext acc =
+            AccessController.getContext();
+
+        public PrivilegedAction wrap( PrivilegedAction a )
+        {
+            if( a == null )
+            {
+                throw new NullPointerException();
+            }
+            return a;
+        }
+
+        public PrivilegedExceptionAction wrap( PrivilegedExceptionAction a )
+        {
+            if( a == null )
+            {
+                throw new NullPointerException();
+            }
+            return a;
+        }
+
+        public AccessControlContext getAccessControlContext()
+        {
+            return acc;
+        }
+    }
+
+    /**
+     * Security context that produces privileged action wrappers which restore
+     * the context class loader before delegating to the sub-policy context's
+     * wrapped action.
+     */
+    private static class AggregateSecurityContext implements SecurityContext
+    {
+
+        private final ClassLoader ccl = getContextClassLoader();
+        private final SecurityContext sc;
+
+        AggregateSecurityContext( SecurityContext sc )
+        {
+            if( sc == null )
+            {
+                throw new NullPointerException();
+            }
+            this.sc = sc;
+        }
+
+        public PrivilegedAction wrap( PrivilegedAction a )
+        {
+            final PrivilegedAction wa = sc.wrap( a );
+            return new PrivilegedAction()
+            {
+                public Object run()
+                {
+                    ClassLoader sccl = setCCL( ccl, false );
+                    try
+                    {
+                        return wa.run();
+                    }
+                    finally
+                    {
+                        setCCL( sccl, sccl != ccl );
+                    }
+                }
+            };
+        }
+
+        public PrivilegedExceptionAction wrap( PrivilegedExceptionAction a )
+        {
+            final PrivilegedExceptionAction wa = sc.wrap( a );
+            return new PrivilegedExceptionAction()
+            {
+                public Object run() throws Exception
+                {
+                    ClassLoader sccl = setCCL( ccl, false );
+                    try
+                    {
+                        return wa.run();
+                    }
+                    finally
+                    {
+                        setCCL( sccl, sccl != ccl );
+                    }
+                }
+            };
+        }
+
+        public AccessControlContext getAccessControlContext()
+        {
+            return sc.getAccessControlContext();
+        }
+
+        private ClassLoader setCCL( final ClassLoader ldr, final boolean force )
+        {
+            return (ClassLoader) AccessController.doPrivileged(
+                new PrivilegedAction()
+                {
+                    public Object run()
+                    {
+                        Thread t = Thread.currentThread();
+                        ClassLoader old = null;
+                        if( force || ldr != ( old = t.getContextClassLoader() ) )
+                        {
+                            t.setContextClassLoader( ldr );
+                        }
+                        return old;
+                    }
+		});
+	}
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ClassLoaderUtil.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ClassLoaderUtil.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ClassLoaderUtil.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/ClassLoaderUtil.java Tue Dec  9 21:15:48 2008
@@ -0,0 +1,249 @@
+/*
+ * 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.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.SecureClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.logging.Logger;
+
+/**
+ * This class provides useful utilities for creating and
+ * manipulating class loaders.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+public class ClassLoaderUtil
+{
+    /**
+     * Configure logger
+     */
+    static final Logger logger =
+        Logger.getLogger( "com.sun.jini.start.ClassLoaderUtil" );
+
+    // Private constructor to prevent instantiation
+    private ClassLoaderUtil()
+    {
+    }
+
+    /**
+     * Utility method that converts the components of a <code>String</code>
+     * representing a classpath into file <code>URL</code>(s).
+     *
+     * @param classpath <code>String</code> containing components separated
+     *                  by path separators that represent the components
+     *                  making up a classpath
+     * @return a <code>URL[]</code> where
+     *         each element of the array corresponds to one of the components
+     *         in the <code>classpath</code> parameter. The path components
+     *         are (potentially) expanded via
+     *         <code>File.getCanonicalFile()</code> before converting to a
+     *         <code>URL</code> format.
+     * @throws java.net.MalformedURLException If the path cannot be parsed as a URL
+     * @throws java.net.IOException           If an I/O error occurs,
+     *                                        which is possible because the construction of
+     *                                        the canonical pathname may require filesystem queries
+     */
+    public static URL[] getClasspathURLs( String classpath )
+        throws IOException, MalformedURLException
+    {
+        StringTokenizer st = new StringTokenizer( classpath, File.pathSeparator );
+        URL[] urls = new URL[st.countTokens()];
+        for( int i = 0; st.hasMoreTokens(); i++ )
+        {
+            urls[ i ] =
+                new File( st.nextToken() ).getCanonicalFile().toURI().toURL();
+        }
+        return urls;
+    }//end getClasspathURLs
+
+    /**
+     * Utility method that converts the components of a <code>String</code>
+     * representing a codebase into standard <code>URL</code>(s).
+     *
+     * @param codebase <code>String</code> containing components separated
+     *                 by spaces in which each component is in
+     *                 <code>URL</code> format.
+     * @return a <code>URL[]</code> where
+     *         each element of the array corresponds to one of the components
+     *         in the <code>codebase</code> parameter
+     * @throws java.net.MalformedURLException
+     */
+    public static URL[] getCodebaseURLs( String codebase )
+        throws MalformedURLException
+    {
+        StringTokenizer st = new StringTokenizer( codebase );
+        URL[] urls = new URL[st.countTokens()];
+        for( int i = 0; st.hasMoreTokens(); i++ )
+        {
+            urls[ i ] = new URL( st.nextToken() );
+        }
+        return urls;
+    }//end getCodebaseURLs
+
+    /**
+     * Utility method that converts the components of a <code>String</code>
+     * representing a codebase or classpath into <code>URL</code>(s).
+     *
+     * @param importCodebase <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.
+     * @return a <code>URL[]</code> where
+     *         each element of the array corresponds to one of the components
+     *         in the <code>importCodebase</code> parameter
+     * @throws java.net.MalformedURLException If the path cannot be parsed as a URL
+     * @throws java.net.IOException           If an I/O error occurs,
+     *                                        which is possible because the construction of
+     *                                        the canonical pathname may require filesystem queries
+     */
+    public static URL[] getImportCodebaseURLs( String importCodebase )
+        throws IOException, MalformedURLException
+    {
+        try
+        {
+            return getCodebaseURLs( importCodebase );
+        }
+        catch( MalformedURLException me )
+        {
+            return getClasspathURLs( importCodebase );
+        }
+    }//end getImportCodebaseURLs
+
+    /**
+     * Utility method that retrieves the components making up the class loader
+     * delegation tree for the current context class loader and returns each
+     * in an <code>ArrayList</code>.
+     *
+     * @return an <code>ArrayList</code> instance in which each element of the
+     *         list is one of the components making up the current delegation
+     *         tree.
+     */
+    private static ArrayList getContextClassLoaderTree()
+    {
+        Thread curThread = Thread.currentThread();
+        ClassLoader curClassLoader = curThread.getContextClassLoader();
+        return getClassLoaderTree( curClassLoader );
+    }//end getCurClassLoaderTree
+
+    /**
+     * Utility method that retrieves the components making up the class loader
+     * delegation tree for the given <code>classloader</code> parameter and
+     * returns them via an <code>ArrayList</code>.
+     *
+     * @param classloader <code>ClassLoader</code> instance whose delegation
+     *                    tree is to be retrieved and returned
+     * @return an <code>ArrayList</code> instance in which each element of the
+     *         list is one of the components making up the delegation tree
+     *         of the given class loader.
+     */
+    private static ArrayList getClassLoaderTree( ClassLoader classloader )
+    {
+        ArrayList loaderList = new ArrayList();
+        while( classloader != null )
+        {
+            loaderList.add( classloader );
+            classloader = classloader.getParent();
+        }//end loop
+        loaderList.add( null ); //Append boot classloader
+        Collections.reverse( loaderList );
+        return loaderList;
+    }//end getClassLoaderTree
+
+    /**
+     * Utility method that displays the class loader delegation tree for
+     * the current context class loader. For each class loader in the tree,
+     * this method displays the locations from which that class loader
+     * will retrieve and load requested classes.
+     * <p>
+     * This method can be useful when debugging problems related to the
+     * receipt of exceptions such as <code>ClassNotFoundException</code>.
+     */
+    public static void displayContextClassLoaderTree()
+    {
+        Thread curThread = Thread.currentThread();
+        ClassLoader curClassLoader = curThread.getContextClassLoader();
+        displayClassLoaderTree( curClassLoader );
+    }//end displayCurClassLoaderTree
+
+    /**
+     * Utility method that displays the class loader delegation tree for
+     * the given class loader. For each class loader in the tree, this
+     * method displays the locations from which that class loader will
+     * retrieve and load requested classes.
+     * <p>
+     * This method can be useful when debugging problems related to the
+     * receipt of exceptions such as <code>ClassNotFoundException</code>.
+     *
+     * @param classloader <code>ClassLoader</code> instance whose delegation
+     *                    tree is to be displayed
+     */
+    public static void displayClassLoaderTree( ClassLoader classloader )
+    {
+        ArrayList loaderList = getClassLoaderTree( classloader );
+        System.out.println( "" );
+        System.out.println( "ClassLoader Tree has "
+                            + loaderList.size() + " levels" );
+        System.out.println( "  cl0 -- Boot ClassLoader " );
+        ClassLoader curClassLoader = null;
+        for( int i = 1; i < loaderList.size(); i++ )
+        {
+            System.out.println( "   |" );
+            curClassLoader = (ClassLoader) loaderList.get( i );
+            System.out.print( "  cl" + i + " -- ClassLoader "
+                              + curClassLoader + ": " );
+            if( curClassLoader instanceof URLClassLoader )
+            {
+                URL[] urls = ( (URLClassLoader) ( curClassLoader ) ).getURLs();
+                if( urls != null )
+                {
+                    System.out.print( urls[ 0 ] );
+                    for( int j = 1; j < urls.length; j++ )
+                    {
+                        System.out.print( ", " + urls[ j ] );
+                    }
+                }
+                else
+                {//urls == null
+                    System.out.print( "null search path" );
+                }//endif
+            }
+            else
+            {
+                if( curClassLoader instanceof SecureClassLoader )
+                {
+                    System.out.print( "is instance of SecureClassLoader" );
+                }
+                else
+                {
+                    System.out.print( "is unknown ClassLoader type" );
+                }
+            }//endif
+            System.out.println( "" );
+        }//end loop
+        System.out.println( "" );
+    }//end displayClassLoaderTree
+
+}//end class ClassLoaderUtil

Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/DestroySharedGroup.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/DestroySharedGroup.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/DestroySharedGroup.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/DestroySharedGroup.java Tue Dec  9 21:15:48 2008
@@ -0,0 +1,365 @@
+/*
+ * 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.start.SharedActivatableServiceDescriptor.Created;
+import com.sun.jini.system.FileSystem;
+import java.io.File;
+import java.rmi.activation.ActivationSystem;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+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;
+
+/**
+ * This class contains the command-line interface for
+ * destroying an instance of a shared activation group.
+ *
+ * The following items are discussed below:
+ * <ul>
+ * <li><a href="#configEntries">Configuring DestroySharedGroup</a>
+ * <li><a href="#logging">Logging</a>
+ * </ul>
+ *
+ * <a name="configEntries">
+ * <h3>Configuring DestroySharedGroup</h3>
+ * </a>
+ *
+ * This implementation of <code>DestroySharedGroup</code> supports the
+ * following configuration entries, with component
+ * <code>com.sun.jini.start</code>:
+ *
+ * <table summary="Describes the activationSystemPreparer 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>
+ * activationSystemPreparer</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 proxy preparer for the proxy for the
+ * activation system. The value should not be <code>null</code>. This
+ * entry is obtained at service start and restart. This entry is only
+ * used by the activatable implementation. <p>
+ *
+ * The service calls the {@link
+ * java.rmi.activation.ActivationSystem#unregisterObject
+ * unregisterObject} method on the {@link
+ * java.rmi.activation.ActivationSystem} when there is a problem
+ * creating a service.
+ * </table>
+ *
+ * <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
+ * services starter. If <code>null</code>, no JAAS login is performed.
+ * </table>
+ *
+ * <table summary="Describes the serviceDestructors 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>
+ * serviceDestructors</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 DestroySharedGroup service 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 destruction from proceeding
+ * <tr> <td> {@link java.util.logging.Level#WARNING WARNING} <td>
+ * for problems with service destruction that don't prevent further
+ * processing
+ * <tr> <td> {@link java.util.logging.Level#FINER FINER} <td>
+ * for high level
+ * service destruction operation tracing
+ * <tr> <td> {@link java.util.logging.Level#FINEST FINEST} <td>
+ * for low level
+ * service destruction operation tracing
+ *
+ * </table> <p>
+ *
+ * @author Sun Microsystems, Inc.
+ * @see com.sun.jini.start.ServiceStarter
+ * @since 1.2
+ */
+public class DestroySharedGroup
+{
+
+    /**
+     * Configure logger.
+     */
+    private static final Logger logger = ServiceStarter.logger;
+
+    // Private constructor to prevent instantiation
+    private DestroySharedGroup()
+    {
+    }
+
+    /**
+     * The main method for the <code>DestroySharedGroup</code> application.
+     * The <code>args</code> parameter is passed directly to
+     * <code>ConfigurationProvider.getInstance()</code> in order to
+     * obtain a <code>Configuration</code> object. This configuration
+     * object is then queried for a
+     * <code>com.sun.jini.start.serviceDestructors</code> entry, which
+     * is assumed to be a <code>SharedActivatableServiceDescriptor[]</code>
+     * configured to run {@link com.sun.jini.start.SharedGroup} implementations.
+     * The {@link com.sun.jini.start.SharedGroup#destroyVM() destroyVM()}
+     * method is then called on each of the array elements. An attempt is
+     * made to also delete shared group <code>log</code> directory associated
+     * with each array element.
+     *
+     * @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 net.jini.config.Configuration
+     * @see net.jini.config.ConfigurationProvider
+     */
+    public static void main( String[] args )
+    {
+        ServiceStarter.ensureSecurityManager();
+        logger.entering( DestroySharedGroup.class.getName(), "main",
+                         ( (Object[]) args ) );
+        try
+        {
+            Configuration config = ConfigurationProvider.getInstance( args );
+            ServiceDescriptor[] srvArray =
+                (ServiceDescriptor[]) config.getEntry(
+                    ServiceStarter.START_PACKAGE, "serviceDestructors",
+                    ServiceDescriptor[].class, null );
+            if( srvArray == null || srvArray.length == 0 )
+            {
+                logger.log( Level.WARNING, "service.config.empty" );
+                return;
+            }
+            LoginContext loginContext = (LoginContext)
+                config.getEntry( ServiceStarter.START_PACKAGE, "loginContext",
+                                 LoginContext.class, null );
+            if( loginContext != null )
+            {
+                destroyWithLogin( srvArray, config, loginContext );
+            }
+            else
+            {
+                destroy( srvArray, config );
+            }
+        }
+        catch( ConfigurationException ce )
+        {
+            logger.log( Level.SEVERE, "destroy.config.exception", ce );
+        }
+        catch( Exception e )
+        {
+            logger.log( Level.SEVERE, "destroy.unexpected.exception", e );
+        }
+        logger.exiting( DestroySharedGroup.class.getName(), "main" );
+    }
+
+    /**
+     * Method that attempts to destroy any available <code>SharedGroup</code>
+     * objects in the provided <code>ServiceDescriptor[]</code>.
+     */
+    private static void destroy( ServiceDescriptor[] srvArray,
+                                 Configuration config ) throws Exception
+    {
+        logger.entering( DestroySharedGroup.class.getName(), "destroy",
+                         new Object[]{ Arrays.asList( srvArray ), config } );
+        Created created = null;
+        SharedActivatableServiceDescriptor desc = null;
+        ActivationSystem activationSystem = null;
+
+        for( int i = 0; i < srvArray.length; i++ )
+        {
+            if( srvArray[ i ] instanceof SharedActivatableServiceDescriptor )
+            {
+                desc = (SharedActivatableServiceDescriptor) srvArray[ i ];
+                activationSystem =
+                    ServiceStarter.getActivationSystem(
+                        desc.getActivationSystemHost(),
+                        desc.getActivationSystemPort(),
+                        config );
+                try
+                {
+                    created = (Created) desc.create( config );
+                    if( created != null &&
+                        created.proxy instanceof SharedGroup )
+                    {
+                        // service proxy from create() is already prepared
+                        SharedGroup sg = (SharedGroup) created.proxy;
+                        try
+                        {
+                            sg.destroyVM();
+                            try
+                            {
+                                File log = new File( desc.getSharedGroupLog() );
+                                FileSystem.destroy( log, true );
+                            }
+                            catch( Exception e )
+                            {
+                                logger.log( Level.WARNING,
+                                            "destroy.group.deletion", e );
+                            }
+                        }
+                        catch( Exception e )
+                        {
+                            logger.log( Level.SEVERE,
+                                        "destroy.group.exception", e );
+//TODO - Add configurable retry logic or just unregister				
+                        }
+                    }
+                    else
+                    {
+                        logger.log( Level.WARNING, "destroy.unexpected.proxy",
+                                    ( created == null ) ? null : created.proxy );
+                        if( created != null && created.aid != null )
+                        {
+                            try
+                            {
+                                activationSystem.unregisterObject( created.aid );
+                            }
+                            catch( Exception e )
+                            {
+                                logger.log( Level.WARNING,
+                                            "destroy.unregister.exception", e );
+                            }
+                        }
+                    }
+                }
+                catch( Exception ee )
+                {
+                    logger.log( Level.SEVERE, "destroy.creation.exception", ee );
+                    if( created != null && created.aid != null )
+                    {
+                        try
+                        {
+                            activationSystem.unregisterObject( created.aid );
+                        }
+                        catch( Exception e )
+                        {
+                            logger.log( Level.WARNING,
+                                        "destroy.unregister.exception", ee );
+                        }
+                    }
+                }
+            }
+            else
+            {
+                logger.log( Level.WARNING, "destroy.unexpected.type", srvArray[ i ] );
+            }
+        }
+        logger.exiting( DestroySharedGroup.class.getName(), "destroy" );
+    }
+
+    /**
+     * Method that attempts to login via the provided
+     * <code>LoginContext</code> and then calls <code>destroy</code>.
+     */
+    private static void destroyWithLogin(
+        final ServiceDescriptor[] descs, final Configuration config,
+        final LoginContext loginContext ) throws Exception
+    {
+        logger.entering( DestroySharedGroup.class.getName(),
+                         "destroyWithLogin", new Object[]{ descs, config, loginContext } );
+        loginContext.login();
+        try
+        {
+            Subject.doAsPrivileged(
+                loginContext.getSubject(),
+                new PrivilegedExceptionAction()
+                {
+                    public Object run() throws Exception
+                    {
+                        destroy( descs, config );
+                        return null;
+                    }
+                },
+                null );
+        }
+        catch( PrivilegedActionException e )
+        {
+            throw e.getException();
+        }
+        finally
+        {
+            try
+            {
+                loginContext.logout();
+            }
+            catch( LoginException le )
+            {
+                logger.log( Level.FINE, "service.logout.exception", le );
+            }
+        }
+        logger.exiting( DestroySharedGroup.class.getName(),
+                        "destroyWithLogin" );
+        return;
+    }
+}
+
+

Added: incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/HTTPDStatus.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/HTTPDStatus.java?rev=724983&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/HTTPDStatus.java (added)
+++ incubator/river/jtsk/skunk/niclas1/services/start/src/main/java/com/sun/jini/start/HTTPDStatus.java Tue Dec  9 21:15:48 2008
@@ -0,0 +1,140 @@
+/*
+ * 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.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Class which can be used to print a descriptive warning message
+ * if a codebase accessibility problem is found.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+public class HTTPDStatus
+{
+    /**
+     * Config logger.
+     */
+    private static final Logger logger = ServiceStarter.logger;
+
+    // Private constructor to prevent instantiation
+    private HTTPDStatus()
+    {
+    }
+
+    /**
+     * Command line interface that checks the accessability of a desired
+     * JAR file(s), given its <code>URL</code> address.
+     * Note: The provided <code>URL</code>(s) cannot contain embedded spaces.
+     *
+     * @param args <code>String</code> array containing the command line
+     *             arguments
+     */
+    public static void main( String[] args )
+    {
+        if( args.length < 1 )
+        {
+            System.err.println( "Usage: HTTPDStatus URL1 [URL2 ... URLN]" );
+            return;
+        }//endif
+        for( int i = 0; i < args.length; i++ )
+        {
+            httpdWarning( args[ i ] );
+        }
+    }//end main
+
+
+    /**
+     * Method that takes a <code>codebase</code>
+     * parameter and displays a warning message if
+     * it is determined that a potential codebase
+     * accessibility problem exists.
+     *
+     * @param codebase <code>String</code> containing the codebase to poll
+     *                 for the existence of a running HTTP server with
+     *                 access to the JAR file referenced in this parameter
+     */
+    public static void httpdWarning( String codebase )
+    {
+        if( codebase == null )
+        {
+            logger.log( Level.WARNING, "httpserver.warning",
+                        new Object[]{ codebase, "Codebase is null" } );
+            return;
+        }
+        StringTokenizer st = new StringTokenizer( codebase, " " );
+        String url = null;
+        URL u = null;
+        for( int i = 0; st.hasMoreTokens(); i++ )
+        {
+            url = st.nextToken();
+            try
+            {
+                u = new URL( url );
+                String fileName = u.getFile();
+                //Skip file check for directories
+                if( fileName == null ||
+                    fileName.endsWith( "/" ) )
+                {
+                    logger.log( Level.FINEST, "httpserver.skipping", url );
+                }
+                else
+                {
+                    try
+                    {
+                        drainStream( u.openStream() );
+                    }
+                    catch( Exception ioe )
+                    {
+                        logger.log( Level.WARNING, "httpserver.warning",
+                                    new Object[]{ url, ioe.toString() } );
+                        logger.log( Level.FINEST, "httpserver.exception", ioe );
+                    }
+                }
+            }
+            catch( MalformedURLException e )
+            {
+                logger.log( Level.WARNING, "httpserver.unknownprotocol", url );
+                logger.log( Level.FINEST, "httpserver.exception", e );
+            }
+        }
+        return;
+    }//end httpdStatus
+
+    /**
+     * Reads and discards all data from a given input stream.
+     *
+     * @param is the <code>InputStream</code> from which to read data
+     */
+    private static void drainStream( InputStream is ) throws IOException
+    {
+        BufferedInputStream reader =
+            new BufferedInputStream( is );
+        while( reader.read() != -1 )
+        {
+        }
+    }//end drainSocket
+
+}//end class HTTPDStatus



Mime
View raw message