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