You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2006/08/27 20:26:28 UTC

svn commit: r437433 [10/17] - in /incubator/harmony/enhanced/classlib/trunk/modules/jndi/src: main/java/javax/naming/ main/java/javax/naming/directory/ main/java/javax/naming/event/ main/java/javax/naming/ldap/ main/java/javax/naming/spi/ main/java/org...

Modified: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java?rev=437433&r1=437432&r2=437433&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java Sun Aug 27 11:26:20 2006
@@ -1,814 +1,814 @@
-/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable
- * 
- * Licensed 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 javax.naming.spi;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-
-import javax.naming.CannotProceedException;
-import javax.naming.Context;
-import org.apache.harmony.jndi.internal.EnvironmentReader;
-import org.apache.harmony.jndi.internal.UrlParser;
-
-import javax.naming.Name;
-import javax.naming.NamingException;
-import javax.naming.NoInitialContextException;
-import javax.naming.RefAddr;
-import javax.naming.Reference;
-import javax.naming.Referenceable;
-import javax.naming.StringRefAddr;
-
-/**
- * The <code>NamingManager</code> class should not be instantiated although it
- * can be extended by classes within the <code>javax.naming.spi</code> package -
- * see {@link DirectoryManager}. All its methods are static.
- * <p>
- * The methods are used by service providers for accessing object and state
- * factories and for determining continuation contexts. Many of the methods
- * create objects. These may be <code>Context</code> objects or objects
- * referred to by the naming service.
- * </p>
- * <p>
- * The <code>Name</code> and <code>Hashtable</code> arguments passed to the
- * <code>NamingManager</code> methods remain owned purely by the calling
- * method. They must not be changed or referenced.
- * </p>
- * <p>
- * It should be noted that it is possible for an application to access a
- * namespace other than that supplied by the default <code>InitialContext</code>
- * (as specified by <code>Context.INITIAL_CONTEXT_FACTORY</code>). It is
- * possible to call the following <code>InitialContext</code> methods passing
- * a URL string either as the <code>String</code> or <code>Name</code>
- * parameter: <code>lookup, bin, rebind, unbind, rename, list, listBindings, 
- * destroySubcontext, createSubcontext, lookupLink, getNameParser</code>.
- * This allows you to have one <code>InitialContext</code> object where these
- * methods usually use the default initial context but access a URL
- * <code>Context</code> instead when invoked with a URL string.
- * </p>
- * <p>
- * A URL string is of the format abc:\nnnnnn where abc is the scheme of the URL.
- * (See <code>InitialContext</code> where it refers to RFC1738.) When a URL
- * string is supplied to those <code>InitialContext</code> methods, a URL
- * context is used instead of the default initial context when performing that
- * method. URL context factories are used to create URL contexts. A URL context
- * factory is really just a service provider's implementation of an
- * <code>ObjectFactory</code>. It is not essential that a service provider
- * supplies one if they do not wish to support URL <code>Contexts.</code>
- * </p>
- * <p>
- * See the <code>getURLContext</code> method for a description of how a URL
- * context factory is located.
- * </p>
- * <p>
- * Please note that multithreaded access to this class must be safe. For
- * example, for thread safety, it should not be possible for one thread to read
- * the installed <code>InitialContextFactoryBuilder</code> or
- * <code>ObjectFactoryBuilder</code> while another thread is in the process of
- * setting it.
- * </p>
- * <p>
- * Also note that privileges should be granted to get the context classloader
- * and to read the resource files.
- * </p>
- * 
- * @see DirectoryManager
- */
-
-public class NamingManager {
-
-    /*
-     * -------------------------------------------------------------------
-     * Constants
-     * -------------------------------------------------------------------
-     */
-
-    /**
-     * The property name of <code>CannotProceedException</code> in a context's
-     * environment.
-     */
-    public static final String CPE = "java.naming.spi.CannotProceedException"; //$NON-NLS-1$
-
-    /*
-     * ------------------------------------------------------------------- 
-     * Class variables
-     * -------------------------------------------------------------------
-     */
-
-    static InitialContextFactoryBuilder icfb = null;
-
-    static ObjectFactoryBuilder ofb = null;
-
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
-    NamingManager() {
-        // package private to prevent it being instanced but make it can be
-        // subclassed by DirectoryManager
-    }
-
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
-    /**
-     * Install an <code>InitialContextFactoryBuilder</code>. Once this has
-     * been set it cannot be reset. Attempts to do so cause an
-     * <code>IllegalStateException</code>. The builder can only be installed
-     * if the security policy allows the setting of the factory.
-     * 
-     * @param icfb
-     *            the builder to be installed - can be null, but then no builder
-     *            is installed.
-     * @throws IllegalStateException
-     *             if an builder has already been installed.
-     * @throws SecurityException
-     *             is a security error prevents the installation.
-     * @throws NamingException
-     *             for other errors encountered.
-     */
-    public static synchronized void setInitialContextFactoryBuilder(
-            InitialContextFactoryBuilder icfb) throws IllegalStateException,
-            SecurityException, NamingException {
-
-        if (null != NamingManager.icfb) {
-            throw new IllegalStateException(
-                    "InitialContextFactoryBuilder cannot be reset"); //$NON-NLS-1$
-        }
-
-        // check security access
-        SecurityManager sm = System.getSecurityManager();
-        if (null != sm) {
-            sm.checkSetFactory();
-        }
-
-        NamingManager.icfb = icfb;
-    }
-
-    /**
-     * Returns true when an <code>InitialContextFactoryBuilder</code> has been
-     * installed.
-     * 
-     * @return true when an <code>InitialContextFactoryBuilder</code> has been
-     *         installed.
-     */
-    public static boolean hasInitialContextFactoryBuilder() {
-        return null != icfb;
-    }
-
-    /**
-     * Install an <code>ObjectFactoryBuilder</code>. Once this has been set
-     * it cannot be reset. Attempts to do so cause an
-     * <code>IllegalStateException</code>. The builder can only be installed
-     * if the security policy allows the setting of the factory.
-     * 
-     * @param ofb
-     *            the <code>ObjectFactoryBuilder</code> to be installed - can
-     *            be null, but then no builder is installed.
-     * @throws IllegalStateException
-     *             if an <code>ObjectFactoryBuilder</code> has already been
-     *             installed.
-     * @throws SecurityException
-     *             is a security error prevents the installation.
-     * @throws NamingException
-     *             for other errors encountered.
-     */
-    public static synchronized void setObjectFactoryBuilder(
-            ObjectFactoryBuilder ofb) throws IllegalStateException,
-            SecurityException, NamingException {
-
-        if (null != NamingManager.ofb) {
-            throw new IllegalStateException(
-                    "ObjectFactoryBuilder cannot be reset"); //$NON-NLS-1$
-        }
-
-        // check security access
-        SecurityManager sm = System.getSecurityManager();
-        if (null != sm) {
-            sm.checkSetFactory();
-        }
-
-        NamingManager.ofb = ofb;
-    }
-
-    /**
-     * Create an <code>InitialContext</code> from either a previously
-     * installed <code>InitialContextFactoryBuilder</code> or from the
-     * <code>Context.INITIAL_CONTEXT_FACTORY</code> property in the supplied
-     * <code> Hashtable h</code> if no builder is installed. An installed
-     * <code>InitialContextFactoryBuilder</code> can generate a factory which
-     * can be used to create the <code>InitialContext</code>. The
-     * <code>Context.INITIAL_CONTEXT_FACTORY</code> property contains the
-     * class of a factory which can be used to create the
-     * <code>InitialContext</code>.
-     * 
-     * @param h
-     *            a hashtable containing properties and values - may be null
-     * @return an <code>InitialContext</code>
-     * @throws NoInitialContextException
-     *             if the <code>InitialContext</code> cannot be created.
-     * @throws NamingException
-     */
-    public static Context getInitialContext(Hashtable<?, ?> h)
-            throws NoInitialContextException, NamingException {
-
-        // if InitialContextFactoryBuilder is set
-        if (null != icfb) {
-            // create InitialContext using builder
-            return icfb.createInitialContextFactory(h).getInitialContext(h);
-        }
-
-        // create InitialContext using factory specified in hashtable
-        try {
-            // get factory class name
-            String factoryClassName =
-                (String) h.get(Context.INITIAL_CONTEXT_FACTORY);
-            // new factory instance
-            Class factoryClass = classForName(factoryClassName);
-            InitialContextFactory factory = (InitialContextFactory) factoryClass
-                    .newInstance();
-            // create initial context instance using the factory
-            return factory.getInitialContext(h);
-        } catch (NamingException e) {
-            // throw NamingException
-            throw e;
-        } catch (Exception e) {
-            // failed, throw NoInitialContextException
-            NamingException nex = new NoInitialContextException(
-                    "Failed to create InitialContext using factory specified in hashtable " //$NON-NLS-1$
-                            + h);
-            nex.setRootCause(e);
-            throw nex;
-        }
-    }
-
-    /**
-     * Create an object from either a previously installed
-     * <code>ObjectFactoryBuilder</code> or from a supplied reference or from
-     * the <code>Context.OBJECT_FACTORIES</code> property in the supplied
-     * <code>Hashtable h</code>.
-     * <p>
-     * An installed <code>ObjectFactoryBuilder</code> can generate a factory
-     * which can be used to create the object instance to return to caller. Any
-     * encountered exceptions are thrown.
-     * </p>
-     * <p>
-     * If an <code>ObjectFactoryBuilder</code> has not been installed then the
-     * supplied <code>Object o</code> may provide a <code>Reference</code>
-     * or <code>Referenceable</code> object. If so, then that
-     * <code>Object o</code> may have an associated class in a factory which
-     * could be loaded and used to create the object instance. If the factory
-     * class cannot be loaded then the <code>URLClassLoader</code> may be able
-     * to load a class from the list of URLs specified in the reference's
-     * factory class location. Any exceptions encountered are passed up.
-     * </p>
-     * <p>
-     * If a reference is supplied but no factory class can be loaded from it
-     * then this method returns the supplied object <code>o</code>.
-     * </p>
-     * <p>
-     * If a factory class loads successfully and can then be used to create an
-     * object instance then that instance is returned to the caller.
-     * </p>
-     * <p>
-     * If no factory name was associated with the <code>Reference</code>
-     * object <code>o</code> then see whether the <code>Reference</code> or
-     * <code>Referenceable</code> object has any <code>StringRefAddrs</code>
-     * of address type URL or url in its address list. For each entry in the
-     * list, in the order they appear in the list, it may be possible to use the
-     * URL factory to create the object. A URL in a <code>StringRefAddr</code>
-     * should have a scheme which can be used to locate the associated URL
-     * context factory in the same way as in the <code>getURLContext</code>
-     * method. (The scheme is the part which comes before :\. For example the
-     * URL http://www.apache.org has the scheme http.) A URL with no scheme
-     * would be ignored for these purposes.
-     * </p>
-     * <p>
-     * If no <code>ObjectFactoryBuilder</code> was installed, no factory class
-     * name is supplied with a <code>Reference</code> and no URL contexts
-     * succeeded in creating an <code>Object</code> then try the factories in
-     * <code>Context.OBJECT_FACTORIES</code> for this environment. Also try
-     * the provider resource file belonging to the context <code>c</code>.
-     * (See <code>Context</code> description for details of Provider resource
-     * files.) If any factory throws an exception then pass that back to the
-     * caller - no further factories are tried.
-     * </p>
-     * <p>
-     * If all factories fail to load or create the <code>Object</code> then
-     * return the argument object <code>o</code> as the returned object.
-     * </p>
-     * 
-     * @param o
-     *            an object which may provide reference or location information.
-     *            May be null.
-     * @param n
-     *            The name of the <code>Object</code> relative to the default
-     *            initial context(or relative to the Context c if it is
-     *            supplied)
-     * @param c
-     *            the <code>Context</code> to which the <code>Name</code> is
-     *            relative
-     * @param h
-     *            a <code>Hashtable</code> containing environment properties
-     *            and values - may be null
-     * @return a new <code>Object</code> or the supplied <code>Object o</code>
-     *         if one cannot be created.
-     * @throws NamingException
-     *             if one is encountered
-     * @throws Exception
-     *             if any other exception is encountered
-     */
-    public static Object getObjectInstance(Object o, Name n, Context c,
-            Hashtable<?, ?> h) throws NamingException, Exception {
-
-        // 1. try ObjectFactoryBuilder, if it is set
-        if (null != ofb) {
-            // use the builder to create an object factory
-            ObjectFactory factory = ofb.createObjectFactory(o, h);
-            // get object instance using the factory and return
-            return factory.getObjectInstance(o, n, c, h);
-        }
-
-        // 2. see whether o is a Referenceable or a Reference
-        Reference ref = null;
-        if (o instanceof Referenceable) {
-            ref = ((Referenceable) o).getReference();
-        }
-        if (o instanceof Reference) {
-            ref = (Reference) o;
-        }
-        // if o is a Referenceable or a Reference
-        if (null != ref) {
-            // if a factory class name is supplied by the reference, use it to
-            // create
-            if (null != ref.getFactoryClassName()) {
-                return getObjectInstanceByFactoryInReference(ref, o, n, c, h);
-            }
-            // see if ref has any StringRefAddrs of address type URL,
-            Object result = getObjectInstanceByUrlRefAddr(n, c, h, ref);
-            // if success, return it
-            if (null != result) {
-                return result;
-            }
-        }
-
-        // 3. try Context.OBJECT_FACTORIES
-        Object result = getObjectInstanceByObjectFactory(o, n, c, h);
-        if (null != result) {
-            return result;
-        }
-
-        // all failed, just return o
-        return o;
-    }
-
-    private static Object getObjectInstanceByObjectFactory(Object o, Name n,
-            Context c, Hashtable h) throws NamingException, Exception {
-        // obtain object factories from hashtable and service provider resource
-        // file
-        String fnames[] = EnvironmentReader
-                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
-                        Context.OBJECT_FACTORIES);
-        for (String element : fnames) {
-            // new factory instance by its class name
-            ObjectFactory factory = null;
-            try {
-                factory = (ObjectFactory) classForName(element).newInstance();
-            } catch (Exception e) {
-                continue;
-            }
-            // create object using factory
-            Object obj = factory.getObjectInstance(o, n, c, h);
-            if (null != obj) {
-                return obj;
-            }
-        }
-        // no object factory succeeded, return null
-        return null;
-    }
-
-    private static Object getObjectInstanceByUrlRefAddr(Name n, Context c,
-            Hashtable h, Reference ref) throws NamingException {
-        // obtain pkg prefixes from hashtable and service provider resource file
-        String pkgPrefixes[] = EnvironmentReader
-                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
-                        Context.URL_PKG_PREFIXES);
-        // for each RefAddr
-        Enumeration<RefAddr> enumeration = ref.getAll();
-        while (enumeration.hasMoreElements()) {
-            RefAddr addr = enumeration.nextElement();
-            // if it is StringRefAddr and type is URL
-            if (addr instanceof StringRefAddr
-                    && addr.getType().equalsIgnoreCase("URL")) { //$NON-NLS-1$
-                // get the url address
-                String url = (String) ((StringRefAddr) addr).getContent();
-                // try create using url context factory
-                Object obj = getObjectInstanceByUrlContextFactory(url, n, c, h,
-                        pkgPrefixes, UrlParser.getScheme(url));
-                // if success, return the created obj
-                if (null != obj) {
-                    return obj;
-                }
-            }
-        }
-        // failed to create using any StringRefAddr of address type URL, return
-        // null
-        return null;
-    }
-
-    private static Object getObjectInstanceByUrlContextFactory(String url,
-            Name n, Context c, Hashtable h, String pkgPrefixes[], String schema)
-            throws NamingException {
-        // if schema is empty or null, fail, return null
-        if (null == schema || 0 == schema.length()) {
-            return null;
-        }
-
-        for (String element : pkgPrefixes) {
-            ObjectFactory factory = null;
-            try {
-                // create url context factory instance
-                String clsName = element + "." //$NON-NLS-1$
-                        + schema + "." //$NON-NLS-1$
-                        + schema + "URLContextFactory"; //$NON-NLS-1$
-                factory = (ObjectFactory) classForName(clsName).newInstance();
-            } catch (Exception e) {
-                // failed to create factory, continue trying
-                continue;
-            }
-            try {
-                // create obj using url context factory
-                Object obj = factory.getObjectInstance(url, n, c, h);
-                // if create success, return it
-                if (null != obj) {
-                    return obj;
-                }
-            } catch (Exception e) {
-                // throw NamingException, if factory fails
-                if (e instanceof NamingException) {
-                    throw (NamingException) e;
-                }
-                NamingException nex = new NamingException(
-                        "Failed to create object instance"); //$NON-NLS-1$
-                nex.setRootCause(e);
-                throw nex;
-            }
-        }
-        // fail to create using url context factory, return null
-        return null;
-    }
-
-    private static Object getObjectInstanceByFactoryInReference(Reference ref,
-            Object o, Name n, Context c, Hashtable h) throws Exception {
-        ObjectFactory factory = null;
-
-        // try load the factory by its class name
-        try {
-            factory = (ObjectFactory) classForName(ref.getFactoryClassName())
-                    .newInstance();
-        } catch (ClassNotFoundException e) {
-            // Ignore.
-        }
-
-        // try load the factory from its class location
-        if (null == factory && null != ref.getFactoryClassLocation()) {
-            factory = (ObjectFactory) loadFactoryFromLocation(ref
-                    .getFactoryClassName(), ref.getFactoryClassLocation());
-        }
-        // if factory cannot be loaded
-        if (null == factory) {
-            // return o
-            return o;
-        }
-
-        // get object instance using the factory and return it
-        return factory.getObjectInstance(ref, n, c, h);
-    }
-
-    /*
-     * If cannot load class, return null. Throws any exceptions except
-     * ClassNotFoundException
-     */
-    private static Object loadFactoryFromLocation(String clsName,
-            String location) throws Exception {
-
-        // convert location into an array of URL, separated by ' '
-        StringTokenizer st = new StringTokenizer(location, " "); //$NON-NLS-1$
-        URL urls[] = new URL[st.countTokens()];
-        for (int i = 0; i < urls.length; i++) {
-            urls[i] = new URL(st.nextToken());
-        }
-
-        // new a URLClassLoader from the URLs
-        URLClassLoader l = new URLClassLoader(urls);
-
-        // try load factory by URLClassLoader
-        try {
-            // return the new instance
-            return l.loadClass(clsName).newInstance();
-        } catch (ClassNotFoundException e) {
-            // return null if class loading failed
-            return null;
-        }
-    }
-
-    /**
-     * Get the state of an Object.
-     * <p>
-     * The <code>Context.STATE_FACTORIES</code> property from the
-     * <code>Hashtable h</code> together with the
-     * <code>Context.STATE_FACTORIES</code> property from the provider
-     * resource file of the <code>Context c</code> provides the list of
-     * factories tried to get an object's state.
-     * </p>
-     * <p>
-     * Each factory in the list is attempted to be loaded using the context
-     * class loader. Once a class is loaded then it can be used to create a new
-     * instance of it to obtain the factory which can then use its
-     * <code>getStateToBind</code> to find the return object. Once an object
-     * is found then it is not necessary to examine further factories and the
-     * object is returned it as the return parameter.
-     * </p>
-     * <p>
-     * If no factory is loaded or all loaded factories fail to return an object
-     * then return the supplied <code>Object o</code> as the return param.
-     * </p>
-     * <p>
-     * Note for service provider implementors: Classes which implement the
-     * <code>StateFactory</code> interface must be public with a public
-     * constructor that has no parameters.
-     * </p>
-     * 
-     * @param o
-     *            an object which may provide reference or location information.
-     *            May be null.
-     * @param n
-     *            the name of the <code>Object</code> relative to the default
-     *            initial context (or relative to the Context c if it is
-     *            supplied)
-     * @param c
-     *            the <code>Context</code> to which the <code>Name</code> is
-     *            relative
-     * @param h
-     *            a <code>Hashtable</code> containing environment properties
-     *            and values - may be null
-     * @return the state of the specified object
-     * @throws NamingException
-     *             if one is encountered
-     */
-    public static Object getStateToBind(Object o, Name n,
-                                        Context c, Hashtable<?, ?> h)
-            throws NamingException {
-
-        // obtain state factories from hashtable and service provider resource
-        // file
-        String fnames[] = EnvironmentReader
-                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
-                        Context.STATE_FACTORIES);
-
-        for (String element : fnames) {
-            // new factory instance by its class name
-            StateFactory factory = null;
-            try {
-                factory = (StateFactory) classForName(element).newInstance();
-            } catch (Exception e) {
-                continue;
-            }
-            // try obtain state using the factory
-            Object state = factory.getStateToBind(o, n, c, h);
-            // if a state obtained successfully, return it
-            if (null != state) {
-                return state;
-            }
-        }
-
-        // all factories failed, return the input argument o
-        return o;
-    }
-
-    /**
-     * Creates a URL <code>Context</code> which can subsequently be used to
-     * resolve any URLs with the URL scheme s. A <code>URLContextFactory</code>
-     * is a type of <code>ObjectFactory</code> used to create a
-     * <code>URLContext</code> when <code>getObjectInstance</code> is
-     * invoked with the <code>Object o</code> set to null (see the description
-     * of <code>ObjectFactory</code>).
-     * <p>
-     * This <code>getURLContext</code> method tries to locate the
-     * <code>URLContextFactory</code> based on the
-     * <code>Context.URL_PKG_PREFIXES</code> property which contains the
-     * prefixes to be tried as the start of the package name. (See
-     * <code>Context</code>).
-     * </p>
-     * <p>
-     * Each package prefix entry (and finally the default value) are tried to
-     * find the class which can be used to create the Context.
-     * </p>
-     * <p>
-     * A full class name is derived as
-     * <code>packageprefix.s.sURLContextFactory</code> where <code>s</code>
-     * is the scheme.
-     * </p>
-     * <p>
-     * For example if a scheme is abc and the package prefix to try is com.ibm
-     * then the factory class to try is
-     * <code>com.ibm.abc.abcURLContextFactory</code>. Once a factory is
-     * created then a <code>Context</code> is created using the special use of
-     * <code>ObjectFactory.getObjectInstance</code>.
-     * </p>
-     * <p>
-     * Once a first factory is created, it is used to create the context, and NO
-     * further attemptions will be made on other pkg prefixes.
-     * </p>
-     * 
-     * @param schema
-     *            the URL scheme to which the Context will relate
-     * @param envmt
-     *            a <code>Hashtable</code> containing environment properties
-     *            and values - may be null
-     * @return the URL <code>Context</code> or null if no
-     *         <code>URLContextFactory</code> instance can be created and
-     *         therefore a Context cannot be created.
-     * @throws NamingException
-     *             if one is encountered.
-     */
-    public static Context getURLContext(String schema, Hashtable<?, ?> envmt)
-            throws NamingException {
-
-        if (null == schema || 0 == schema.length() || null == envmt) {
-            return null;
-        }
-
-        // obtain pkg prefixes from hashtable
-        String pkgPrefixes[] = EnvironmentReader
-                .getFactoryNamesFromEnvironmentAndProviderResource(envmt, null,
-                        Context.URL_PKG_PREFIXES);
-
-        for (String element : pkgPrefixes) {
-            // create factory instance
-            ObjectFactory factory;
-            try {
-                String clsName = element + "." //$NON-NLS-1$
-                        + schema + "." //$NON-NLS-1$
-                        + schema + "URLContextFactory"; //$NON-NLS-1$
-                factory = (ObjectFactory) classForName(clsName).newInstance();
-            } catch (Exception ex) {
-                // fail to create factory, continue to try another
-                continue;
-            }
-            try {
-                // create url context using the factory, and return it
-                return (Context) factory.getObjectInstance(null, null, null,
-                        envmt);
-            } catch (NamingException e) {
-                // find NamingException, throw it
-                throw e;
-            } catch (Exception e) {
-                // other exception, throw as NamingException
-                NamingException nex = new NamingException(
-                        "other exception happens: " + e.toString()); //$NON-NLS-1$
-                nex.setRootCause(e);
-                throw nex;
-            }
-        }
-
-        // cannot create context instance from any pkg prefixes, return null
-        return null;
-    }
-
-    /**
-     * Create the next context when using federation. All the information
-     * required to do this is contained in the
-     * <code>CannotProceedException</code> <code>e</code>. If the resolved
-     * object is null then throw the supplied
-     * <code>CannotProceedException</code> <code>e</code> using the stack
-     * details from this thread. The resolved object in <code>e</code> may
-     * already be a <code>Context</code>. This is the case where the service
-     * provider gives an explicit pointer to the next naming system. A Context
-     * object is returned as the continuation context, but need not be the same
-     * object instance as the resolved object.
-     * <p>
-     * If the resolved object is not already a <code>Context</code> then it is
-     * necessary to use the resolved object together with the
-     * <code>altName</code> name, the <code>altNameCtx</code> context and
-     * the environment hashtable to get an instance of the object. This should
-     * then be a context which is returned as the continuation context. If an
-     * instance cannot be obtained then throw the supplied
-     * <code>CannotProceedException</code> using the stack details from this
-     * thread.
-     * </p>
-     * <p>
-     * This method is responsible for setting the property denoted by the
-     * <code>CPE</code> string to be the supplied
-     * <code>CannotProceedException</code> for the exception <code>e</code>
-     * environment. The continuation context should then inherit this property.
-     * </p>
-     * 
-     * @param cpe
-     *            the <code>CannotProceedException</code> generated by the
-     *            context of the previous naming system when it can proceed no
-     *            further.
-     * @return the next Context when using federation
-     * @throws NamingException
-     *             if the resolved object is null or if a context cannot be
-     *             obtained from it either directly or indirectly.
-     */
-    public static Context getContinuationContext(CannotProceedException cpe)
-            throws NamingException {
-
-        Context ctx = null;
-
-        // set CPE property of the env
-        if (cpe.getEnvironment() == null) {
-            cpe.setEnvironment(new Hashtable<String, CannotProceedException>());
-        }
-        ((Hashtable<String, CannotProceedException>) cpe.getEnvironment()).put(
-                CPE, cpe);
-
-        // if resolved object is null
-        if (null == cpe.getResolvedObj()) {
-            // re-throw cpe
-            cpe.fillInStackTrace();
-            throw cpe;
-        }
-
-        // if cpe's resolved obj is Context
-        if (cpe.getResolvedObj() instanceof Context) {
-            // accept it as the continuation context
-            ctx = (Context) cpe.getResolvedObj();
-        } else {
-            // otherwise, call getObjectInstance() to get a context instance
-            try {
-                ctx = (Context) getObjectInstance(cpe.getResolvedObj(), cpe
-                        .getAltName(), cpe.getAltNameCtx(), cpe
-                        .getEnvironment());
-            } catch (Exception ex) {
-                // throw back CPE in case of any exception
-                throw cpe;
-            }
-            // if ctx cannot be obtained
-            if (null == ctx) {
-                // re-throw CPE
-                cpe.fillInStackTrace();
-                throw cpe;
-            }
-        }
-
-        // return the continuation context
-        return ctx;
-    }
-
-    private static Class classForName(final String className)
-            throws ClassNotFoundException {
-
-        Class cls = AccessController
-                .doPrivileged(new PrivilegedAction<Class>() {
-                    public Class run() {
-                        // try thread context class loader first
-                        try {
-                            return Class.forName(className, true, Thread
-                                    .currentThread().getContextClassLoader());
-                        } catch (ClassNotFoundException e) {
-                            // Ignored.
-                        }
-                        // try system class loader second
-                        try {
-                            return Class.forName(className, true, ClassLoader
-                                    .getSystemClassLoader());
-                        } catch (ClassNotFoundException e1) {
-                            // Ignored.
-                        }
-                        // return null, if fail to load class
-                        return null;
-                    }
-                });
-
-        if (cls == null) {
-            throw new ClassNotFoundException(
-                    "class " + className + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
-        }
-
-        return cls;
-    }
-}
+/* Copyright 2004, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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 javax.naming.spi;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+
+import javax.naming.CannotProceedException;
+import javax.naming.Context;
+import org.apache.harmony.jndi.internal.EnvironmentReader;
+import org.apache.harmony.jndi.internal.UrlParser;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.NoInitialContextException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+
+/**
+ * The <code>NamingManager</code> class should not be instantiated although it
+ * can be extended by classes within the <code>javax.naming.spi</code> package -
+ * see {@link DirectoryManager}. All its methods are static.
+ * <p>
+ * The methods are used by service providers for accessing object and state
+ * factories and for determining continuation contexts. Many of the methods
+ * create objects. These may be <code>Context</code> objects or objects
+ * referred to by the naming service.
+ * </p>
+ * <p>
+ * The <code>Name</code> and <code>Hashtable</code> arguments passed to the
+ * <code>NamingManager</code> methods remain owned purely by the calling
+ * method. They must not be changed or referenced.
+ * </p>
+ * <p>
+ * It should be noted that it is possible for an application to access a
+ * namespace other than that supplied by the default <code>InitialContext</code>
+ * (as specified by <code>Context.INITIAL_CONTEXT_FACTORY</code>). It is
+ * possible to call the following <code>InitialContext</code> methods passing
+ * a URL string either as the <code>String</code> or <code>Name</code>
+ * parameter: <code>lookup, bin, rebind, unbind, rename, list, listBindings, 
+ * destroySubcontext, createSubcontext, lookupLink, getNameParser</code>.
+ * This allows you to have one <code>InitialContext</code> object where these
+ * methods usually use the default initial context but access a URL
+ * <code>Context</code> instead when invoked with a URL string.
+ * </p>
+ * <p>
+ * A URL string is of the format abc:\nnnnnn where abc is the scheme of the URL.
+ * (See <code>InitialContext</code> where it refers to RFC1738.) When a URL
+ * string is supplied to those <code>InitialContext</code> methods, a URL
+ * context is used instead of the default initial context when performing that
+ * method. URL context factories are used to create URL contexts. A URL context
+ * factory is really just a service provider's implementation of an
+ * <code>ObjectFactory</code>. It is not essential that a service provider
+ * supplies one if they do not wish to support URL <code>Contexts.</code>
+ * </p>
+ * <p>
+ * See the <code>getURLContext</code> method for a description of how a URL
+ * context factory is located.
+ * </p>
+ * <p>
+ * Please note that multithreaded access to this class must be safe. For
+ * example, for thread safety, it should not be possible for one thread to read
+ * the installed <code>InitialContextFactoryBuilder</code> or
+ * <code>ObjectFactoryBuilder</code> while another thread is in the process of
+ * setting it.
+ * </p>
+ * <p>
+ * Also note that privileges should be granted to get the context classloader
+ * and to read the resource files.
+ * </p>
+ * 
+ * @see DirectoryManager
+ */
+
+public class NamingManager {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * The property name of <code>CannotProceedException</code> in a context's
+     * environment.
+     */
+    public static final String CPE = "java.naming.spi.CannotProceedException"; //$NON-NLS-1$
+
+    /*
+     * ------------------------------------------------------------------- 
+     * Class variables
+     * -------------------------------------------------------------------
+     */
+
+    static InitialContextFactoryBuilder icfb = null;
+
+    static ObjectFactoryBuilder ofb = null;
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+    NamingManager() {
+        // package private to prevent it being instanced but make it can be
+        // subclassed by DirectoryManager
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Install an <code>InitialContextFactoryBuilder</code>. Once this has
+     * been set it cannot be reset. Attempts to do so cause an
+     * <code>IllegalStateException</code>. The builder can only be installed
+     * if the security policy allows the setting of the factory.
+     * 
+     * @param icfb
+     *            the builder to be installed - can be null, but then no builder
+     *            is installed.
+     * @throws IllegalStateException
+     *             if an builder has already been installed.
+     * @throws SecurityException
+     *             is a security error prevents the installation.
+     * @throws NamingException
+     *             for other errors encountered.
+     */
+    public static synchronized void setInitialContextFactoryBuilder(
+            InitialContextFactoryBuilder icfb) throws IllegalStateException,
+            SecurityException, NamingException {
+
+        if (null != NamingManager.icfb) {
+            throw new IllegalStateException(
+                    "InitialContextFactoryBuilder cannot be reset"); //$NON-NLS-1$
+        }
+
+        // check security access
+        SecurityManager sm = System.getSecurityManager();
+        if (null != sm) {
+            sm.checkSetFactory();
+        }
+
+        NamingManager.icfb = icfb;
+    }
+
+    /**
+     * Returns true when an <code>InitialContextFactoryBuilder</code> has been
+     * installed.
+     * 
+     * @return true when an <code>InitialContextFactoryBuilder</code> has been
+     *         installed.
+     */
+    public static boolean hasInitialContextFactoryBuilder() {
+        return null != icfb;
+    }
+
+    /**
+     * Install an <code>ObjectFactoryBuilder</code>. Once this has been set
+     * it cannot be reset. Attempts to do so cause an
+     * <code>IllegalStateException</code>. The builder can only be installed
+     * if the security policy allows the setting of the factory.
+     * 
+     * @param ofb
+     *            the <code>ObjectFactoryBuilder</code> to be installed - can
+     *            be null, but then no builder is installed.
+     * @throws IllegalStateException
+     *             if an <code>ObjectFactoryBuilder</code> has already been
+     *             installed.
+     * @throws SecurityException
+     *             is a security error prevents the installation.
+     * @throws NamingException
+     *             for other errors encountered.
+     */
+    public static synchronized void setObjectFactoryBuilder(
+            ObjectFactoryBuilder ofb) throws IllegalStateException,
+            SecurityException, NamingException {
+
+        if (null != NamingManager.ofb) {
+            throw new IllegalStateException(
+                    "ObjectFactoryBuilder cannot be reset"); //$NON-NLS-1$
+        }
+
+        // check security access
+        SecurityManager sm = System.getSecurityManager();
+        if (null != sm) {
+            sm.checkSetFactory();
+        }
+
+        NamingManager.ofb = ofb;
+    }
+
+    /**
+     * Create an <code>InitialContext</code> from either a previously
+     * installed <code>InitialContextFactoryBuilder</code> or from the
+     * <code>Context.INITIAL_CONTEXT_FACTORY</code> property in the supplied
+     * <code> Hashtable h</code> if no builder is installed. An installed
+     * <code>InitialContextFactoryBuilder</code> can generate a factory which
+     * can be used to create the <code>InitialContext</code>. The
+     * <code>Context.INITIAL_CONTEXT_FACTORY</code> property contains the
+     * class of a factory which can be used to create the
+     * <code>InitialContext</code>.
+     * 
+     * @param h
+     *            a hashtable containing properties and values - may be null
+     * @return an <code>InitialContext</code>
+     * @throws NoInitialContextException
+     *             if the <code>InitialContext</code> cannot be created.
+     * @throws NamingException
+     */
+    public static Context getInitialContext(Hashtable<?, ?> h)
+            throws NoInitialContextException, NamingException {
+
+        // if InitialContextFactoryBuilder is set
+        if (null != icfb) {
+            // create InitialContext using builder
+            return icfb.createInitialContextFactory(h).getInitialContext(h);
+        }
+
+        // create InitialContext using factory specified in hashtable
+        try {
+            // get factory class name
+            String factoryClassName =
+                (String) h.get(Context.INITIAL_CONTEXT_FACTORY);
+            // new factory instance
+            Class factoryClass = classForName(factoryClassName);
+            InitialContextFactory factory = (InitialContextFactory) factoryClass
+                    .newInstance();
+            // create initial context instance using the factory
+            return factory.getInitialContext(h);
+        } catch (NamingException e) {
+            // throw NamingException
+            throw e;
+        } catch (Exception e) {
+            // failed, throw NoInitialContextException
+            NamingException nex = new NoInitialContextException(
+                    "Failed to create InitialContext using factory specified in hashtable " //$NON-NLS-1$
+                            + h);
+            nex.setRootCause(e);
+            throw nex;
+        }
+    }
+
+    /**
+     * Create an object from either a previously installed
+     * <code>ObjectFactoryBuilder</code> or from a supplied reference or from
+     * the <code>Context.OBJECT_FACTORIES</code> property in the supplied
+     * <code>Hashtable h</code>.
+     * <p>
+     * An installed <code>ObjectFactoryBuilder</code> can generate a factory
+     * which can be used to create the object instance to return to caller. Any
+     * encountered exceptions are thrown.
+     * </p>
+     * <p>
+     * If an <code>ObjectFactoryBuilder</code> has not been installed then the
+     * supplied <code>Object o</code> may provide a <code>Reference</code>
+     * or <code>Referenceable</code> object. If so, then that
+     * <code>Object o</code> may have an associated class in a factory which
+     * could be loaded and used to create the object instance. If the factory
+     * class cannot be loaded then the <code>URLClassLoader</code> may be able
+     * to load a class from the list of URLs specified in the reference's
+     * factory class location. Any exceptions encountered are passed up.
+     * </p>
+     * <p>
+     * If a reference is supplied but no factory class can be loaded from it
+     * then this method returns the supplied object <code>o</code>.
+     * </p>
+     * <p>
+     * If a factory class loads successfully and can then be used to create an
+     * object instance then that instance is returned to the caller.
+     * </p>
+     * <p>
+     * If no factory name was associated with the <code>Reference</code>
+     * object <code>o</code> then see whether the <code>Reference</code> or
+     * <code>Referenceable</code> object has any <code>StringRefAddrs</code>
+     * of address type URL or url in its address list. For each entry in the
+     * list, in the order they appear in the list, it may be possible to use the
+     * URL factory to create the object. A URL in a <code>StringRefAddr</code>
+     * should have a scheme which can be used to locate the associated URL
+     * context factory in the same way as in the <code>getURLContext</code>
+     * method. (The scheme is the part which comes before :\. For example the
+     * URL http://www.apache.org has the scheme http.) A URL with no scheme
+     * would be ignored for these purposes.
+     * </p>
+     * <p>
+     * If no <code>ObjectFactoryBuilder</code> was installed, no factory class
+     * name is supplied with a <code>Reference</code> and no URL contexts
+     * succeeded in creating an <code>Object</code> then try the factories in
+     * <code>Context.OBJECT_FACTORIES</code> for this environment. Also try
+     * the provider resource file belonging to the context <code>c</code>.
+     * (See <code>Context</code> description for details of Provider resource
+     * files.) If any factory throws an exception then pass that back to the
+     * caller - no further factories are tried.
+     * </p>
+     * <p>
+     * If all factories fail to load or create the <code>Object</code> then
+     * return the argument object <code>o</code> as the returned object.
+     * </p>
+     * 
+     * @param o
+     *            an object which may provide reference or location information.
+     *            May be null.
+     * @param n
+     *            The name of the <code>Object</code> relative to the default
+     *            initial context(or relative to the Context c if it is
+     *            supplied)
+     * @param c
+     *            the <code>Context</code> to which the <code>Name</code> is
+     *            relative
+     * @param h
+     *            a <code>Hashtable</code> containing environment properties
+     *            and values - may be null
+     * @return a new <code>Object</code> or the supplied <code>Object o</code>
+     *         if one cannot be created.
+     * @throws NamingException
+     *             if one is encountered
+     * @throws Exception
+     *             if any other exception is encountered
+     */
+    public static Object getObjectInstance(Object o, Name n, Context c,
+            Hashtable<?, ?> h) throws NamingException, Exception {
+
+        // 1. try ObjectFactoryBuilder, if it is set
+        if (null != ofb) {
+            // use the builder to create an object factory
+            ObjectFactory factory = ofb.createObjectFactory(o, h);
+            // get object instance using the factory and return
+            return factory.getObjectInstance(o, n, c, h);
+        }
+
+        // 2. see whether o is a Referenceable or a Reference
+        Reference ref = null;
+        if (o instanceof Referenceable) {
+            ref = ((Referenceable) o).getReference();
+        }
+        if (o instanceof Reference) {
+            ref = (Reference) o;
+        }
+        // if o is a Referenceable or a Reference
+        if (null != ref) {
+            // if a factory class name is supplied by the reference, use it to
+            // create
+            if (null != ref.getFactoryClassName()) {
+                return getObjectInstanceByFactoryInReference(ref, o, n, c, h);
+            }
+            // see if ref has any StringRefAddrs of address type URL,
+            Object result = getObjectInstanceByUrlRefAddr(n, c, h, ref);
+            // if success, return it
+            if (null != result) {
+                return result;
+            }
+        }
+
+        // 3. try Context.OBJECT_FACTORIES
+        Object result = getObjectInstanceByObjectFactory(o, n, c, h);
+        if (null != result) {
+            return result;
+        }
+
+        // all failed, just return o
+        return o;
+    }
+
+    private static Object getObjectInstanceByObjectFactory(Object o, Name n,
+            Context c, Hashtable h) throws NamingException, Exception {
+        // obtain object factories from hashtable and service provider resource
+        // file
+        String fnames[] = EnvironmentReader
+                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
+                        Context.OBJECT_FACTORIES);
+        for (String element : fnames) {
+            // new factory instance by its class name
+            ObjectFactory factory = null;
+            try {
+                factory = (ObjectFactory) classForName(element).newInstance();
+            } catch (Exception e) {
+                continue;
+            }
+            // create object using factory
+            Object obj = factory.getObjectInstance(o, n, c, h);
+            if (null != obj) {
+                return obj;
+            }
+        }
+        // no object factory succeeded, return null
+        return null;
+    }
+
+    private static Object getObjectInstanceByUrlRefAddr(Name n, Context c,
+            Hashtable h, Reference ref) throws NamingException {
+        // obtain pkg prefixes from hashtable and service provider resource file
+        String pkgPrefixes[] = EnvironmentReader
+                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
+                        Context.URL_PKG_PREFIXES);
+        // for each RefAddr
+        Enumeration<RefAddr> enumeration = ref.getAll();
+        while (enumeration.hasMoreElements()) {
+            RefAddr addr = enumeration.nextElement();
+            // if it is StringRefAddr and type is URL
+            if (addr instanceof StringRefAddr
+                    && addr.getType().equalsIgnoreCase("URL")) { //$NON-NLS-1$
+                // get the url address
+                String url = (String) ((StringRefAddr) addr).getContent();
+                // try create using url context factory
+                Object obj = getObjectInstanceByUrlContextFactory(url, n, c, h,
+                        pkgPrefixes, UrlParser.getScheme(url));
+                // if success, return the created obj
+                if (null != obj) {
+                    return obj;
+                }
+            }
+        }
+        // failed to create using any StringRefAddr of address type URL, return
+        // null
+        return null;
+    }
+
+    private static Object getObjectInstanceByUrlContextFactory(String url,
+            Name n, Context c, Hashtable h, String pkgPrefixes[], String schema)
+            throws NamingException {
+        // if schema is empty or null, fail, return null
+        if (null == schema || 0 == schema.length()) {
+            return null;
+        }
+
+        for (String element : pkgPrefixes) {
+            ObjectFactory factory = null;
+            try {
+                // create url context factory instance
+                String clsName = element + "." //$NON-NLS-1$
+                        + schema + "." //$NON-NLS-1$
+                        + schema + "URLContextFactory"; //$NON-NLS-1$
+                factory = (ObjectFactory) classForName(clsName).newInstance();
+            } catch (Exception e) {
+                // failed to create factory, continue trying
+                continue;
+            }
+            try {
+                // create obj using url context factory
+                Object obj = factory.getObjectInstance(url, n, c, h);
+                // if create success, return it
+                if (null != obj) {
+                    return obj;
+                }
+            } catch (Exception e) {
+                // throw NamingException, if factory fails
+                if (e instanceof NamingException) {
+                    throw (NamingException) e;
+                }
+                NamingException nex = new NamingException(
+                        "Failed to create object instance"); //$NON-NLS-1$
+                nex.setRootCause(e);
+                throw nex;
+            }
+        }
+        // fail to create using url context factory, return null
+        return null;
+    }
+
+    private static Object getObjectInstanceByFactoryInReference(Reference ref,
+            Object o, Name n, Context c, Hashtable h) throws Exception {
+        ObjectFactory factory = null;
+
+        // try load the factory by its class name
+        try {
+            factory = (ObjectFactory) classForName(ref.getFactoryClassName())
+                    .newInstance();
+        } catch (ClassNotFoundException e) {
+            // Ignore.
+        }
+
+        // try load the factory from its class location
+        if (null == factory && null != ref.getFactoryClassLocation()) {
+            factory = (ObjectFactory) loadFactoryFromLocation(ref
+                    .getFactoryClassName(), ref.getFactoryClassLocation());
+        }
+        // if factory cannot be loaded
+        if (null == factory) {
+            // return o
+            return o;
+        }
+
+        // get object instance using the factory and return it
+        return factory.getObjectInstance(ref, n, c, h);
+    }
+
+    /*
+     * If cannot load class, return null. Throws any exceptions except
+     * ClassNotFoundException
+     */
+    private static Object loadFactoryFromLocation(String clsName,
+            String location) throws Exception {
+
+        // convert location into an array of URL, separated by ' '
+        StringTokenizer st = new StringTokenizer(location, " "); //$NON-NLS-1$
+        URL urls[] = new URL[st.countTokens()];
+        for (int i = 0; i < urls.length; i++) {
+            urls[i] = new URL(st.nextToken());
+        }
+
+        // new a URLClassLoader from the URLs
+        URLClassLoader l = new URLClassLoader(urls);
+
+        // try load factory by URLClassLoader
+        try {
+            // return the new instance
+            return l.loadClass(clsName).newInstance();
+        } catch (ClassNotFoundException e) {
+            // return null if class loading failed
+            return null;
+        }
+    }
+
+    /**
+     * Get the state of an Object.
+     * <p>
+     * The <code>Context.STATE_FACTORIES</code> property from the
+     * <code>Hashtable h</code> together with the
+     * <code>Context.STATE_FACTORIES</code> property from the provider
+     * resource file of the <code>Context c</code> provides the list of
+     * factories tried to get an object's state.
+     * </p>
+     * <p>
+     * Each factory in the list is attempted to be loaded using the context
+     * class loader. Once a class is loaded then it can be used to create a new
+     * instance of it to obtain the factory which can then use its
+     * <code>getStateToBind</code> to find the return object. Once an object
+     * is found then it is not necessary to examine further factories and the
+     * object is returned it as the return parameter.
+     * </p>
+     * <p>
+     * If no factory is loaded or all loaded factories fail to return an object
+     * then return the supplied <code>Object o</code> as the return param.
+     * </p>
+     * <p>
+     * Note for service provider implementors: Classes which implement the
+     * <code>StateFactory</code> interface must be public with a public
+     * constructor that has no parameters.
+     * </p>
+     * 
+     * @param o
+     *            an object which may provide reference or location information.
+     *            May be null.
+     * @param n
+     *            the name of the <code>Object</code> relative to the default
+     *            initial context (or relative to the Context c if it is
+     *            supplied)
+     * @param c
+     *            the <code>Context</code> to which the <code>Name</code> is
+     *            relative
+     * @param h
+     *            a <code>Hashtable</code> containing environment properties
+     *            and values - may be null
+     * @return the state of the specified object
+     * @throws NamingException
+     *             if one is encountered
+     */
+    public static Object getStateToBind(Object o, Name n,
+                                        Context c, Hashtable<?, ?> h)
+            throws NamingException {
+
+        // obtain state factories from hashtable and service provider resource
+        // file
+        String fnames[] = EnvironmentReader
+                .getFactoryNamesFromEnvironmentAndProviderResource(h, c,
+                        Context.STATE_FACTORIES);
+
+        for (String element : fnames) {
+            // new factory instance by its class name
+            StateFactory factory = null;
+            try {
+                factory = (StateFactory) classForName(element).newInstance();
+            } catch (Exception e) {
+                continue;
+            }
+            // try obtain state using the factory
+            Object state = factory.getStateToBind(o, n, c, h);
+            // if a state obtained successfully, return it
+            if (null != state) {
+                return state;
+            }
+        }
+
+        // all factories failed, return the input argument o
+        return o;
+    }
+
+    /**
+     * Creates a URL <code>Context</code> which can subsequently be used to
+     * resolve any URLs with the URL scheme s. A <code>URLContextFactory</code>
+     * is a type of <code>ObjectFactory</code> used to create a
+     * <code>URLContext</code> when <code>getObjectInstance</code> is
+     * invoked with the <code>Object o</code> set to null (see the description
+     * of <code>ObjectFactory</code>).
+     * <p>
+     * This <code>getURLContext</code> method tries to locate the
+     * <code>URLContextFactory</code> based on the
+     * <code>Context.URL_PKG_PREFIXES</code> property which contains the
+     * prefixes to be tried as the start of the package name. (See
+     * <code>Context</code>).
+     * </p>
+     * <p>
+     * Each package prefix entry (and finally the default value) are tried to
+     * find the class which can be used to create the Context.
+     * </p>
+     * <p>
+     * A full class name is derived as
+     * <code>packageprefix.s.sURLContextFactory</code> where <code>s</code>
+     * is the scheme.
+     * </p>
+     * <p>
+     * For example if a scheme is abc and the package prefix to try is com.ibm
+     * then the factory class to try is
+     * <code>com.ibm.abc.abcURLContextFactory</code>. Once a factory is
+     * created then a <code>Context</code> is created using the special use of
+     * <code>ObjectFactory.getObjectInstance</code>.
+     * </p>
+     * <p>
+     * Once a first factory is created, it is used to create the context, and NO
+     * further attemptions will be made on other pkg prefixes.
+     * </p>
+     * 
+     * @param schema
+     *            the URL scheme to which the Context will relate
+     * @param envmt
+     *            a <code>Hashtable</code> containing environment properties
+     *            and values - may be null
+     * @return the URL <code>Context</code> or null if no
+     *         <code>URLContextFactory</code> instance can be created and
+     *         therefore a Context cannot be created.
+     * @throws NamingException
+     *             if one is encountered.
+     */
+    public static Context getURLContext(String schema, Hashtable<?, ?> envmt)
+            throws NamingException {
+
+        if (null == schema || 0 == schema.length() || null == envmt) {
+            return null;
+        }
+
+        // obtain pkg prefixes from hashtable
+        String pkgPrefixes[] = EnvironmentReader
+                .getFactoryNamesFromEnvironmentAndProviderResource(envmt, null,
+                        Context.URL_PKG_PREFIXES);
+
+        for (String element : pkgPrefixes) {
+            // create factory instance
+            ObjectFactory factory;
+            try {
+                String clsName = element + "." //$NON-NLS-1$
+                        + schema + "." //$NON-NLS-1$
+                        + schema + "URLContextFactory"; //$NON-NLS-1$
+                factory = (ObjectFactory) classForName(clsName).newInstance();
+            } catch (Exception ex) {
+                // fail to create factory, continue to try another
+                continue;
+            }
+            try {
+                // create url context using the factory, and return it
+                return (Context) factory.getObjectInstance(null, null, null,
+                        envmt);
+            } catch (NamingException e) {
+                // find NamingException, throw it
+                throw e;
+            } catch (Exception e) {
+                // other exception, throw as NamingException
+                NamingException nex = new NamingException(
+                        "other exception happens: " + e.toString()); //$NON-NLS-1$
+                nex.setRootCause(e);
+                throw nex;
+            }
+        }
+
+        // cannot create context instance from any pkg prefixes, return null
+        return null;
+    }
+
+    /**
+     * Create the next context when using federation. All the information
+     * required to do this is contained in the
+     * <code>CannotProceedException</code> <code>e</code>. If the resolved
+     * object is null then throw the supplied
+     * <code>CannotProceedException</code> <code>e</code> using the stack
+     * details from this thread. The resolved object in <code>e</code> may
+     * already be a <code>Context</code>. This is the case where the service
+     * provider gives an explicit pointer to the next naming system. A Context
+     * object is returned as the continuation context, but need not be the same
+     * object instance as the resolved object.
+     * <p>
+     * If the resolved object is not already a <code>Context</code> then it is
+     * necessary to use the resolved object together with the
+     * <code>altName</code> name, the <code>altNameCtx</code> context and
+     * the environment hashtable to get an instance of the object. This should
+     * then be a context which is returned as the continuation context. If an
+     * instance cannot be obtained then throw the supplied
+     * <code>CannotProceedException</code> using the stack details from this
+     * thread.
+     * </p>
+     * <p>
+     * This method is responsible for setting the property denoted by the
+     * <code>CPE</code> string to be the supplied
+     * <code>CannotProceedException</code> for the exception <code>e</code>
+     * environment. The continuation context should then inherit this property.
+     * </p>
+     * 
+     * @param cpe
+     *            the <code>CannotProceedException</code> generated by the
+     *            context of the previous naming system when it can proceed no
+     *            further.
+     * @return the next Context when using federation
+     * @throws NamingException
+     *             if the resolved object is null or if a context cannot be
+     *             obtained from it either directly or indirectly.
+     */
+    public static Context getContinuationContext(CannotProceedException cpe)
+            throws NamingException {
+
+        Context ctx = null;
+
+        // set CPE property of the env
+        if (cpe.getEnvironment() == null) {
+            cpe.setEnvironment(new Hashtable<String, CannotProceedException>());
+        }
+        ((Hashtable<String, CannotProceedException>) cpe.getEnvironment()).put(
+                CPE, cpe);
+
+        // if resolved object is null
+        if (null == cpe.getResolvedObj()) {
+            // re-throw cpe
+            cpe.fillInStackTrace();
+            throw cpe;
+        }
+
+        // if cpe's resolved obj is Context
+        if (cpe.getResolvedObj() instanceof Context) {
+            // accept it as the continuation context
+            ctx = (Context) cpe.getResolvedObj();
+        } else {
+            // otherwise, call getObjectInstance() to get a context instance
+            try {
+                ctx = (Context) getObjectInstance(cpe.getResolvedObj(), cpe
+                        .getAltName(), cpe.getAltNameCtx(), cpe
+                        .getEnvironment());
+            } catch (Exception ex) {
+                // throw back CPE in case of any exception
+                throw cpe;
+            }
+            // if ctx cannot be obtained
+            if (null == ctx) {
+                // re-throw CPE
+                cpe.fillInStackTrace();
+                throw cpe;
+            }
+        }
+
+        // return the continuation context
+        return ctx;
+    }
+
+    private static Class classForName(final String className)
+            throws ClassNotFoundException {
+
+        Class cls = AccessController
+                .doPrivileged(new PrivilegedAction<Class>() {
+                    public Class run() {
+                        // try thread context class loader first
+                        try {
+                            return Class.forName(className, true, Thread
+                                    .currentThread().getContextClassLoader());
+                        } catch (ClassNotFoundException e) {
+                            // Ignored.
+                        }
+                        // try system class loader second
+                        try {
+                            return Class.forName(className, true, ClassLoader
+                                    .getSystemClassLoader());
+                        } catch (ClassNotFoundException e1) {
+                            // Ignored.
+                        }
+                        // return null, if fail to load class
+                        return null;
+                    }
+                });
+
+        if (cls == null) {
+            throw new ClassNotFoundException(
+                    "class " + className + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        return cls;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java?rev=437433&r1=437432&r2=437433&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java Sun Aug 27 11:26:20 2006
@@ -1,108 +1,108 @@
-/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
- * 
- * Licensed 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 javax.naming.spi;
-
-import java.util.Hashtable;
-import javax.naming.Name;
-import javax.naming.Context;
-
-/**
- * An <code>ObjectFactory</code> creates objects of a specified type. A variety
- * of different objects may be used by a JNDI application; these objects are
- * meaningful to the application and can be manipulated according to the
- * methods available to the class of the object, such as a printer object.
- * The class implementing this interface should be public, should also provide
- * a public constructor taking no arguments, and should be thread-safe. Where
- * URL is mentioned below, this refers to RFC 1738 and related RFCs.
- *  
- */
-public interface ObjectFactory {
-
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
-    /**
-     * Creates an object of the type specified by parameter <code>o</code>, 
-     * including any reference or location details, customised by the specified
-     * <code>envmt</code> parameter. 
-     * <p>
-     * Object factories are specified via environment properties from several
-     * sources including provider properties files (see the specification of 
-     * the <code>Context</code> interface) and may comprise a list of factories. 
-     * Each object factory in the list is used by 
-     * <code>NamingManager.getObjectInstance()</code> which invokes this method 
-     * on each of them until a non-null result is achieved or until the list is 
-     * exhausted. If an <code>ObjectFactory</code> throws an exception, it 
-     * should be passed back to the code that invoked
-     * <code>NamingManager.getObjectInstance()</code> and no further object 
-     * factories in the list are examined. An exception should only be thrown 
-     * by an object factory if it is intended that no other object factories 
-     * be examined. Usually, if an <code>ObjectFactory</code> is unable to 
-     * create an object, then null should be returned.</p>
-     * <p>
-     * A special case of <code>ObjectFactory</code> is a URL context factory 
-     * which is used either to create an object whose location is specified by 
-     * a URL passed as the object <code>o</code> or creates contexts for 
-     * resolving URLs. The <code>getObjectInstance()</code> method of a URL
-     * context factory must obey these rules:</p>
-     * <p>
-     * 1. When <code>Object o</code> is null, return a new Context object 
-     * suitable for resolving any URL of the scheme supported by this factory.</p>
-     * <p>
-     * 2. When <code>Object o</code> is a URL string, return a new object 
-     * (usually a context) identified by the URL, so that names relatively 
-     * lower than that context may be resolved. </p>
-     * <p>
-     * 3. When <code>Object o</code> is an <code>Array</code> object with more 
-     * than one URL string (order is not important), return a new object 
-     * (usually a context) identified by the URL as in rule 2, above. The URLs 
-     * in the array are considered to be equivalent in relation to the 
-     * associated context, but the object (context) factory can choose whether 
-     * or not to verify that they are truly equivalent.</p>
-     * <p>
-     * 4. Otherwise, the behaviour of this method depends on the context 
-     * factory implementation.</p>
-     * 
-     * @param o     may be null or may contain location or reference details
-     * @param n     the name relative to the context <code>c</code> of the 
-     *              object being created and may be null; the implementation 
-     *              may clone or copy this object, but will not modify the 
-     *              original.
-     * @param c     may be null when the name is relative to the default 
-     *              initial context, or specifies the context to which the 
-     *              name is relative (if a factory uses this context object, 
-     *              synchronization should be used as Context objects are not
-     *              thread-safe).
-     * @param envmt may be null; the implementation may clone or copy this 
-     *              object, but will not modify the original.
-     * @return      either an object of the specified type or null if no 
-     *              object could be created.
-     * @throws Exception causes no further object factory will be tried
-     */
-    Object getObjectInstance(
-        Object o,
-        Name n,
-        Context c,
-        Hashtable<?, ?> envmt)
-        throws Exception;
-
-}
-
-
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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 javax.naming.spi;
+
+import java.util.Hashtable;
+import javax.naming.Name;
+import javax.naming.Context;
+
+/**
+ * An <code>ObjectFactory</code> creates objects of a specified type. A variety
+ * of different objects may be used by a JNDI application; these objects are
+ * meaningful to the application and can be manipulated according to the
+ * methods available to the class of the object, such as a printer object.
+ * The class implementing this interface should be public, should also provide
+ * a public constructor taking no arguments, and should be thread-safe. Where
+ * URL is mentioned below, this refers to RFC 1738 and related RFCs.
+ *  
+ */
+public interface ObjectFactory {
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Creates an object of the type specified by parameter <code>o</code>, 
+     * including any reference or location details, customised by the specified
+     * <code>envmt</code> parameter. 
+     * <p>
+     * Object factories are specified via environment properties from several
+     * sources including provider properties files (see the specification of 
+     * the <code>Context</code> interface) and may comprise a list of factories. 
+     * Each object factory in the list is used by 
+     * <code>NamingManager.getObjectInstance()</code> which invokes this method 
+     * on each of them until a non-null result is achieved or until the list is 
+     * exhausted. If an <code>ObjectFactory</code> throws an exception, it 
+     * should be passed back to the code that invoked
+     * <code>NamingManager.getObjectInstance()</code> and no further object 
+     * factories in the list are examined. An exception should only be thrown 
+     * by an object factory if it is intended that no other object factories 
+     * be examined. Usually, if an <code>ObjectFactory</code> is unable to 
+     * create an object, then null should be returned.</p>
+     * <p>
+     * A special case of <code>ObjectFactory</code> is a URL context factory 
+     * which is used either to create an object whose location is specified by 
+     * a URL passed as the object <code>o</code> or creates contexts for 
+     * resolving URLs. The <code>getObjectInstance()</code> method of a URL
+     * context factory must obey these rules:</p>
+     * <p>
+     * 1. When <code>Object o</code> is null, return a new Context object 
+     * suitable for resolving any URL of the scheme supported by this factory.</p>
+     * <p>
+     * 2. When <code>Object o</code> is a URL string, return a new object 
+     * (usually a context) identified by the URL, so that names relatively 
+     * lower than that context may be resolved. </p>
+     * <p>
+     * 3. When <code>Object o</code> is an <code>Array</code> object with more 
+     * than one URL string (order is not important), return a new object 
+     * (usually a context) identified by the URL as in rule 2, above. The URLs 
+     * in the array are considered to be equivalent in relation to the 
+     * associated context, but the object (context) factory can choose whether 
+     * or not to verify that they are truly equivalent.</p>
+     * <p>
+     * 4. Otherwise, the behaviour of this method depends on the context 
+     * factory implementation.</p>
+     * 
+     * @param o     may be null or may contain location or reference details
+     * @param n     the name relative to the context <code>c</code> of the 
+     *              object being created and may be null; the implementation 
+     *              may clone or copy this object, but will not modify the 
+     *              original.
+     * @param c     may be null when the name is relative to the default 
+     *              initial context, or specifies the context to which the 
+     *              name is relative (if a factory uses this context object, 
+     *              synchronization should be used as Context objects are not
+     *              thread-safe).
+     * @param envmt may be null; the implementation may clone or copy this 
+     *              object, but will not modify the original.
+     * @return      either an object of the specified type or null if no 
+     *              object could be created.
+     * @throws Exception causes no further object factory will be tried
+     */
+    Object getObjectInstance(
+        Object o,
+        Name n,
+        Context c,
+        Hashtable<?, ?> envmt)
+        throws Exception;
+
+}
+
+

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java?rev=437433&r1=437432&r2=437433&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java Sun Aug 27 11:26:20 2006
@@ -1,58 +1,58 @@
-/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
- * 
- * Licensed 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 javax.naming.spi;
-
-import java.util.Hashtable;
-import javax.naming.NamingException;
-
-/**
- * An object factory builder creates an object factory, and an object factory
- * creates objects of a specified type. A variety of different objects may be
- * used by a JNDI application; these objects are meaningful to the application
- * and can be manipulated according to the methods available to the class of
- * the object, such as a printer object. The application uses
- * <code>NamingManager.setObjectFactoryBuilder()</code> to specify its own or 
- * its preferred builder to override JNDI default policies; any such builder 
- * must implement the <code>ObjectFactoryBuilder</code> interface.
- * 
- */
-public interface ObjectFactoryBuilder {
-
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
-    /**
-     * Returns an <code>ObjectFactory</code> customised by the 
-     * <code>envmt</code> parameter that is capable of creating instances
-     * of the object <code>o</code>. 
-     * 
-     * @param o     may be null
-     * @param envmt may be null
-     * @return      an <code>ObjectFactory</code> customised by the 
-     *              <code>envmt</code> parameter that is capable of creating
-     *              instances of the object <code>o</code>. 
-     * @throws NamingException if an object factory could not be created.
-     */
-    ObjectFactory createObjectFactory(Object o, Hashtable<?, ?> envmt)
-        throws NamingException;
-
-}
-
-
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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 javax.naming.spi;
+
+import java.util.Hashtable;
+import javax.naming.NamingException;
+
+/**
+ * An object factory builder creates an object factory, and an object factory
+ * creates objects of a specified type. A variety of different objects may be
+ * used by a JNDI application; these objects are meaningful to the application
+ * and can be manipulated according to the methods available to the class of
+ * the object, such as a printer object. The application uses
+ * <code>NamingManager.setObjectFactoryBuilder()</code> to specify its own or 
+ * its preferred builder to override JNDI default policies; any such builder 
+ * must implement the <code>ObjectFactoryBuilder</code> interface.
+ * 
+ */
+public interface ObjectFactoryBuilder {
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Returns an <code>ObjectFactory</code> customised by the 
+     * <code>envmt</code> parameter that is capable of creating instances
+     * of the object <code>o</code>. 
+     * 
+     * @param o     may be null
+     * @param envmt may be null
+     * @return      an <code>ObjectFactory</code> customised by the 
+     *              <code>envmt</code> parameter that is capable of creating
+     *              instances of the object <code>o</code>. 
+     * @throws NamingException if an object factory could not be created.
+     */
+    ObjectFactory createObjectFactory(Object o, Hashtable<?, ?> envmt)
+        throws NamingException;
+
+}
+
+

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ResolveResult.java
------------------------------------------------------------------------------
    svn:eol-style = native