/*
 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.naming;

import java.util.Hashtable;
import javax.naming.spi.NamingManager;
import com.sun.naming.internal.ResourceManager;

/**
 * This class is the starting context for performing naming operations.
 *<p>
 * All naming operations are relative to a context.
 * The initial context implements the Context interface and
 * provides the starting point for resolution of names.
 *<p>
 * <a name=ENVIRONMENT></a>
 * When the initial context is constructed, its environment
 * is initialized with properties defined in the environment parameter
 * passed to the constructor, and in any
 * <a href=Context.html#RESOURCEFILES>application resource files</a>.
 *<p>
 * JNDI determines each property's value by merging
 * the values from the following two sources, in order:
 * <ol>
 * <li>
 * The first occurrence of the property from the constructor's
 * environment parameter and system properties.
 * <li>
 * The application resource files ({@code jndi.properties}).
 * </ol>
 * For each property found in both of these two sources, or in
 * more than one application resource file, the property's value
 * is determined as follows.  If the property is
 * one of the standard JNDI properties that specify a list of JNDI
 * factories (see <a href=Context.html#LISTPROPS>{@code Context}</a>),
 * all of the values are
 * concatenated into a single colon-separated list.  For other
 * properties, only the first value found is used.
 *
 *<p>
 * The initial context implementation is determined at runtime.
 * The default policy uses the environment property
 * "{@link Context#INITIAL_CONTEXT_FACTORY java.naming.factory.initial}",
 * which contains the class name of the initial context factory.
 * An exception to this policy is made when resolving URL strings, as described
 * below.
 *<p>
 * When a URL string (a {@code String} of the form
 * <em>scheme_id:rest_of_name</em>) is passed as a name parameter to
 * any method, a URL context factory for handling that scheme is
 * located and used to resolve the URL.  If no such factory is found,
 * the initial context specified by
 * {@code "java.naming.factory.initial"} is used.  Similarly, when a
 * {@code CompositeName} object whose first component is a URL string is
 * passed as a name parameter to any method, a URL context factory is
 * located and used to resolve the first name component.
 * See {@link NamingManager#getURLContext
 * NamingManager.getURLContext()} for a description of how URL
 * context factories are located.
 *<p>
 * This default policy of locating the initial context and URL context
 * factories may be overridden
 * by calling
 * {@code NamingManager.setInitialContextFactoryBuilder()}.
 *<p>
 * NoInitialContextException is thrown when an initial context cannot
 * be instantiated. This exception can be thrown during any interaction
 * with the InitialContext, not only when the InitialContext is constructed.
 * For example, the implementation of the initial context might lazily
 * retrieve the context only when actual methods are invoked on it.
 * The application should not have any dependency on when the existence
 * of an initial context is determined.
 *<p>
 * When the environment property "java.naming.factory.initial" is
 * non-null, the InitialContext constructor will attempt to create the
 * initial context specified therein. At that time, the initial context factory
 * involved might throw an exception if a problem is encountered. However,
 * it is provider implementation-dependent when it verifies and indicates
 * to the users of the initial context any environment property- or
 * connection- related problems. It can do so lazily--delaying until
 * an operation is performed on the context, or eagerly, at the time
 * the context is constructed.
 *<p>
 * An InitialContext instance is not synchronized against concurrent
 * access by multiple threads. Multiple threads each manipulating a
 * different InitialContext instance need not synchronize.
 * Threads that need to access a single InitialContext instance
 * concurrently should synchronize amongst themselves and provide the
 * necessary locking.
 *
 * @author Rosanna Lee
 * @author Scott Seligman
 *
 * @see Context
 * @see NamingManager#setInitialContextFactoryBuilder
 *      NamingManager.setInitialContextFactoryBuilder
 * @since 1.3, JNDI 1.1
 */

public class InitialContext implements Context {

    /**
     * The environment associated with this InitialContext.
     * It is initialized to null and is updated by the constructor
     * that accepts an environment or by the {@code init()} method.
     * @see #addToEnvironment
     * @see #removeFromEnvironment
     * @see #getEnvironment
     */
    protected Hashtable<Object,Object> myProps = null;

    /**
     * Field holding the result of calling NamingManager.getInitialContext().
     * It is set by getDefaultInitCtx() the first time getDefaultInitCtx()
     * is called. Subsequent invocations of getDefaultInitCtx() return
     * the value of defaultInitCtx.
     * @see #getDefaultInitCtx
     */
    protected Context defaultInitCtx = null;

