/* InitialContext.java -- Initial naming context.
   Copyright (C) 2000, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.naming;

import java.applet.Applet;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Properties;

import javax.naming.spi.NamingManager;

/**
 * The starting context for performing naming operations. All naming operations
 * are performed in the scope of some context. The initial context is the
 * starting point for the name resolution.
 */
public class InitialContext implements Context
{
  /**
   * Contains the default initial context. This value is returned by
   * {@link NamingManager#getInitialContext}. It is set by this method
   * when calling it first time. The subsequent calls return the value of
   * this field.
   */
  protected Context defaultInitCtx;

  /**
   * Indicates if the initial context was obtained by calling
   * {@link NamingManager#getInitialContext}.
   */
  protected boolean gotDefault = false;

  /**
   * The environment, associated with this initial context.
   */
  protected Hashtable<Object,Object> myProps;

  /**
   * The list of the properties, to that the second alternative value must
   * be appended after the colon to the first possible value. Used in
   * {@link #merge(Hashtable, Hashtable)}
   */
  static final HashSet<String> colon_list;
  static
    {
      colon_list = new HashSet<String>();
      colon_list.add(Context.OBJECT_FACTORIES);
      colon_list.add(Context.URL_PKG_PREFIXES);
      colon_list.add(Context.STATE_FACTORIES);
    }

   /**
    * The properties that are searched in the agreed places in the
    * {@link #init(Hashtable)} method.
    */
    static final String[] use_properties =
      {
        Context.DNS_URL,
        Context.INITIAL_CONTEXT_FACTORY,
        Context.OBJECT_FACTORIES,
        Context.PROVIDER_URL,
        Context.STATE_FACTORIES,
        Context.URL_PKG_PREFIXES,
      };


  /**
   * Creates the new initial context with the given properties.
   *
   * @param environment the properties, used by the initial context being
   *          created.
   * @throws NamingException
   */
  public InitialContext(Hashtable<?,?> environment) throws NamingException
  {
    init(environment);
  }

  /**
   * Creates the initial context with the possibility to delay its
   * initialisation.
   *
   * @param lazy specified if the initialization should not be performed by this
   *          constructor (true). If the valueis false, it works the same way as
   *          the parameterless constructor.
   * @throws NamingException
   */
  protected InitialContext(boolean lazy) throws NamingException
  {
    if (! lazy)
      init(null);
  }

  /**
   * Creates teh new initial context with no properties. Same as
   * InitialContext(null).
   *
   * @throws NamingException
   */
  public InitialContext() throws NamingException
  {
    init(null);
  }

  /**
   * <p>
   * Initialises the context, using the properties, specified in the passed
   * table.
   * </p>
   * The missing properties are additionally obtained (in order) from the
   * following locations:
   * <ul>
   * <li>If the passed parameter contains the key Context.APPLET, its value
   * must be the instance of the {@link Applet}. Then the properties are
   * requested via {@link Applet#getParameter(String)}.</li>
   * <li>The value of the system property is used.</li>
   * <li>The resource "jndi.properties" is requested from the context class
   * loader of the current thread</li>
   * <li>The property file "jndi.properties" is read from the location,
   * specified by the system property "gnu.classpath.home.url".
   * </ul>
   * </p>
   *
   * @param environment the table of the properties, may be null. The method
   *          modifies the table and stores the reference to it. The caller must
   *          not later reuse this structure for other purposes.
   * @since 1.3
   */
  protected void init(Hashtable<?, ?> environment) throws NamingException
  {
    // If is documented that the caller should not modify the environment.
    if (environment != null)
      myProps = (Hashtable<Object, Object>) environment;
    else
      myProps = new Hashtable<Object, Object>();

    Applet napplet = (Applet) myProps.get(Context.APPLET);

    Properties pApplet = null;
    if (napplet != null)
      pApplet = new Properties();
    Properties pSystem = new Properties();
    Object value;

    for (int i = use_properties.length - 1; i >= 0; i--)
      {
        String key = use_properties[i];
        if (napplet != null)
          {
            value = napplet.getParameter(key);
            if (value != null)
              pApplet.put(key, value);
          }

        value = System.getProperty(key);
        if (value != null)
          pSystem.put(key, value);
      }

    merge(myProps, pSystem);
    if (pApplet != null)
      merge(myProps, pApplet);

    try
      {
        Enumeration ep = Thread.currentThread().
          getContextClassLoader().getResources("jndi.properties");
        while (ep.hasMoreElements())
          {
            URL url = (URL) ep.nextElement();
            Properties p = new Properties();

            try
              {
                InputStream is = url.openStream();
                p.load(is);
                is.close();
              }
            catch (IOException e)
              {
                // Ignore.
              }

            merge(myProps, p);
          }
      }
    catch (IOException e)
      {
        // Ignore.
      }

    String home = System.getProperty("gnu.classpath.home.url");
    if (home != null)
      {
        String url = home + "/jndi.properties";
        Properties p = new Properties();

        try
          {
            InputStream is = new URL(url).openStream();
            p.load(is);
            is.close();
          }
        catch (IOException e)
          {
            // Ignore.
          }

        merge(myProps, p);
      }
  }

  /**
   * Merge the content of the two tables. If the second table contains the key
   * that is missing in the first table, this key - value pair is copied to the
   * first table. If both first and second tables contain the same key AND the
   * {@link #colon_list} set also contains this key, the value from the second
   * table is appended to the value from the first table after semicolon, and
   * the resulted value replaces the value in the first table.
   *
   * @param primary the first table to merge. The merged result is also stored
   *          in this table.
   * @param additional the second table, from where additional values are taken
   */
  static void merge (Hashtable<Object, Object> primary,
                     Hashtable<Object, Object> additional)
  {
    Enumeration en = additional.keys();

    while (en.hasMoreElements())
      {
        String key2 = (String) en.nextElement();
        Object value1 = primary.get(key2);
        if (value1 == null)
          primary.put(key2, additional.get(key2));
        else if (colon_list.contains(key2))
          {
            String value2 = (String) additional.get(key2);
            primary.put(key2, (String) value1 + ":" + value2);
          }
      }
  }

