Package net.jini.export

Source Code of net.jini.export.ServerContext$Spi

/*
* 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 net.jini.export;

import com.sun.jini.resource.Service;
import java.rmi.server.ServerNotActiveException;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import net.jini.io.context.ClientHost;
import net.jini.io.context.ClientSubject;
import net.jini.security.Security;

/**
* The <code>ServerContext</code> class contains static methods to
* execute some action within an appropriate server context for the
* current thread and to obtain the server context for the current thread.
*
* <p>For example, an {@link Exporter} implementation may supply context
* information for incoming calls dispatched to its exported remote objects
* via the {@link #doWithServerContext ServerContext.doWithServerContext}
* method.
*
* @author Sun Microsystems, Inc.
*
* @since 2.0
* @see net.jini.io.context.ClientHost
* @see net.jini.io.context.ClientSubject
**/
public final class ServerContext {

    private static final ThreadLocal state = new ThreadLocal();
    private static ServerContext.Spi[] providers = null;

    private static ServerContext.Spi[] getProviders() {
        if (providers == null) {
            providers = (ServerContext.Spi[]) Security.doPrivileged(new PrivilegedAction() {

                public Object run() {
                    ClassLoader cl = Thread.currentThread().getContextClassLoader();
                    ArrayList list = new ArrayList(1);
                    Iterator i = Service.providers(ServerContext.Spi.class, cl);
                    while (i.hasNext()) {
                        list.add(i.next());
                    }
                    return list.toArray(new ServerContext.Spi[list.size()]);
                }
            });
        }
        return providers;
    }

    /**
     * Prevents instantiation.
     */
    private ServerContext() {
    }

    /**
     * Sets the server context for the current thread to the supplied
     * <code>context</code> collection and invokes the <code>run</code> method
     * of the supplied <code>runnable</code> object.  When this method
     * returns, the thread's server context is unset.
     *
     * <p>If a server context is currently set for the current thread,
     * that server context cannot be reset; that is, a server context
     * cannot be overwritten or nested.  If a server context is already
     * set for the current thread, an <code>IllegalStateException</code> is
     * thrown.
     *
     * @param  runnable the action to perform in the server context
     * @param  context the context to set
     *
     * @throws  NullPointerException if <code>context</code> or
     *    <code>runnable</code> is <code>null</code>
     * @throws  IllegalStateException if the context is already
     *     set for this thread
     * @see #getServerContextElement
     **/
    public static void doWithServerContext(Runnable runnable,
            Collection context) {
        if (context == null) {
            throw new NullPointerException("context cannot be null");
        }
        if (state.get() != null) {
            throw new IllegalStateException(
                    "context is already set for this thread");
        }

        state.set(context);
        try {
            runnable.run();
        } finally {
            state.set(null);
        }
    }

    /**
     * Returns the server context collection for the current thread.  If no
     * server context collection has been explicitly specified via a
     * previous call to {@link #doWithServerContext
     * ServerContext.doWithServerContext}, then an ordered list of
     * providers (obtained as specified below) implementing the {@link
     * ServerContext.Spi} interface is consulted.  {@link
     * ServerContext.Spi#getServerContext} is called on each provider in
     * turn; the first non-<code>null</code> return value is returned by
     * this method.  If no provider is able to supply a server context
     * collection, then a <code>ServerNotActiveException</code> is thrown.
     *
     * <p>The list of server context providers is obtained as follows.  For
     * each resource named
     * <code>META-INF/services/net.jini.export.ServerContext$Spi</code>
     * that is visible to the system class loader, the contents of the
     * resource are parsed as UTF-8 text to produce a list of class names.
     * The resource must contain a list of fully-qualified class names, one per
     * line. Space and tab characters surrounding each name, as well as blank
     * lines, are ignored.  The comment character is <tt>'#'</tt>; all
     * characters on each line starting with the first comment character are
     * ignored. Each class name (that is not a duplicate of any previous class
     * name) is loaded through the system class loader, and the resulting
     * class must be assignable to {@link ServerContext.Spi} and have a public
     * no-argument constructor. The constructor is invoked to create a fallback
     * context provider instance. An implementation is permitted to search for
     * provider instances eagerly (i.e., upon startup), and cache the
     * verifier instances rather than recreating them on every call.
     *
     * <p>The contents of the collection are determined by the caller of
     * {@link #doWithServerContext ServerContext.doWithServerContext}.  The
     * context information available from a given element of the collection
     * is determined by that element's type.  Examples of types that a
     * given element might implement include {@link ClientHost} and {@link
     * ClientSubject}.
     *
     * <p>The order of the elements in the collection is insignificant.
     * The collection may be empty.
     *
     * <p>The caller of this method cannot assume that the returned
     * collection is modifiable.
     *
     * @return  the server context for the current thread
     * @throws  ServerNotActiveException if no context is set for the
     *    current thread
     **/
    public static Collection getServerContext()
            throws ServerNotActiveException {
        Collection context = (Collection) state.get();
        if (context == null) {
            for (int i = 0; i < getProviders().length; i++) {
                if ((context = getProviders()[i].getServerContext()) != null) {
                    break;
                }
            }
        }
        if (context == null) {
            throw new ServerNotActiveException("not in remote call");
        }
        return context;
    }

    /**
     * Defines the interface for server context providers, which are
     * consulted by {@link ServerContext#getServerContext} if no server context
     * has been explicitly associated with the current thread via a previous
     * call to {@link ServerContext#doWithServerContext}.
     */
    public interface Spi {

        /**
         * Returns a server context collection for the current thread, or
         * <code>null</code> if provider does not contain context for the
         * current thread.
         *
         * <p>The context information available from a given element of
         * the collection is determined by that element's type.  The order
         * of the elements is insignificant.  The collection may be empty.
         *
         * <p>The caller of this method cannot assume that the returned
         * collection is modifiable.
         *
         * @return  the server context for the current thread,
         *      or <code>null</code> if none known
         */
        Collection getServerContext();
    }

    /**
     * Returns the first element in the current server context collection
     * (obtained by calling {@link #getServerContext
     * ServerContext.getServerContext}) that is an instance of the given
     * type <code>type</code>.  If no element in the collection is an
     * instance of the type <code>type</code>, then <code>null</code> is
     * returned.
     *
     * @param  type the type of the element
     * @return   the first element in the server context collection that is
     *    an instance of the type <code>type</code> or <code>null</code>
     * @throws  ServerNotActiveException if no server context is set for
     *    the current thread
     **/
    public static Object getServerContextElement(Class type)
            throws ServerNotActiveException {
        Collection context = getServerContext();
        Iterator iter = context.iterator();
        while (iter.hasNext()) {
            Object elem = iter.next();
            if (elem != null && type.isAssignableFrom(elem.getClass())) {
                return elem;
            }
        }
        return null;
    }
}
TOP

Related Classes of net.jini.export.ServerContext$Spi

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.