    /**
     * Field indicating whether the initial context has been obtained
     * by calling NamingManager.getInitialContext().
     * If true, its result is in <code>defaultInitCtx</code>.
     */
    protected boolean gotDefault = false;

    /**
     * Constructs an initial context with the option of not
     * initializing it.  This may be used by a constructor in
     * a subclass when the value of the environment parameter
     * is not yet known at the time the {@code InitialContext}
     * constructor is called.  The subclass's constructor will
     * call this constructor, compute the value of the environment,
     * and then call {@code init()} before returning.
     *
     * @param lazy
     *          true means do not initialize the initial context; false
     *          is equivalent to calling {@code new InitialContext()}
     * @throws  NamingException if a naming exception is encountered
     *
     * @see #init(Hashtable)
     * @since 1.3
     */
    protected InitialContext(boolean lazy) throws NamingException {
        if (!lazy) {
            init(null);
        }
    }

    /**
     * Constructs an initial context.
     * No environment properties are supplied.
     * Equivalent to {@code new InitialContext(null)}.
     *
     * @throws  NamingException if a naming exception is encountered
     *
     * @see #InitialContext(Hashtable)
     */
    public InitialContext() throws NamingException {
        init(null);
    }

    /**
     * Constructs an initial context using the supplied environment.
     * Environment properties are discussed in the class description.
     *
     * <p> This constructor will not modify {@code environment}
     * or save a reference to it, but may save a clone.
     * Caller should not modify mutable keys and values in
     * {@code environment} after it has been passed to the constructor.
     *
     * @param environment
     *          environment used to create the initial context.
     *          Null indicates an empty environment.
     *
     * @throws  NamingException if a naming exception is encountered
     */
    public InitialContext(Hashtable<?,?> environment)
        throws NamingException
    {
        if (environment != null) {
            environment = (Hashtable)environment.clone();
        }
        init(environment);
    }

    /**
     * Initializes the initial context using the supplied environment.
     * Environment properties are discussed in the class description.
     *
     * <p> This method will modify {@code environment} and save
     * a reference to it.  The caller may no longer modify it.
     *
     * @param environment
     *          environment used to create the initial context.
     *          Null indicates an empty environment.
     *
     * @throws  NamingException if a naming exception is encountered
     *
     * @see #InitialContext(boolean)
     * @since 1.3
     */
    @SuppressWarnings("unchecked")
    protected void init(Hashtable<?,?> environment)
        throws NamingException
    {
        myProps = (Hashtable<Object,Object>)
                ResourceManager.getInitialEnvironment(environment);

        if (myProps.get(Context.INITIAL_CONTEXT_FACTORY) != null) {
            // user has specified initial context factory; try to get it
            getDefaultInitCtx();
        }
    }

    /**
     * A static method to retrieve the named object.
     * This is a shortcut method equivalent to invoking:
     * <p>
     * <code>
     *        InitialContext ic = new InitialContext();
     *        Object obj = ic.lookup();
     * </code>
     * <p> If {@code name} is empty, returns a new instance of this context
     * (which represents the same naming context as this context, but its
     * environment may be modified independently and it may be accessed
     * concurrently).
     *
     * @param <T> the type of the returned object
     * @param name
     *          the name of the object to look up
     * @return  the object bound to {@code name}
     * @throws  NamingException if a naming exception is encountered
     *
     * @see #doLookup(String)
     * @see #lookup(Name)
     * @since 1.6
     */
    @SuppressWarnings("unchecked")
    public static <T> T doLookup(Name name)
        throws NamingException {
        return (T) (new InitialContext()).lookup(name);
    }

   /**
     * A static method to retrieve the named object.
     * See {@link #doLookup(Name)} for details.
     * @param <T> the type of the returned object
     * @param name
     *          the name of the object to look up
     * @return  the object bound to {@code name}
     * @throws  NamingException if a naming exception is encountered
     * @since 1.6
     */
    @SuppressWarnings("unchecked")
    public static <T> T doLookup(String name)
        throws NamingException {
        return (T) (new InitialContext()).lookup(name);
    }

    private static String getURLScheme(String str) {
        int colon_posn = str.indexOf(':');
        int slash_posn = str.indexOf('/');

        if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
            return str.substring(0, colon_posn);
        return null;
    }

