874 lines · 35.2 KB · Java
RawDownload
/* * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.naming.spi; import java.util.Enumeration;import java.util.Hashtable;import java.util.StringTokenizer;import java.net.MalformedURLException; import javax.naming.*;import com.sun.naming.internal.VersionHelper;import com.sun.naming.internal.ResourceManager;import com.sun.naming.internal.FactoryEnumeration; /** * This class contains methods for creating context objects * and objects referred to by location information in the naming * or directory service. *<p> * This class cannot be instantiated.  It has only static methods. *<p> * The mention of URL in the documentation for this class refers to * a URL string as defined by RFC 1738 and its related RFCs. It is * any string that conforms to the syntax described therein, and * may not always have corresponding support in the java.net.URL * class or Web browsers. *<p> * NamingManager is safe for concurrent access by multiple threads. *<p> * Except as otherwise noted, * a <tt>Name</tt> or environment parameter * passed to any method is owned by the caller. * The implementation will not modify the object or keep a reference * to it, although it may keep a reference to a clone or copy. * * @author Rosanna Lee * @author Scott Seligman * @since 1.3 */ public class NamingManager {     /*     * Disallow anyone from creating one of these.     * Made package private so that DirectoryManager can subclass.     */     NamingManager() {}     // should be protected and package private    static final VersionHelper helper = VersionHelper.getVersionHelper(); // --------- object factory stuff     /**     * Package-private; used by DirectoryManager and NamingManager.     */    private static ObjectFactoryBuilder object_factory_builder = null;     /**     * The ObjectFactoryBuilder determines the policy used when     * trying to load object factories.     * See getObjectInstance() and class ObjectFactory for a description     * of the default policy.     * setObjectFactoryBuilder() overrides this default policy by installing     * an ObjectFactoryBuilder. Subsequent object factories will     * be loaded and created using the installed builder.     *<p>     * The builder can only be installed if the executing thread is allowed     * (by the security manager's checkSetFactory() method) to do so.     * Once installed, the builder cannot be replaced.     *<p>     * @param builder The factory builder to install. If null, no builder     *                  is installed.     * @exception SecurityException builder cannot be installed     *          for security reasons.     * @exception NamingException builder cannot be installed for     *         a non-security-related reason.     * @exception IllegalStateException If a factory has already been installed.     * @see #getObjectInstance     * @see ObjectFactory     * @see ObjectFactoryBuilder     * @see java.lang.SecurityManager#checkSetFactory     */    public static synchronized void setObjectFactoryBuilder(            ObjectFactoryBuilder builder) throws NamingException {        if (object_factory_builder != null)            throw new IllegalStateException("ObjectFactoryBuilder already set");         SecurityManager security = System.getSecurityManager();        if (security != null) {            security.checkSetFactory();        }        object_factory_builder = builder;    }     /**     * Used for accessing object factory builder.     */    static synchronized ObjectFactoryBuilder getObjectFactoryBuilder() {        return object_factory_builder;    }      /**     * Retrieves the ObjectFactory for the object identified by a reference,     * using the reference's factory class name and factory codebase     * to load in the factory's class.     * @param ref The non-null reference to use.     * @param factoryName The non-null class name of the factory.     * @return The object factory for the object identified by ref; null     * if unable to load the factory.     */    static ObjectFactory getObjectFactoryFromReference(        Reference ref, String factoryName)        throws IllegalAccessException,        InstantiationException,        MalformedURLException {        Class clas = null;         // Try to use current class loader        try {             clas = helper.loadClass(factoryName);        } catch (ClassNotFoundException e) {            // ignore and continue            // e.printStackTrace();        }        // All other exceptions are passed up.         // Not in class path; try to use codebase        String codebase;        if (clas == null &&                (codebase = ref.getFactoryClassLocation()) != null) {            try {                clas = helper.loadClass(factoryName, codebase);            } catch (ClassNotFoundException e) {            }        }         return (clas != null) ? (ObjectFactory) clas.newInstance() : null;    }      /**     * Creates an object using the factories specified in the     * <tt>Context.OBJECT_FACTORIES</tt> property of the environment     * or of the provider resource file associated with <tt>nameCtx</tt>.     *     * @return factory created; null if cannot create     */    private static Object createObjectFromFactories(Object obj, Name name,            Context nameCtx, Hashtable environment) throws Exception {         FactoryEnumeration factories = ResourceManager.getFactories(            Context.OBJECT_FACTORIES, environment, nameCtx);         if (factories == null)            return null;         // Try each factory until one succeeds        ObjectFactory factory;        Object answer = null;        while (answer == null && factories.hasMore()) {            factory = (ObjectFactory)factories.next();            answer = factory.getObjectInstance(obj, name, nameCtx, environment);        }        return answer;    }     private static String getURLScheme(String str) {        int colon_posn = str.indexOf(':');        int slash_posn = str.indexOf('/');         if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))            return str.substring(0, colon_posn);        return null;    }     /**     * Creates an instance of an object for the specified object     * and environment.     * <p>     * If an object factory builder has been installed, it is used to     * create a factory for creating the object.     * Otherwise, the following rules are used to create the object:     *<ol>     * <li>If <code>refInfo</code> is a <code>Reference</code>     *    or <code>Referenceable</code> containing a factory class name,     *    use the named factory to create the object.     *    Return <code>refInfo</code> if the factory cannot be created.     *    Under JDK 1.1, if the factory class must be loaded from a location     *    specified in the reference, a <tt>SecurityManager</tt> must have     *    been installed or the factory creation will fail.     *    If an exception is encountered while creating the factory,     *    it is passed up to the caller.     * <li>If <tt>refInfo</tt> is a <tt>Reference</tt> or     *    <tt>Referenceable</tt> with no factory class name,     *    and the address or addresses are <tt>StringRefAddr</tt>s with     *    address type "URL",     *    try the URL context factory corresponding to each URL's scheme id     *    to create the object (see <tt>getURLContext()</tt>).     *    If that fails, continue to the next step.     * <li> Use the object factories specified in     *    the <tt>Context.OBJECT_FACTORIES</tt> property of the environment,     *    and of the provider resource file associated with     *    <tt>nameCtx</tt>, in that order.     *    The value of this property is a colon-separated list of factory     *    class names that are tried in order, and the first one that succeeds     *    in creating an object is the one used.     *    If none of the factories can be loaded,     *    return <code>refInfo</code>.     *    If an exception is encountered while creating the object, the     *    exception is passed up to the caller.     *</ol>     *<p>     * Service providers that implement the <tt>DirContext</tt>     * interface should use     * <tt>DirectoryManager.getObjectInstance()</tt>, not this method.     * Service providers that implement only the <tt>Context</tt>     * interface should use this method.     * <p>     * Note that an object factory (an object that implements the ObjectFactory     * interface) must be public and must have a public constructor that     * accepts no arguments.     * <p>     * The <code>name</code> and <code>nameCtx</code> parameters may     * optionally be used to specify the name of the object being created.     * <code>name</code> is the name of the object, relative to context     * <code>nameCtx</code>.  This information could be useful to the object     * factory or to the object implementation.     *  If there are several possible contexts from which the object     *  could be named -- as will often be the case -- it is up to     *  the caller to select one.  A good rule of thumb is to select the     * "deepest" context available.     * If <code>nameCtx</code> is null, <code>name</code> is relative     * to the default initial context.  If no name is being specified, the     * <code>name</code> parameter should be null.     *     * @param refInfo The possibly null object for which to create an object.     * @param name The name of this object relative to <code>nameCtx</code>.     *          Specifying a name is optional; if it is     *          omitted, <code>name</code> should be null.     * @param nameCtx The context relative to which the <code>name</code>     *          parameter is specified.  If null, <code>name</code> is     *          relative to the default initial context.     * @param environment The possibly null environment to     *          be used in the creation of the object factory and the object.     * @return An object created using <code>refInfo</code>; or     *          <code>refInfo</code> if an object cannot be created using     *          the algorithm described above.     * @exception NamingException if a naming exception was encountered     *  while attempting to get a URL context, or if one of the     *          factories accessed throws a NamingException.     * @exception Exception if one of the factories accessed throws an     *          exception, or if an error was encountered while loading     *          and instantiating the factory and object classes.     *          A factory should only throw an exception if it does not want     *          other factories to be used in an attempt to create an object.     *  See ObjectFactory.getObjectInstance().     * @see #getURLContext     * @see ObjectFactory     * @see ObjectFactory#getObjectInstance     */    public static Object        getObjectInstance(Object refInfo, Name name, Context nameCtx,                          Hashtable<?,?> environment)        throws Exception    {         ObjectFactory factory;         // Use builder if installed        ObjectFactoryBuilder builder = getObjectFactoryBuilder();        if (builder != null) {            // builder must return non-null factory            factory = builder.createObjectFactory(refInfo, environment);            return factory.getObjectInstance(refInfo, name, nameCtx,                environment);        }         // Use reference if possible        Reference ref = null;        if (refInfo instanceof Reference) {            ref = (Reference) refInfo;        } else if (refInfo instanceof Referenceable) {            ref = ((Referenceable)(refInfo)).getReference();        }         Object answer;         if (ref != null) {            String f = ref.getFactoryClassName();            if (f != null) {                // if reference identifies a factory, use exclusively                 factory = getObjectFactoryFromReference(ref, f);                if (factory != null) {                    return factory.getObjectInstance(ref, name, nameCtx,                                                     environment);                }                // No factory found, so return original refInfo.                // Will reach this point if factory class is not in                // class path and reference does not contain a URL for it                return refInfo;             } else {                // if reference has no factory, check for addresses                // containing URLs                 answer = processURLAddrs(ref, name, nameCtx, environment);                if (answer != null) {                    return answer;                }            }        }         // try using any specified factories        answer =            createObjectFromFactories(refInfo, name, nameCtx, environment);        return (answer != null) ? answer : refInfo;    }     /*     * Ref has no factory.  For each address of type "URL", try its URL     * context factory.  Returns null if unsuccessful in creating and     * invoking a factory.     */    static Object processURLAddrs(Reference ref, Name name, Context nameCtx,                                  Hashtable environment)            throws NamingException {         for (int i = 0; i < ref.size(); i++) {            RefAddr addr = ref.get(i);            if (addr instanceof StringRefAddr &&                addr.getType().equalsIgnoreCase("URL")) {                 String url = (String)addr.getContent();                Object answer = processURL(url, name, nameCtx, environment);                if (answer != null) {                    return answer;                }            }        }        return null;    }     private static Object processURL(Object refInfo, Name name,                                     Context nameCtx, Hashtable environment)            throws NamingException {        Object answer;         // If refInfo is a URL string, try to use its URL context factory        // If no context found, continue to try object factories.        if (refInfo instanceof String) {            String url = (String)refInfo;            String scheme = getURLScheme(url);            if (scheme != null) {                answer = getURLObject(scheme, refInfo, name, nameCtx,                                      environment);                if (answer != null) {                    return answer;                }            }        }         // If refInfo is an array of URL strings,        // try to find a context factory for any one of its URLs.        // If no context found, continue to try object factories.        if (refInfo instanceof String[]) {            String[] urls = (String[])refInfo;            for (int i = 0; i <urls.length; i++) {                String scheme = getURLScheme(urls[i]);                if (scheme != null) {                    answer = getURLObject(scheme, refInfo, name, nameCtx,                                          environment);                    if (answer != null)                        return answer;                }            }        }        return null;    }      /**     * Retrieves a context identified by <code>obj</code>, using the specified     * environment.     * Used by ContinuationContext.     *     * @param obj       The object identifying the context.     * @param name      The name of the context being returned, relative to     *                  <code>nameCtx</code>, or null if no name is being     *                  specified.     *                  See the <code>getObjectInstance</code> method for     *                  details.     * @param ctx       The context relative to which <code>name</code> is     *                  specified, or null for the default initial context.     *                  See the <code>getObjectInstance</code> method for     *                  details.     * @param environment Environment specifying characteristics of the     *                  resulting context.     * @return A context identified by <code>obj</code>.     *     * @see #getObjectInstance     */    static Context getContext(Object obj, Name name, Context nameCtx,                              Hashtable environment) throws NamingException {        Object answer;         if (obj instanceof Context) {            // %%% Ignore environment for now.  OK since method not public.            return (Context)obj;        }         try {            answer = getObjectInstance(obj, name, nameCtx, environment);        } catch (NamingException e) {            throw e;        } catch (Exception e) {            NamingException ne = new NamingException();            ne.setRootCause(e);            throw ne;        }         return (answer instanceof Context)            ? (Context)answer            : null;    }     // Used by ContinuationContext    static Resolver getResolver(Object obj, Name name, Context nameCtx,                                Hashtable environment) throws NamingException {        Object answer;         if (obj instanceof Resolver) {            // %%% Ignore environment for now.  OK since method not public.            return (Resolver)obj;        }         try {            answer = getObjectInstance(obj, name, nameCtx, environment);        } catch (NamingException e) {            throw e;        } catch (Exception e) {            NamingException ne = new NamingException();            ne.setRootCause(e);            throw ne;        }         return (answer instanceof Resolver)            ? (Resolver)answer            : null;    }      /***************** URL Context implementations ***************/     /**     * Creates a context for the given URL scheme id.     * <p>     * The resulting context is for resolving URLs of the     * scheme <code>scheme</code>. The resulting context is not tied     * to a specific URL. It is able to handle arbitrary URLs with     * the specified scheme.     *<p>     * The class name of the factory that creates the resulting context     * has the naming convention <i>scheme-id</i>URLContextFactory     * (e.g. "ftpURLContextFactory" for the "ftp" scheme-id),     * in the package specified as follows.     * The <tt>Context.URL_PKG_PREFIXES</tt> environment property (which     * may contain values taken from applet parameters, system properties,     * or application resource files)     * contains a colon-separated list of package prefixes.     * Each package prefix in     * the property is tried in the order specified to load the factory class.     * The default package prefix is "com.sun.jndi.url" (if none of the     * specified packages work, this default is tried).

Lines 1–500 of 874.