You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/15 15:57:17 UTC

svn commit: r386087 [9/45] - in /incubator/harmony/enhanced/classlib/trunk: make/ make/patternsets/ modules/jndi/ modules/jndi/META-INF/ modules/jndi/make/ modules/jndi/make/common/ modules/jndi/src/ modules/jndi/src/main/ modules/jndi/src/main/java/ m...

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/NamingManager.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,832 @@
+/* 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.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 com.ibm.jndi.EnvironmentReader;
+import com.ibm.jndi.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 each object factory
+        for (int i = 0; i < fnames.length; i++) {
+            // new factory instance by its class name
+            ObjectFactory factory = null;
+            try {
+                factory = (ObjectFactory) classForName(fnames[i]).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 enumeration = ref.getAll();
+        while (enumeration.hasMoreElements()) {
+            RefAddr addr = (RefAddr) 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 each pkg prefix
+        for (int i = 0; i < pkgPrefixes.length; i++) {
+            ObjectFactory factory = null;
+            try {
+                // create url context factory instance
+                String clsName =
+                    pkgPrefixes[i]
+                        + "." //$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 each state factory
+        for (int i = 0; i < fnames.length; i++) {
+            // new factory instance by its class name
+            StateFactory factory = null;
+            try {
+                factory = (StateFactory) classForName(fnames[i]).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 each pkg prefix
+        for (int i = 0; i < pkgPrefixes.length; i++) {
+            // create factory instance
+            ObjectFactory factory;
+            try {
+                String clsName =
+                    pkgPrefixes[i]
+                        + "." //$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());
+        }
+        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 =
+            (Class) AccessController.doPrivileged(new PrivilegedAction() {
+            public Object 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;
+
+    }
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +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;
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ObjectFactoryBuilder.java Wed Mar 15 06:55:38 2006
@@ -0,0 +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;
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ResolveResult.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ResolveResult.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ResolveResult.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/ResolveResult.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,219 @@
+/* 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 javax.naming.Name;
+import javax.naming.InvalidNameException;
+import javax.naming.CompositeName;
+
+/**
+ * An instance of <code>ResolveResult</code> is produced when a name 
+ * resolution operation has completed. The instance must contain the object
+ * associated with the successfully resolved name, and any remaining portion
+ * of the name yet to be resolved. Where a <code>String</code> parameter is 
+ * used to specify a name, it should be considered to be a composite name. 
+ * <p>
+ * Multithreaded access to a single <code>ResolveResult</code> instance is 
+ * only safe when client code locks the object first.</p>
+ *
+ */
+public class ResolveResult implements java.io.Serializable {
+
+    /*
+     * -------------------------------------------------------------------
+     * Constants
+     * -------------------------------------------------------------------
+     */
+
+    /*
+     * This field must have value -4552108072002407559L and should be commented
+     * with text "J2SE 1.4.2".  
+     */ 
+    static final long serialVersionUID = -4552108072002407559L;
+
+    /*
+     * -------------------------------------------------------------------
+     * Instance variables
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * This field holds the object associated with the resolved name.
+     * It may be null only when a subclass is constructed. It must be 
+     * initialized to a non-null value by constructors of this class.
+     * 
+     * @serial
+     */
+    protected Object resolvedObj;
+
+    /**
+     * This field holds the portion of a resolved name that remains to be
+     * resolved. It may be null only when a subclass is constructed. It must 
+     * be initialized to a non-null value by constructors of this class.
+     * 
+     * @serial 
+     */
+    protected Name remainingName;
+
+
+    /*
+     * -------------------------------------------------------------------
+     * Constructors
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * This is the default constructor implicitly invoked by subclass
+     * constructors. This constructor set both the resolved object and 
+     * the remaining name to null.
+     */
+    protected ResolveResult() {
+        this.resolvedObj = null;
+        this.remainingName = null;
+    }
+
+    /**
+     * This constructor creates a instance with the specified resolved 
+     * object and a specified remaining name of type <code>String</code>. The 
+     * name argument may not be null, but may be empty. The object argument
+     * may not be null.
+     *
+     * @param o may not be null
+     * @param s may not be null, but may be empty
+     */
+    public ResolveResult(Object o, String s) {
+        this.resolvedObj = o;
+        try {
+            this.remainingName = new CompositeName(s);
+        } catch (InvalidNameException e) {
+            this.remainingName = null;
+        }
+    }
+
+    /**
+     * This constructor creates a instance with the specified resolved 
+     * object and a remaining name of type <code>Name</code>. The name 
+     * argument may not be null, but may be empty. The object argument 
+     * may not be null.
+     * 
+     * @param o may not be null
+     * @param n may not be null
+     */
+    public ResolveResult(Object o, Name n) {
+        this.resolvedObj = o;
+        if (null == n) {
+            this.remainingName = null;
+        } else {
+            this.remainingName = (Name) n.clone();
+        }
+    }
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Extends the remaining name (remainingName) with a single 
+     * specified name component. The name argument may be null, but this 
+     * leaves the remaining name unmodified.
+     * 
+     * @param s the name component to be added to the remaining name.
+     *          A null leaves the remaining name unmodified.
+     */
+    public void appendRemainingComponent(String s) {
+        if (null != s) {
+            if (null == this.remainingName) {
+                this.remainingName = new CompositeName();
+            }
+            try {
+                remainingName.add(s);
+            } catch (InvalidNameException e) {
+                throw new Error(e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Extends the remaining name (remainingName) with all components of
+     * the specified name. The name argument may be null, but this leaves the
+     * remaining name unmodified.
+     *  
+     * @param n the name to be added to the remaining name
+     *          A null leaves the remaining name unmodified.
+     */
+    public void appendRemainingName(Name n) {
+        if (null != n) {
+            if (null == this.remainingName) {
+                this.remainingName = (Name) n.clone();
+            } else {
+                try {
+                    this.remainingName.addAll(n);
+                } catch (InvalidNameException e) {
+                    throw new Error(e.getMessage());
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns any unresolved portion of the name that was resolved 
+     * (the remaining name). The returned <code>Name</code> may be empty, 
+     * but may not be null.
+     * 
+     * @return  any unresolved portion of the name that was resolved
+     *          (the remaining name).
+     */
+    public Name getRemainingName() {
+        return this.remainingName;
+    }
+
+    /**
+     * Returns the non-null object that was resolved (resolved object).
+     *  
+     * @return the non-null object that was resolved (resolved object).
+     */
+    public Object getResolvedObj() {
+        return this.resolvedObj;
+    }
+
+    /**
+     * Sets the remaining name (remainingName) to a copy of the specified
+     * <code>Name</code> parameter may be empty, but not null.
+     *
+     * @param n a name, may be empty, but no null
+     */
+    public void setRemainingName(Name n) {
+        if (null == n) {
+            this.remainingName = null;
+        } else {
+            this.remainingName = (Name) n.clone();
+        }
+    }
+    
+    /**
+     * Sets the resolved object (resolved object) to o which may not be null.
+     *  
+     * @param o an object, may not be null
+     */
+    public void setResolvedObj(Object o) {
+        this.resolvedObj = o;
+    }
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/Resolver.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/Resolver.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/Resolver.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/Resolver.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,75 @@
+/* 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 javax.naming.Name;
+import javax.naming.NamingException;
+
+/**
+ * The <code>Resolver</code> interface describes an intermediate context which
+ * may be used in name resolution. In some context implementations, it is 
+ * possible that subtypes of <code>Context</code> may not be supported; in such
+ * cases, a class implementing the <code>Resolver</code> interface becomes 
+ * useful to obtain a context which is of a specified subtype of 
+ * <code>Context</code>.
+ * 
+ */
+public interface Resolver {
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Partially resolves the name specified by name <code>n</code> stopping 
+     * at the first context object which is of the <code>Context</code> subtype 
+     * specified by class <code>c</code>.
+     * 
+     * @param n a name
+     * @param c a context
+     * @return  details of the resolved context object and the part of the name
+     *          remaining to be resolved in a non-null <code>ResolveResult</code>
+     *          object.
+     * @throws javax.naming.NotContextException if no context of the specified subtype is 
+     *          found.
+     * @throws NamingException if other naming errors occur
+     */
+    ResolveResult resolveToClass(Name n, Class c)
+        throws NamingException;
+
+    /**
+     * Partially resolves the name specified by name <code>n</code> stopping 
+     * at the first context object which is of the <code>Context</code> subtype 
+     * specified by class <code>c</code>.
+     * 
+     * @param n a name in string
+     * @param c a context
+     * @return  details of the resolved context object and the part of the name
+     *          remaining to be resolved in a non-null <code>ResolveResult</code>
+     *          object.
+     * @throws javax.naming.NotContextException if no context of the specified subtype is 
+     *          found.
+     * @throws NamingException if other naming errors occur
+     */
+    ResolveResult resolveToClass(String n, Class c)
+        throws NamingException;
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/StateFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/StateFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/StateFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/spi/StateFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,98 @@
+/* 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;
+import javax.naming.NamingException;
+
+/**
+ * The <code>StateFactory</code> interface describes a factory used to get 
+ * the state of an object to be bound. Using a <code>lookup()</code> on a 
+ * suitable context, an class may be found representing, say, a printer; 
+ * an <code>ObjectFactory</code> may be used to create an instance of the 
+ * printer object class and methods defined by the printer class may be used 
+ * to inspect and manipulate the printer. There is a reverse mechanism in 
+ * which a <code>StateFactory</code> is used by the service provider
+ * to obtain the state of the (in this case) printer for storing in the 
+ * naming system. In addition to implementing this interface, a 
+ * <code>StateFactory</code> class must be public and have a public 
+ * constructor taking no parameters.
+ * <p>
+ * Note that while <code>StateFactory</code> is meant to be used in 
+ * <code>Context</code> service providers, whereas <code>DirStateFactory</code>
+ * is meant to be used in <code>DirContext</code> service providers.</p>
+ *
+ */
+public interface StateFactory {
+
+    /*
+     * -------------------------------------------------------------------
+     * Methods
+     * -------------------------------------------------------------------
+     */
+
+    /**
+     * Returns a new instance of the specified object <code>o</code> 
+     * containing the state of the object to be bound, customised by the 
+     * specified <code>envmt</code> parameter. The name and context 
+     * parameters optionally specify the name of the object being created. 
+     * 
+     * Object and state 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. When the service provider looks to obtain the list
+     * of state factories, the environment and provider properties files are 
+     * search for the property name specified by constant
+     * <code>Context.STATE_FACTORIES</code>. Each state factory in the
+     * resulting list is used by <code>NamingManager.getStateToBind()</code> 
+     * which invokes this method on each of them until a non-null result is 
+     * achieved or until the list is exhausted. If a <code>StatetFactory</code>
+     * throws an exception, it should be passed back to the code that 
+     * invoked <code>NamingManager.getStateToBind()</code> and no further 
+     * state factories in the list are examined. An exception should only be 
+     * thrown by a state factory if it is intended that no other state 
+     * factories be examined. Usually, if an state factory is unable to
+     * return the state of an object, then null should be returned.
+     * 
+     * @param o     may be null, or specifies the returning instance
+     * @param n     may be null, or specifies the name relative to the 
+     *              specified context <code>c</code>. The implementation 
+     *              may clone or copy this object, but will not modify the 
+     *              original.
+     * @param c     the context to which the name parameter is relative, or 
+     *              may be null when using a name relative the the default 
+     *              initial context. 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 a new instance of the specified object 
+     *              <code>o</code> containing the state of the object to be 
+     *              bound, customised by the specified 
+     *              <code>envmt</code> parameter. Or null if no object could 
+     *              be created.
+     * @throws NamingException if it is intended that no other state 
+     *              factories be examined.
+     */
+    Object getStateToBind(Object o, Name n, Context c, Hashtable envmt)
+        throws NamingException;
+
+}
+
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/dir2/dir2URLContextFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/dir2/dir2URLContextFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/dir2/dir2URLContextFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/dir2/dir2URLContextFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,127 @@
+/* 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 com.sun.jndi.url.dir2;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.directory.Attributes;
+import javax.naming.spi.DirObjectFactory;
+
+import tests.api.javax.naming.spi.TestNamingManager;
+import tests.api.javax.naming.util.Log;
+
+public class dir2URLContextFactory implements DirObjectFactory {
+
+	Log log = new Log(dir2URLContextFactory.class);
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
+	 *      javax.naming.Name, javax.naming.Context, java.util.Hashtable)
+	 */
+	public Object getObjectInstance(Object o, Name n, Context c, Hashtable h)
+			throws Exception {
+		log.setMethod("getObjectInstance");
+		log.log("wrong method call");
+		return getObjectInstance(o, n, c, h, null);
+
+	}
+
+	public static class MockObject {
+		private Attributes a;
+
+		private Object o;
+
+		private Name n;
+
+		private Context c;
+
+		private Hashtable envmt;
+
+		public MockObject(Object o, Name n, Context c, Hashtable envmt,
+				Attributes a) {
+			this.o = o;
+			this.n = n;
+			this.c = c;
+			this.envmt = envmt;
+			this.a = a;
+		}
+
+		public String toString() {
+			String s = "MockObject {";
+
+			s += "Object= " + o + "\n";
+			s += "Name= " + n + "\n";
+			s += "Context= " + c + "\n";
+			s += "Env= " + envmt;
+			s += "Attr= " + a;
+			s += "}";
+
+			return s;
+		}
+
+		public boolean equals(Object obj) {
+			if (obj instanceof MockObject) {
+				MockObject theOther = (MockObject) obj;
+				if (o != theOther.o) {
+					return false;
+				}
+
+				boolean nameEqual = (null == n ? null == theOther.n : n
+						.equals(theOther.n));
+				if (!nameEqual) {
+					return false;
+				}
+
+				if (c != theOther.c) {
+					return false;
+				}
+
+				boolean envmtEqual = (null == envmt ? null == theOther.envmt
+						: envmt.equals(theOther.envmt));
+				if (!envmtEqual) {
+					return false;
+				}
+
+				boolean attrEqual = (null == a ? null == theOther.a : a
+						.equals(theOther.a));
+
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object,
+	 *      javax.naming.Name, javax.naming.Context, java.util.Hashtable,
+	 *      javax.naming.directory.Attributes)
+	 */
+	public Object getObjectInstance(Object o, Name n, Context c, Hashtable h,
+			Attributes a) throws Exception {
+		TestNamingManager.issueIndicatedExceptions(h);
+		if (TestNamingManager.returnNullIndicated(h)) {
+			return null;
+		}
+
+		return new MockObject(o, n, c, h, a);
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/nntp/nntpURLContextFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/nntp/nntpURLContextFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/nntp/nntpURLContextFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/com/sun/jndi/url/nntp/nntpURLContextFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,103 @@
+/* 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 com.sun.jndi.url.nntp;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.spi.ObjectFactory;
+
+import tests.api.javax.naming.spi.TestNamingManager;
+
+public class nntpURLContextFactory implements ObjectFactory {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
+	 *      javax.naming.Name, javax.naming.Context, java.util.Hashtable)
+	 */
+	public Object getObjectInstance(Object o, Name n, Context c, Hashtable h)
+			throws Exception {
+
+		TestNamingManager.issueIndicatedExceptions(h);
+		if (TestNamingManager.returnNullIndicated(h)) {
+			return null;
+		}
+
+		return new MockObject(o, n, c, h);
+	}
+
+	public static class MockObject {
+		private Object o;
+
+		private Name n;
+
+		private Context c;
+
+		private Hashtable envmt;
+
+		public MockObject(Object o, Name n, Context c, Hashtable envmt) {
+			this.o = o;
+			this.n = n;
+			this.c = c;
+			this.envmt = envmt;
+		}
+
+		public String toString() {
+			String s = "MockObject {";
+
+			s += "Object= " + o + "\n";
+			s += "Name= " + n + "\n";
+			s += "Context= " + c + "\n";
+			s += "Env= " + envmt;
+
+			s += "}";
+
+			return s;
+		}
+
+		public boolean equals(Object obj) {
+			if (obj instanceof MockObject) {
+				MockObject theOther = (MockObject) obj;
+				if (o != theOther.o) {
+					return false;
+				}
+
+				boolean nameEqual = (null == n ? null == theOther.n : n
+						.equals(theOther.n));
+				if (!nameEqual) {
+					return false;
+				}
+
+				if (c != theOther.c) {
+					return false;
+				}
+
+				boolean envmtEqual = (null == envmt ? null == theOther.envmt
+						: envmt.equals(theOther.envmt));
+				if (!envmtEqual) {
+					return false;
+				}
+
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttribute.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttribute.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttribute.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttributes.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttributes.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BasicAttributes.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BinaryRefAddr.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BinaryRefAddr.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/BinaryRefAddr.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompositeName.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompositeName.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompositeName.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName_bad.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName_bad.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/CompoundName_bad.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/InvalidNameException.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/InvalidNameException.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/InvalidNameException.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/LinkRef.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/LinkRef.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/LinkRef.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NamingException.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NamingException.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NamingException.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NoInitialContextException.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NoInitialContextException.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NoInitialContextException.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NotContextException.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NotContextException.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/NotContextException.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/Reference.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/Reference.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/Reference.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/ResolveResult.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/ResolveResult.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/ResolveResult.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/StringRefAddr.ser
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/StringRefAddr.ser?rev=386087&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/data/StringRefAddr.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContext.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContext.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContext.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContext.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,268 @@
+/* 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 dazzle.jndi.testing.spi;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.naming.Binding;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+import javax.naming.OperationNotSupportedException;
+
+public class DazzleContext implements Context {
+
+	class BindingsEnum extends NamesEnum {
+
+		BindingsEnum(Enumeration keysEnum) {
+			super(keysEnum);
+		}
+
+		public Object nextElement() {
+			String key = (String) super.keysEnum.nextElement();
+			return new Binding(key, namespace.get(key));
+		}
+	}
+
+	class NamesEnum implements NamingEnumeration {
+
+		Enumeration keysEnum;
+
+		NamesEnum(Enumeration keysEnum) {
+			this.keysEnum = keysEnum;
+		}
+
+		public void close() throws NamingException {
+		}
+
+		public boolean hasMore() throws NamingException {
+			return hasMoreElements();
+		}
+
+		public boolean hasMoreElements() {
+			return keysEnum.hasMoreElements();
+		}
+
+		public Object next() throws NamingException {
+			return nextElement();
+		}
+
+		public Object nextElement() {
+			String key = (String) keysEnum.nextElement();
+			return new NameClassPair(key, namespace.get(key).getClass()
+					.getName());
+		}
+	}
+
+	private static NameParser nameParser = new DazzleParser();
+
+	Hashtable environment;
+
+	Hashtable namespace;
+
+	DazzleContext(Hashtable environment) {
+		this.environment = new Hashtable();
+		namespace = new Hashtable();
+		this.environment = (Hashtable) environment.clone();
+	}
+
+	public Object addToEnvironment(String propertyName, Object propertyValue)
+			throws NamingException {
+		return environment.put(propertyName, propertyValue);
+	}
+
+	public void bind(Name name, Object target) throws NamingException {
+		bind(name.toString(), target);
+	}
+
+	public void bind(String strName, Object target) throws NamingException {
+		if (strName.length() == 0) {
+			throw new InvalidNameException("Name cannot be empty!");
+		}
+		if (namespace.get(strName) != null) {
+			throw new NameAlreadyBoundException();
+		} else {
+			namespace.put(strName, target);
+			return;
+		}
+	}
+
+	public void close() throws NamingException {
+		environment = namespace = null;
+	}
+
+	public Name composeName(Name name, Name prefix) throws NamingException {
+		Name composite = (Name) prefix.clone();
+		composite.addAll(name);
+		return composite;
+	}
+
+	public String composeName(String strName, String strPrefix)
+			throws NamingException {
+		return composeName(((Name) (new CompositeName(strName))),
+				((Name) (new CompositeName(strPrefix)))).toString();
+	}
+
+	public Context createSubcontext(Name name) throws NamingException {
+		return createSubcontext(name.toString());
+	}
+
+	public Context createSubcontext(String arg0) throws NamingException {
+		throw new OperationNotSupportedException();
+	}
+
+	public void destroySubcontext(Name name) throws NamingException {
+		destroySubcontext(name.toString());
+	}
+
+	public void destroySubcontext(String strName) throws NamingException {
+		throw new OperationNotSupportedException();
+	}
+
+	public Hashtable getEnvironment() throws NamingException {
+		return (Hashtable) environment.clone();
+	}
+
+	public String getNameInNamespace() throws NamingException {
+		return "";
+	}
+
+	public NameParser getNameParser(Name name) throws NamingException {
+		return getNameParser(name.toString());
+	}
+
+	public NameParser getNameParser(String arg0) throws NamingException {
+		return nameParser;
+	}
+
+	public NamingEnumeration list(Name name) throws NamingException {
+		return list(name.toString());
+	}
+
+	public NamingEnumeration list(String strName) throws NamingException {
+		if (strName.length() == 0) {
+			return new NamesEnum(namespace.keys());
+		}
+		Object target = namespace.get(strName);
+		if (target instanceof Context) {
+			return ((Context) target).list("");
+		} else {
+			throw new NotContextException();
+		}
+	}
+
+	public NamingEnumeration listBindings(Name name) throws NamingException {
+		return listBindings(name.toString());
+	}
+
+	public NamingEnumeration listBindings(String strName)
+			throws NamingException {
+		if (strName.length() == 0) {
+			return new BindingsEnum(namespace.keys());
+		}
+		Object target = namespace.get(strName);
+		if (target instanceof Context) {
+			return ((Context) target).listBindings("");
+		} else {
+			throw new NotContextException();
+		}
+	}
+
+	public Object lookup(Name name) throws NamingException {
+		return lookup(name.toString());
+	}
+
+	public Object lookup(String strName) throws NamingException {
+		if (strName.length() == 0) {
+			return new DazzleContext(environment);
+		}
+		Object result = namespace.get(strName);
+		if (result == null) {
+			throw new NameNotFoundException();
+		} else {
+			return result;
+		}
+	}
+
+	public Object lookupLink(Name name) throws NamingException {
+		return lookupLink(name.toString());
+	}
+
+	public Object lookupLink(String strName) throws NamingException {
+		return lookup(strName);
+	}
+
+	public void rebind(Name name, Object target) throws NamingException {
+		rebind(name.toString(), target);
+	}
+
+	public void rebind(String strName, Object target) throws NamingException {
+		if (strName.length() == 0) {
+			throw new InvalidNameException("Name cannot be empty!");
+		} else {
+			namespace.put(strName, target);
+			return;
+		}
+	}
+
+	public Object removeFromEnvironment(String propertyName)
+			throws NamingException {
+		return environment.remove(propertyName);
+	}
+
+	public void rename(Name fromName, Name toName) throws NamingException {
+		rename(fromName.toString(), toName.toString());
+	}
+
+	public void rename(String fromStrName, String toStrName)
+			throws NamingException {
+		if (fromStrName.length() == 0 || toStrName.length() == 0) {
+			throw new InvalidNameException("Name cannot be empty!");
+		}
+		if (namespace.containsKey(toStrName)) {
+			throw new NameAlreadyBoundException();
+		}
+		Object target = namespace.remove(fromStrName);
+		if (target == null) {
+			throw new NameNotFoundException();
+		} else {
+			namespace.put(toStrName, target);
+			return;
+		}
+	}
+
+	public void unbind(Name name) throws NamingException {
+		unbind(name.toString());
+	}
+
+	public void unbind(String strName) throws NamingException {
+		if (strName.length() == 0) {
+			throw new InvalidNameException("Name cannot be empty!");
+		} else {
+			namespace.remove(strName);
+			return;
+		}
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContextFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContextFactory.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContextFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleContextFactory.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,34 @@
+/* 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 dazzle.jndi.testing.spi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+public class DazzleContextFactory implements InitialContextFactory {
+
+	public DazzleContextFactory() {
+		super();
+	}
+
+	public Context getInitialContext(Hashtable environment)
+			throws NamingException {
+		return new DazzleContext(environment);
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleParser.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleParser.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleParser.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/test/java/dazzle/jndi/testing/spi/DazzleParser.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,42 @@
+/* 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 dazzle.jndi.testing.spi;
+
+import java.util.Properties;
+
+import javax.naming.CompoundName;
+import javax.naming.Name;
+import javax.naming.NameParser;
+import javax.naming.NamingException;
+
+class DazzleParser implements NameParser {
+
+	static Properties syntax;
+
+	static {
+		syntax = new Properties();
+		syntax.put("jndi.syntax.direction", "flat");
+		syntax.put("jndi.syntax.ignorecase", "false");
+	}
+
+	DazzleParser() {
+		super();
+	}
+
+	public Name parse(String strName) throws NamingException {
+		return new CompoundName(strName, syntax);
+	}
+}