    /**
     * Retrieves the initial context by calling
     * <code>NamingManager.getInitialContext()</code>
     * and cache it in defaultInitCtx.
     * Set <code>gotDefault</code> so that we know we've tried this before.
     * @return The non-null cached initial context.
     * @exception NoInitialContextException If cannot find an initial context.
     * @exception NamingException If a naming exception was encountered.
     */
    protected Context getDefaultInitCtx() throws NamingException{
        if (!gotDefault) {
            defaultInitCtx = NamingManager.getInitialContext(myProps);
            gotDefault = true;
        }
        if (defaultInitCtx == null)
            throw new NoInitialContextException();

        return defaultInitCtx;
    }

    /**
     * Retrieves a context for resolving the string name <code>name</code>.
     * If <code>name</code> name is a URL string, then attempt
     * to find a URL context for it. If none is found, or if
     * <code>name</code> is not a URL string, then return
     * <code>getDefaultInitCtx()</code>.
     *<p>
     * See getURLOrDefaultInitCtx(Name) for description
     * of how a subclass should use this method.
     * @param name The non-null name for which to get the context.
     * @return A URL context for <code>name</code> or the cached
     *         initial context. The result cannot be null.
     * @exception NoInitialContextException If cannot find an initial context.
     * @exception NamingException In a naming exception is encountered.
     * @see javax.naming.spi.NamingManager#getURLContext
     */
    protected Context getURLOrDefaultInitCtx(String name)
        throws NamingException {
        if (NamingManager.hasInitialContextFactoryBuilder()) {
            return getDefaultInitCtx();
        }
        String scheme = getURLScheme(name);
        if (scheme != null) {
            Context ctx = NamingManager.getURLContext(scheme, myProps);
            if (ctx != null) {
                return ctx;
            }
        }
        return getDefaultInitCtx();
    }

    /**
     * Retrieves a context for resolving <code>name</code>.
     * If the first component of <code>name</code> name is a URL string,
     * then attempt to find a URL context for it. If none is found, or if
     * the first component of <code>name</code> is not a URL string,
     * then return <code>getDefaultInitCtx()</code>.
     *<p>
     * When creating a subclass of InitialContext, use this method as
     * follows.
     * Define a new method that uses this method to get an initial
     * context of the desired subclass.
     * <blockquote><pre>
     * protected XXXContext getURLOrDefaultInitXXXCtx(Name name)
     * throws NamingException {
     *  Context answer = getURLOrDefaultInitCtx(name);
     *  if (!(answer instanceof XXXContext)) {
     *    if (answer == null) {
     *      throw new NoInitialContextException();
     *    } else {
     *      throw new NotContextException("Not an XXXContext");
     *    }
     *  }
     *  return (XXXContext)answer;
     * }
     * </pre></blockquote>
     * When providing implementations for the new methods in the subclass,
     * use this newly defined method to get the initial context.
     * <blockquote><pre>
     * public Object XXXMethod1(Name name, ...) {
     *  throws NamingException {
     *    return getURLOrDefaultInitXXXCtx(name).XXXMethod1(name, ...);
     * }
     * </pre></blockquote>
     *
     * @param name The non-null name for which to get the context.
     * @return A URL context for <code>name</code> or the cached
     *         initial context. The result cannot be null.
     * @exception NoInitialContextException If cannot find an initial context.
     * @exception NamingException In a naming exception is encountered.
     *
     * @see javax.naming.spi.NamingManager#getURLContext
     */
    protected Context getURLOrDefaultInitCtx(Name name)
        throws NamingException {
        if (NamingManager.hasInitialContextFactoryBuilder()) {
            return getDefaultInitCtx();
        }
        if (name.size() > 0) {
            String first = name.get(0);
            String scheme = getURLScheme(first);
            if (scheme != null) {
                Context ctx = NamingManager.getURLContext(scheme, myProps);
                if (ctx != null) {
                    return ctx;
                }
            }
        }
        return getDefaultInitCtx();
    }

// Context methods
// Most Javadoc is deferred to the Context interface.

    public Object lookup(String name) throws NamingException {
        return getURLOrDefaultInitCtx(name).lookup(name);
    }

    public Object lookup(Name name) throws NamingException {
        return getURLOrDefaultInitCtx(name).lookup(name);
    }