  /**
   * Get the default initial context. If {@link #gotDefault} == false, this
   * method obtains the initial context from the naming manager and sets
   * gotDefault to true. Otherwise the cached value ({@link #defaultInitCtx} is
   * returned.
   *
   * @return the default initial context
   * @throws NamingException
   */
  protected Context getDefaultInitCtx() throws NamingException
  {
    if (! gotDefault)
      {
        defaultInitCtx = NamingManager.getInitialContext(myProps);
        gotDefault = true;
      }
    return defaultInitCtx;
  }

  /**
   * Obtains the context for resolving the given name. If the first component of
   * the name is the URL string, this method tries to find the corressponding
   * URL naming context. If it is not an URL string, or the URL context is not
   * found, the default initial context is returned.
   *
   * @param name the name, for that it is required to obtain the context.
   * @return the context for resolving the name.
   * @throws NamingException
   */
  protected Context getURLOrDefaultInitCtx(Name name) throws NamingException
  {
    if (name.size() > 0)
      return getURLOrDefaultInitCtx(name.get(0));
    else
      return getDefaultInitCtx();
  }

  /**
   * Obtains the context for resolving the given name. If the first component of
   * the name is the URL string, this method tries to find the corressponding
   * URL naming context. If it is not an URL string, or the URL context is not
   * found, the default initial context is returned.
   *
   * @param name the name, for that it is required to obtain the context.
   * @return the context for resolving the name.
   * @throws NamingException
   */
  protected Context getURLOrDefaultInitCtx(String name) throws NamingException
  {
    String scheme = null;

    if (NamingManager.hasInitialContextFactoryBuilder())
      return getDefaultInitCtx();
    int colon = name.indexOf(':');
    int slash = name.indexOf('/');
    if (colon > 0 && (slash == - 1 || colon < slash))
      scheme = name.substring(0, colon);
    if (scheme != null)
      {
        Context context = NamingManager.getURLContext(scheme, myProps);
        if (context != null)
          return context;
      }

    return getDefaultInitCtx();
  }

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

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

  /** @inheritDoc */
  public Object lookup (Name name) throws NamingException
  {
    try
      {
        return getURLOrDefaultInitCtx (name).lookup (name);
      }
    catch (CannotProceedException cpe)
      {
        Context ctx = NamingManager.getContinuationContext (cpe);
        return ctx.lookup (cpe.getRemainingName());
      }
  }

  /** @inheritDoc */
  public Object lookup (String name) throws NamingException
  {
      try
        {
          return getURLOrDefaultInitCtx (name).lookup (name);
        }
      catch (CannotProceedException cpe)
        {
          Context ctx = NamingManager.getContinuationContext (cpe);
          return ctx.lookup (cpe.getRemainingName());
        }
  }

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

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

  /** @inheritDoc */
  public void unbind (Name name) throws NamingException
  {
    getURLOrDefaultInitCtx (name).unbind (name);
  }

  /** @inheritDoc */
  public void unbind (String name) throws NamingException
  {
    getURLOrDefaultInitCtx (name).unbind (name);
  }

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

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

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

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

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

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

  /** @inheritDoc */
  public void destroySubcontext (Name name) throws NamingException
  {
    getURLOrDefaultInitCtx (name).destroySubcontext (name);
  }

  /** @inheritDoc */
  public void destroySubcontext (String name) throws NamingException
  {
    getURLOrDefaultInitCtx (name).destroySubcontext (name);
  }

  /** @inheritDoc */
  public Context createSubcontext (Name name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).createSubcontext (name);
  }

  /** @inheritDoc */
  public Context createSubcontext (String name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).createSubcontext (name);
  }

  /** @inheritDoc */
  public Object lookupLink (Name name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).lookupLink (name);
  }

  /** @inheritDoc */
  public Object lookupLink (String name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).lookupLink (name);
  }

  /** @inheritDoc */
  public NameParser getNameParser (Name name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).getNameParser (name);
  }

  /** @inheritDoc */
  public NameParser getNameParser (String name) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).getNameParser (name);
  }

  /** @inheritDoc */
  public Name composeName (Name name, Name prefix) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).composeName (name, prefix);
  }

  /** @inheritDoc */
  public String composeName (String name,
                             String prefix) throws NamingException
  {
    return getURLOrDefaultInitCtx (name).composeName (name, prefix);
  }

  /** @inheritDoc */
  public Object addToEnvironment (String propName,
                                  Object propVal) throws NamingException
  {
    return myProps.put (propName, propVal);
  }

  /** @inheritDoc */
  public Object removeFromEnvironment (String propName) throws NamingException
  {
    return myProps.remove (propName);
  }

  /** @inheritDoc */
  public Hashtable<?,?> getEnvironment () throws NamingException
  {
    return myProps;
  }

  /** @inheritDoc */
  public void close () throws NamingException
  {
    myProps = null;
    defaultInitCtx = null;
  }

  /**
   * This operation is not supported for the initial naming context.
   *
   * @throws OperationNotSupportedException always, unless the method is
   *           overridden in the derived class.
   */
  public String getNameInNamespace () throws NamingException
  {
    throw new OperationNotSupportedException ();
  }
}
