| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package javax.naming; |
| |
| import java.util.Hashtable; |
| import javax.naming.spi.NamingManager; |
| |
| import org.apache.harmony.jndi.internal.UrlParser; |
| import org.apache.harmony.jndi.internal.EnvironmentReader; |
| import org.apache.harmony.jndi.internal.nls.Messages; |
| |
| /** |
| * An <code>InitialContext</code> object is required as the starting context |
| * for any naming operations. |
| * Other contexts and subcontexts may be created later. Contexts may consist |
| * of different implementations according to the needs of the application. All |
| * naming operations are performed relative to a context and names are resolved |
| * beginning with the initial context. |
| * <p> |
| * When constructing an initial context, environment properties from a range |
| * of sources may be used to initialize the environment. See the specification |
| * of the {@link Context} interface for further details of environment |
| * properties.</p> |
| * <p> |
| * The environment at runtime determines the initial context implementation. |
| * By default, the naming frameworks look for the initial context factory class |
| * name in the property <code>Context.INITIAL_CONTEXT_FACTORY</code>. When URL |
| * strings must be resolved, a different policy is used which is described |
| * below.</p> |
| * <p> |
| * A <code>NoInitialContextException</code> is thrown when it cannot create an |
| * initial context. The exception may occur not only during constructor |
| * invocation, but may occur later. For example, when a subclass of <code> |
| * InitialContext</code> uses the lazy initialization option, <code> |
| * InitialContext</code> methods may be invoked later which require the |
| * initialization to be completed at that time using the <code>init</code> |
| * protected method. In these circumstances, <code>NoInitialContextException |
| * </code> may be thrown some time after the constructor was invoked. JNDI |
| * applications should be written to be independent of when initial context |
| * is actually initialized.</p> |
| * <p> |
| * If environment property <code>Context.INITIAL_CONTEXT_FACTORY</code> has a |
| * non-null value, then the specified initial context factory may experience a |
| * problem trying to instantiate an initial context and so throw an exception. |
| * It is a responsibility of the service provider implementation as to when an |
| * exception is thrown to report the problem to the JNDI application.</p> |
| * <p> |
| * URL names comprising a String format described by RFC1738 may be components |
| * of names passed to naming operations. Typically, the URL is composed of the |
| * "scheme" - such as one of http, ldap, dns - followed by additional text. If |
| * the JNDI can identify the URL scheme from the specified name, then it is |
| * used to construct a classname suffix in the following form:<br> |
| * <pre> |
| * <package_prefix> . <scheme> . <scheme>URLContextFactory |
| * </pre> |
| * Several variants of the classname are constructed using each element of the |
| * <code>Context.URL_PACKAGE_PREFIXES</code> environment property. Note that an |
| * additional package prefix - "com.sun.jndi.url" - is always considered to be |
| * at the end of those already present in the value of that environment |
| * property. Although a service provider may also provide a URL context |
| * implementation as well as a context implementation, it is not required to do |
| * so, and so an arbitrary service provider might not provide for creating URL |
| * contexts.</p> |
| * <p> |
| * If a URL context is successfully created for a specified URL scheme, the |
| * factory can create contexts for arbitrary URLs of the same scheme. |
| * <code>NamingManager.setInitialContextFactoryBuilder</code> may be used to |
| * specify an alternate policy for locating factories for initial contexts and |
| * URL contexts.</p> |
| * <p> |
| * On successful completion of <code>InitialContext</code> initialization, the |
| * service provider implementation will have returned an appropriate <code> |
| * Context</code> object which can be used for looking up and manipulating names |
| * which may or may not be URL names. <code>InitialContext</code> methods other |
| * than those dealing with environments should delegate context operations to |
| * that <code>Context</code> object.</p> |
| * |
| * @see Context |
| * |
| */ |
| public class InitialContext implements Context { |
| |
| /** |
| * Set to the result of the first successful invocation of <code> |
| * NamingManager.getInitialContext</code> by <code>getDefaultInitCtx |
| * </code>. |
| * Initially null. |
| */ |
| protected Context defaultInitCtx; |
| |
| /** |
| * Set to true when <code>NamingManager.getInitialContext</code> has |
| * been invoked to obtain an initial context. |
| * Initially false. |
| */ |
| protected boolean gotDefault; |
| |
| /** |
| * Contains all those JNDI environment properties that were found in any |
| * of the the sources of JNDI environment properties. |
| * Initially null. |
| */ |
| protected Hashtable<Object, Object> myProps; |
| |
| /* |
| * ------------------------------------------------------------------- |
| * Constructors |
| * ------------------------------------------------------------------- |
| */ |
| |
| /** |
| * Constructs an <code>InitialContext</code> instance without using any |
| * environment properties. |
| * This constructor is effectively the same as using constructor |
| * <code>InitialContext((Hashtable)null)</code>. |
| * |
| * @throws NamingException If failed to create an <code>InitialContext</code>. |
| */ |
| public InitialContext() throws NamingException { |
| this(null); |
| } |
| |
| /** |
| * Constructs an <code>InitialContext</code> instance using environment |
| * properties in the supplied parameter which may be null. |
| * |
| * @param environment the JNDI environment properties used to create |
| * the context |
| * @throws NamingException If failed to create an <code>InitialContext</code>. |
| */ |
| public InitialContext(Hashtable<?, ?> environment) throws NamingException { |
| internalInit(environment); |
| } |
| |
| /** |
| * Constructs an <code>InitialContext</code> instance by indicating whether |
| * a lazy initialization is desired. |
| * Effectively, this is the same as using constructor <code>InitialContext() |
| * </code> if lazy initialization is not indicated. |
| * <p> |
| * This constructor may be invoked with a parameter value of true and the |
| * implementation will defer initialization of the instance. This may be |
| * used in an <code>InitialContext</code> subclass constructor in which |
| * later action will set up a <code>Hashtable</code> object with appropriate |
| * environment properties and pass that to the <code>init</code> method to |
| * complete initialization of the <code>InitialContext</code> object.</p> |
| * |
| * @param doNotInit Specifies whether to initialize the new instance. |
| * @throws NamingException If failed to create an <code>InitialContext</code>. |
| */ |
| protected InitialContext(boolean doNotInit) throws NamingException { |
| if (!doNotInit) { |
| internalInit(null); |
| } |
| } |
| |
| /** |
| * Does private initialization. |
| * |
| * @param env the JNDI environment properties used to create |
| * the context |
| * @throws NamingException If failed to create an InitialContext. |
| */ |
| @SuppressWarnings("unchecked") //$NON-NLS-1$ |
| private void internalInit(Hashtable<?, ?> env) throws NamingException { |
| |
| // 1. Read the environment parameter used to create this Context |
| if (null == env) { |
| myProps = new Hashtable<Object, Object>(); |
| } else { |
| myProps = (Hashtable<Object, Object>) env.clone(); |
| } |
| |
| // 2. Read Applet parameters |
| EnvironmentReader.readAppletParameters( |
| myProps.get(Context.APPLET), |
| myProps); |
| |
| // 3. Read System properties |
| EnvironmentReader.readSystemProperties(myProps); |
| |
| // 4.1 Read application/applet resource files |
| EnvironmentReader.readApplicationResourceFiles(myProps); |
| |
| // 4.2 Read "java.home"/lib/jndi.properties |
| EnvironmentReader.readLibraryResourceFile(myProps); |
| |
| // 5. No need to read service provider resource files |
| |
| // if JNDI standard property "java.naming.factory.initial" has a non-null value |
| if (myProps.containsKey(INITIAL_CONTEXT_FACTORY)) { |
| // call getDefaultInitCtx() to initialize gotDefault and defaultInitCtx |
| getDefaultInitCtx(); |
| } |
| } |
| |
| /** |
| * Uses the specified environment parameter together with other JNDI |
| * properties to initialize this <code>InitialContext</code> object. |
| * The <code>myProps</code> field will be filled with found JNDI properties. |
| * If JNDI standard property "java.naming.factory.initial" has a non-null |
| * value, then <code>getDefaultInitCtx</code> is invoked to try to |
| * initialize fields <code>gotDefault</code> and <code>defaultInitCtx</code> |
| * of the <code>InitialContext</code> object. |
| * |
| * @param env the JNDI environment properties supplied to |
| * create the context |
| * @throws NamingException If naming problems are encountered during |
| * initialization of these fields. |
| */ |
| protected void init(Hashtable<?, ?> env) throws NamingException { |
| this.internalInit(env); |
| } |
| |
| /* |
| * Initializes the default initial context. |
| * |
| * @throws NamingException If failed to initialize this InitialContext. |
| */ |
| private void initializeDefaultInitCtx() throws NamingException { |
| if (!this.gotDefault) { |
| this.defaultInitCtx = NamingManager.getInitialContext(myProps); |
| if (null == this.defaultInitCtx) { |
| throw new NoInitialContextException("Failed to create an initial context."); //$NON-NLS-1$ |
| } |
| this.gotDefault = true; |
| } |
| } |
| |
| /** |
| * Gets the default underlying <code>Context</code> implementation. |
| * If <code>gotDefault</code> is true, returns the value of <code> |
| * defaultInitCtx</code>. Otherwise, calls <code>NamingManager.getInitialContext |
| * </code> to return an initial context for the current environment into |
| * <code>defaultInitCtx</code>, then <code>gotDefault</code> is set true. |
| * If the resulting context object is null, a <code>NoInitialContextException |
| * </code> is thrown, otherwise the value of <code>defaultInitCtx</code> is |
| * returned. |
| * |
| * @return the default context |
| * @throws NoInitialContextException |
| * If <code>NamingManager.getInitialContext</code> |
| * returns null. |
| * @throws NamingException If failed to create the default context. |
| */ |
| protected Context getDefaultInitCtx() throws NamingException { |
| initializeDefaultInitCtx(); |
| return this.defaultInitCtx; |
| } |
| |
| /** |
| * Returns a non-null context for the specified name of Name representation. |
| * <p> |
| * If an initial context factory builder has been defined, then the |
| * specified <code>Name</code> parameter is ignored and the result of <code> |
| * getDefaultInitCtx</code> is returned. Otherwise, if the first component |
| * of the name is not a URL string, then it returns the result of invoking |
| * <code>getDefaultInitCtx</code>. Otherwise, it attempts to return a URL |
| * context {@link javax.naming.spi.NamingManager#getURLContext(String, Hashtable)}, |
| * but if unsuccessful, returns the result of invoking |
| * <code>getDefaultInitCtx</code>.</p> |
| * |
| * @param name a name used in a naming operation which may not |
| * be null |
| * @return a context which may be a URL context |
| * @throws NamingException If failed to get the desired context. |
| */ |
| protected Context getURLOrDefaultInitCtx(Name name) |
| throws NamingException { |
| // If the name has components |
| if (0 < name.size()) { |
| return getURLOrDefaultInitCtx(name.get(0)); |
| } |
| return getDefaultInitCtx(); |
| } |
| |
| /** |
| * Returns a non-null context for the specified name of string |
| * representation. |
| * <p> |
| * If an initial context factory builder has been defined, then the |
| * specified name parameter is ignored and the result of <code> |
| * getDefaultInitCtx</code> is returned. Otherwise, if the name is not a URL |
| * string, then it returns the result of invoking <code>getDefaultInitCtx |
| * </code>. Otherwise, it attempts to return a URL context |
| * {@link javax.naming.spi.NamingManager#getURLContext(String, Hashtable)}, |
| * but if unsuccessful, returns the result of invoking <code> |
| * getDefaultInitCtx</code>.</p> |
| * |
| * @param name a name used in a naming operation which may not |
| * be null |
| * @return a context which may be a URL context |
| * @throws NamingException If failed to get the desired context. |
| */ |
| protected Context getURLOrDefaultInitCtx(String name) |
| throws NamingException { |
| |
| /* |
| * If an initial context factory builder has been defined, then the |
| * specified name parameter is ignored and the result of |
| * getDefaultInitCtx() is returned. |
| */ |
| if (NamingManager.hasInitialContextFactoryBuilder()) { |
| return getDefaultInitCtx(); |
| } |
| |
| if (null == name) { |
| // jndi.00=name must not be null |
| throw new NullPointerException(Messages.getString("jndi.00")); //$NON-NLS-1$ |
| } |
| |
| // If the name has components |
| String scheme = UrlParser.getScheme(name); |
| Context ctx = null; |
| if (null != scheme) { |
| // So the first component is a valid URL |
| ctx = NamingManager.getURLContext(scheme, myProps); |
| } |
| return null == ctx ? getDefaultInitCtx() : ctx; |
| } |
| |
| public Object lookup(Name name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).lookup(name); |
| } |
| |
| public Object lookup(String name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).lookup(name); |
| } |
| |
| public void bind(Name name, Object obj) throws NamingException { |
| getURLOrDefaultInitCtx(name).bind(name, obj); |
| } |
| |
| public void bind(String name, Object obj) throws NamingException { |
| getURLOrDefaultInitCtx(name).bind(name, obj); |
| } |
| |
| public void rebind(Name name, Object obj) throws NamingException { |
| getURLOrDefaultInitCtx(name).rebind(name, obj); |
| } |
| |
| public void rebind(String name, Object obj) throws NamingException { |
| getURLOrDefaultInitCtx(name).rebind(name, obj); |
| } |
| |
| public void unbind(Name name) throws NamingException { |
| getURLOrDefaultInitCtx(name).unbind(name); |
| } |
| |
| public void unbind(String name) throws NamingException { |
| getURLOrDefaultInitCtx(name).unbind(name); |
| } |
| |
| public void rename(Name oldName, Name newName) throws NamingException { |
| getURLOrDefaultInitCtx(oldName).rename(oldName, newName); |
| } |
| |
| public void rename(String oldName, String newName) throws NamingException { |
| getURLOrDefaultInitCtx(oldName).rename(oldName, newName); |
| } |
| |
| public NamingEnumeration<NameClassPair> list(Name name) |
| throws NamingException { |
| return getURLOrDefaultInitCtx(name).list(name); |
| } |
| |
| public NamingEnumeration<NameClassPair> list(String name) |
| throws NamingException { |
| return getURLOrDefaultInitCtx(name).list(name); |
| } |
| |
| public NamingEnumeration<Binding> listBindings(Name name) |
| throws NamingException { |
| return getURLOrDefaultInitCtx(name).listBindings(name); |
| } |
| |
| public NamingEnumeration<Binding> listBindings(String name) |
| throws NamingException { |
| return getURLOrDefaultInitCtx(name).listBindings(name); |
| } |
| |
| public void destroySubcontext(Name name) throws NamingException { |
| getURLOrDefaultInitCtx(name).destroySubcontext(name); |
| } |
| |
| public void destroySubcontext(String name) throws NamingException { |
| getURLOrDefaultInitCtx(name).destroySubcontext(name); |
| } |
| |
| public Context createSubcontext(Name name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).createSubcontext(name); |
| } |
| |
| public Context createSubcontext(String name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).createSubcontext(name); |
| } |
| |
| public Object lookupLink(Name name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).lookupLink(name); |
| } |
| |
| public Object lookupLink(String name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).lookupLink(name); |
| } |
| |
| public NameParser getNameParser(Name name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).getNameParser(name); |
| } |
| |
| public NameParser getNameParser(String name) throws NamingException { |
| return getURLOrDefaultInitCtx(name).getNameParser(name); |
| } |
| |
| /** |
| * Composes the name of this context with a name relative to this context. |
| * Because an initial context could not be named relative to any context |
| * except itself, the value of the prefix parameter must be an empty name. |
| * |
| * @param name |
| * a name relative to this context. |
| * @param prefix |
| * the name of this context relative to one of its ancestors. |
| * |
| * @return the composition of prefix and name. |
| * @throws NamingException |
| * if a naming exception happens. |
| */ |
| public Name composeName(Name name, Name prefix) throws NamingException { |
| if (null == name) { |
| throw new NullPointerException(); |
| } |
| return (Name) name.clone(); |
| } |
| |
| /** |
| * Composes the name of this context with a name relative to this context. |
| * Because an initial context could not be named relative to any context |
| * except itself, the value of the prefix parameter must be an empty name. |
| * |
| * @param name |
| * a name relative to this context. |
| * @param prefix |
| * the name of this context relative to one of its ancestors. |
| * |
| * @return the composition of prefix and name. |
| * @throws NamingException |
| * if a naming exception happens. |
| */ |
| public String composeName(String name, String prefix) |
| throws NamingException { |
| return name; |
| } |
| |
| public Object addToEnvironment(String propName, Object propVal) |
| throws NamingException { |
| this.myProps.put(propName, propVal); |
| return getDefaultInitCtx().addToEnvironment(propName, propVal); |
| } |
| |
| public Object removeFromEnvironment(String propName) |
| throws NamingException { |
| this.myProps.remove(propName); |
| return getDefaultInitCtx().removeFromEnvironment(propName); |
| } |
| |
| public Hashtable<?, ?> getEnvironment() throws NamingException { |
| return getDefaultInitCtx().getEnvironment(); |
| } |
| |
| public void close() throws NamingException { |
| if (this.gotDefault) { |
| getDefaultInitCtx().close(); |
| } |
| } |
| |
| public String getNameInNamespace() throws NamingException { |
| return getDefaultInitCtx().getNameInNamespace(); |
| } |
| } |