    public void bind(String name, Object obj) throws NamingException {
        getURLOrDefaultInitCtx(name).bind(name, obj);
    }

    public void bind(Name name, Object obj) throws NamingException {
        getURLOrDefaultInitCtx(name).bind(name, obj);
    }

    public void rebind(String name, Object obj) throws NamingException {
        getURLOrDefaultInitCtx(name).rebind(name, obj);
    }

    public void rebind(Name name, Object obj) throws NamingException {
        getURLOrDefaultInitCtx(name).rebind(name, obj);
    }

    public void unbind(String name) throws NamingException  {
        getURLOrDefaultInitCtx(name).unbind(name);
    }

    public void unbind(Name name) throws NamingException  {
        getURLOrDefaultInitCtx(name).unbind(name);
    }

    public void rename(String oldName, String newName) throws NamingException {
        getURLOrDefaultInitCtx(oldName).rename(oldName, newName);
    }

    public void rename(Name oldName, Name newName)
        throws NamingException
    {
        getURLOrDefaultInitCtx(oldName).rename(oldName, newName);
    }

    public NamingEnumeration<NameClassPair> list(String name)
        throws NamingException
    {
        return (getURLOrDefaultInitCtx(name).list(name));
    }

    public NamingEnumeration<NameClassPair> list(Name name)
        throws NamingException
    {
        return (getURLOrDefaultInitCtx(name).list(name));
    }

    public NamingEnumeration<Binding> listBindings(String name)
            throws NamingException  {
        return getURLOrDefaultInitCtx(name).listBindings(name);
    }

    public NamingEnumeration<Binding> listBindings(Name name)
            throws NamingException  {
        return getURLOrDefaultInitCtx(name).listBindings(name);
    }

    public void destroySubcontext(String name) throws NamingException  {
        getURLOrDefaultInitCtx(name).destroySubcontext(name);
    }

    public void destroySubcontext(Name name) throws NamingException  {
        getURLOrDefaultInitCtx(name).destroySubcontext(name);
    }

    public Context createSubcontext(String name) throws NamingException  {
        return getURLOrDefaultInitCtx(name).createSubcontext(name);
    }

    public Context createSubcontext(Name name) throws NamingException  {
        return getURLOrDefaultInitCtx(name).createSubcontext(name);
    }

    public Object lookupLink(String name) throws NamingException  {
        return getURLOrDefaultInitCtx(name).lookupLink(name);
    }

    public Object lookupLink(Name name) throws NamingException {
        return getURLOrDefaultInitCtx(name).lookupLink(name);
    }

    public NameParser getNameParser(String name) throws NamingException {
        return getURLOrDefaultInitCtx(name).getNameParser(name);
    }

    public NameParser getNameParser(Name name) throws NamingException {
        return getURLOrDefaultInitCtx(name).getNameParser(name);
    }

    /**
     * Composes the name of this context with a name relative to
     * this context.
     * Since an initial context may never be named relative
     * to any context other than itself, the value of the
     * {@code prefix} parameter must be an empty name ({@code ""}).
     */
    public String composeName(String name, String prefix)
            throws NamingException {
        return name;
    }

    /**
     * Composes the name of this context with a name relative to
     * this context.
     * Since an initial context may never be named relative
     * to any context other than itself, the value of the
     * {@code prefix} parameter must be an empty name.
     */
    public Name composeName(Name name, Name prefix)
        throws NamingException
    {
        return (Name)name.clone();
    }

    public Object addToEnvironment(String propName, Object propVal)
            throws NamingException {
        myProps.put(propName, propVal);
        return getDefaultInitCtx().addToEnvironment(propName, propVal);
    }

    public Object removeFromEnvironment(String propName)
            throws NamingException {
        myProps.remove(propName);
        return getDefaultInitCtx().removeFromEnvironment(propName);
    }

    public Hashtable<?,?> getEnvironment() throws NamingException {
        return getDefaultInitCtx().getEnvironment();
    }

    public void close() throws NamingException {
        myProps = null;
        if (defaultInitCtx != null) {
            defaultInitCtx.close();
            defaultInitCtx = null;
        }
        gotDefault = false;
    }

    public String getNameInNamespace() throws NamingException {
        return getDefaultInitCtx().getNameInNamespace();
    }
};
