/*
 * Copyright 1999-2001 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.naming.internal;

import java.applet.Applet;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.lang.ref.WeakReference;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.util.WeakHashMap;

import javax.naming.*;

/**
  * The ResourceManager class facilitates the reading of JNDI resource files.
  *
  * @author Rosanna Lee
  * @author Scott Seligman
  */

public final class ResourceManager {

    /*
     * Name of provider resource files (without the package-name prefix.)
     */
    private static final String PROVIDER_RESOURCE_FILE_NAME =
            "jndiprovider.properties";

    /*
     * Name of application resource files.
     */
    private static final String APP_RESOURCE_FILE_NAME = "jndi.properties";

    /*
     * Name of properties file in <java.home>/lib.
     */
    private static final String JRELIB_PROPERTY_FILE_NAME = "jndi.properties";

    /*
     * The standard JNDI properties that specify colon-separated lists.
     */
    private static final String[] listProperties = {
        Context.OBJECT_FACTORIES,
        Context.URL_PKG_PREFIXES,
        Context.STATE_FACTORIES,
        // The following shouldn't create a runtime dependence on ldap package.
        javax.naming.ldap.LdapContext.CONTROL_FACTORIES
    };

    private static final VersionHelper helper =
            VersionHelper.getVersionHelper();

    /*
     * A cache of the properties that have been constructed by
     * the ResourceManager.  A Hashtable from a provider resource
     * file is keyed on a class in the resource file's package.
     * One from application resource files is keyed on the thread's
     * context class loader.
     */
    private static final WeakHashMap propertiesCache = new WeakHashMap(11);

    /*
     * A cache of factory objects (ObjectFactory, StateFactory, ControlFactory).
     *
     * A two-level cache keyed first on context class loader and then
     * on propValue.  Value is a list of class or factory objects,
     * weakly referenced so as not to prevent GC of the class loader.
     * Used in getFactories().
     */
    private static final WeakHashMap factoryCache = new WeakHashMap(11);

    /*
     * A cache of URL factory objects (ObjectFactory).
     *
     * A two-level cache keyed first on context class loader and then
     * on classSuffix+propValue.  Value is the factory itself (weakly
     * referenced so as not to prevent GC of the class loader) or
     * NO_FACTORY if a previous search revealed no factory.  Used in
     * getFactory().
     */
    private static final WeakHashMap urlFactoryCache = new WeakHashMap(11);
    private static final WeakReference NO_FACTORY = new WeakReference(null);


    // There should be no instances of this class.
    private ResourceManager() {
    }


    // ---------- Public methods ----------

    /*
     * Given the environment parameter passed to the initial context
     * constructor, returns the full environment for that initial
     * context (never null).  This is based on the environment
     * parameter, the applet parameters (where appropriate), the
     * system properties, and all application resource files.
     *
     * <p> This method will modify <tt>env</tt> and save
     * a reference to it.  The caller may no longer modify it.
     *
     * @param env       environment passed to initial context constructor.
     *                  Null indicates an empty environment.
     *
     * @throws NamingException if an error occurs while reading a
     *          resource file
     */
    public static Hashtable getInitialEnvironment(Hashtable env)
            throws NamingException
    {
        String[] props = VersionHelper.PROPS;   // system/applet properties
        if (env == null) {
            env = new Hashtable(11);
        }
        Applet applet = (Applet)env.get(Context.APPLET);

        // Merge property values from env param, applet params, and system
        // properties.  The first value wins:  there's no concatenation of
        // colon-separated lists.
        // Read system properties by first trying System.getProperties(),
        // and then trying System.getProperty() if that fails.  The former
        // is more efficient due to fewer permission checks.
        //
        String[] jndiSysProps = helper.getJndiProperties();
        for (int i = 0; i < props.length; i++) {
            Object val = env.get(props[i]);
            if (val == null) {
                if (applet != null) {
                    val = applet.getParameter(props[i]);
                }
                if (val == null) {
                    // Read system property.
                    val = (jndiSysProps != null)
                        ? jndiSysProps[i]
                        : helper.getJndiProperty(i);
                }
                if (val != null) {
                    env.put(props[i], val);
                }
            }
        }

        // Merge the above with the values read from all application
        // resource files.  Colon-separated lists are concatenated.
        mergeTables(env, getApplicationResources());
        return env;
    }

    /**
      * Retrieves the property from the environment, or from the provider
      * resource file associated with the given context.  The environment
      * may in turn contain values that come from applet parameters,
      * system properties, or application resource files.
      *
      * If <tt>concat</tt> is true and both the environment and the provider
      * resource file contain the property, the two values are concatenated
      * (with a ':' separator).
      *
      * Returns null if no value is found.
      *
      * @param propName The non-null property name
      * @param env      The possibly null environment properties
      * @param ctx      The possibly null context
      * @param concat   True if multiple values should be concatenated
      * @return the property value, or null is there is none.
      * @throws NamingException if an error occurs while reading the provider
      * resource file.
      */
    public static String getProperty(String propName, Hashtable env,
        Context ctx, boolean concat)
            throws NamingException {

        String val1 = (env != null) ? (String)env.get(propName) : null;
        if ((ctx == null) ||
            ((val1 != null) && !concat)) {
            return val1;
        }
        String val2 = (String)getProviderResource(ctx).get(propName);
        if (val1 == null) {
            return val2;
        } else if ((val2 == null) || !concat) {
            return val1;
        } else {
            return (val1 + ":" + val2);
        }
    }

    /**
     * Retrieves an enumeration of factory classes/object specified by a
     * property.
     *
     * The property is gotten from the environment and the provider
     * resource file associated with the given context and concantenated.
     * See getProperty(). The resulting property value is a list of class names.
     *<p>
     * This method then loads each class using the current thread's context
     * class loader and keeps them in a list. Any class that cannot be loaded
     * is ignored. The resulting list is then cached in a two-level
     * hash table, keyed first by the context class loader and then by
     * the property's value.
     * The next time threads of the same context class loader call this
     * method, they can use the cached list.
     *<p>
     * After obtaining the list either from the cache or by creating one from
     * the property value, this method then creates and returns a
     * FactoryEnumeration using the list. As the FactoryEnumeration is
     * traversed, the cached Class object in the list is instantiated and
     * replaced by an instance of the factory object itself.  Both class
     * objects and factories are wrapped in weak references so as not to
     * prevent GC of the class loader.
     *<p>
     * Note that multiple threads can be accessing the same cached list
     * via FactoryEnumeration, which locks the list during each next().
     * The size of the list will not change,
     * but a cached Class object might be replaced by an instantiated factory
     * object.
     *
     * @param propName  The non-null property name
     * @param env       The possibly null environment properties
     * @param ctx       The possibly null context
     * @return An enumeration of factory classes/objects; null if none.
     * @exception NamingException If encounter problem while reading the provider
     * property file.
     * @see javax.naming.spi.NamingManager#getObjectInstance
     * @see javax.naming.spi.NamingManager#getStateToBind
     * @see javax.naming.spi.DirectoryManager#getObjectInstance
     * @see javax.naming.spi.DirectoryManager#getStateToBind
     * @see javax.naming.ldap.ControlFactory#getControlInstance
     */
    public static FactoryEnumeration getFactories(String propName, Hashtable env,
        Context ctx) throws NamingException {

        String facProp = getProperty(propName, env, ctx, true);
        if (facProp == null)
            return null;  // no classes specified; return null

        // Cache is based on context class loader and property val
        ClassLoader loader = helper.getContextClassLoader();

        Map perLoaderCache = null;
        synchronized (factoryCache) {
            perLoaderCache = (Map) factoryCache.get(loader);
            if (perLoaderCache == null) {
                perLoaderCache = new HashMap(11);
                factoryCache.put(loader, perLoaderCache);
            }
        }

        synchronized (perLoaderCache) {
            List factories = (List) perLoaderCache.get(facProp);
            if (factories != null) {
                // Cached list
                return factories.size() == 0 ? null
                    : new FactoryEnumeration(factories, loader);
            } else {
                // Populate list with classes named in facProp; skipping
                // those that we cannot load
                StringTokenizer parser = new StringTokenizer(facProp, ":");
                factories = new ArrayList(5);
                while (parser.hasMoreTokens()) {
                    try {
                        // System.out.println("loading");
                        String className = parser.nextToken();
                        Class c = helper.loadClass(className, loader);
                        factories.add(new NamedWeakReference(c, className));
                    } catch (Exception e) {
                        // ignore ClassNotFoundException, IllegalArgumentException
                    }
                }
                // System.out.println("adding to cache: " + factories);
                perLoaderCache.put(facProp, factories);
                return new FactoryEnumeration(factories, loader);
            }
        }
    }

    /**
     * Retrieves a factory from a list of packages specified in a
     * property.
     *
     * The property is gotten from the environment and the provider
     * resource file associated with the given context and concatenated.
     * classSuffix is added to the end of this list.
     * See getProperty(). The resulting property value is a list of package
     * prefixes.
     *<p>
     * This method then constructs a list of class names by concatenating
     * each package prefix with classSuffix and attempts to load and
     * instantiate the class until one succeeds.
     * Any class that cannot be loaded is ignored.
     * The resulting object is then cached in a two-level hash table,
     * keyed first by the context class loader and then by the property's
     * value and classSuffix.
     * The next time threads of the same context class loader call this
     * method, they use the cached factory.
     * If no factory can be loaded, NO_FACTORY is recorded in the table
     * so that next time it'll return quickly.
     *
     * @param propName  The non-null property name
     * @param env       The possibly null environment properties
     * @param ctx       The possibly null context
     * @param classSuffix The non-null class name
     *                  (e.g. ".ldap.ldapURLContextFactory).
     * @param defaultPkgPrefix The non-null default package prefix.
     *        (e.g., "com.sun.jndi.url").
     * @return An factory object; null if none.
     * @exception NamingException If encounter problem while reading the provider
     * property file, or problem instantiating the factory.
     *
     * @see javax.naming.spi.NamingManager#getURLContext
     * @see javax.naming.spi.NamingManager#getURLObject
     */
    public static Object getFactory(String propName, Hashtable env, Context ctx,
        String classSuffix, String defaultPkgPrefix) throws NamingException {

        // Merge property with provider property and supplied default
        String facProp = getProperty(propName, env, ctx, true);
        if (facProp != null)
            facProp += (":" + defaultPkgPrefix);
        else
            facProp = defaultPkgPrefix;

        // Cache factory based on context class loader, class name, and
        // property val
        ClassLoader loader = helper.getContextClassLoader();
        String key = classSuffix + " " + facProp;

        Map perLoaderCache = null;
        synchronized (urlFactoryCache) {
            perLoaderCache = (Map) urlFactoryCache.get(loader);
            if (perLoaderCache == null) {
                perLoaderCache = new HashMap(11);
                urlFactoryCache.put(loader, perLoaderCache);
            }
        }

        synchronized (perLoaderCache) {
            Object factory = null;

            WeakReference factoryRef = (WeakReference) perLoaderCache.get(key);
            if (factoryRef == NO_FACTORY) {
                return null;
            } else if (factoryRef != null) {
                factory = factoryRef.get();
                if (factory != null) {  // check if weak ref has been cleared
                    return factory;
                }
            }

            // Not cached; find first factory and cache
            StringTokenizer parser = new StringTokenizer(facProp, ":");
            String className;
            while (factory == null && parser.hasMoreTokens()) {
                className = parser.nextToken() + classSuffix;
                try {
                    // System.out.println("loading " + className);
                    factory = helper.loadClass(className, loader).newInstance();
                } catch (InstantiationException e) {
                    NamingException ne =
                        new NamingException("Cannot instantiate " + className);
                    ne.setRootCause(e);
                    throw ne;
                } catch (IllegalAccessException e) {
                    NamingException ne =
                        new NamingException("Cannot access " + className);
                    ne.setRootCause(e);
                    throw ne;
                } catch (Exception e) {
                    // ignore ClassNotFoundException, IllegalArgumentException,
                    // etc.
                }
            }

            // Cache it.
            perLoaderCache.put(key, (factory != null)
                                        ? new WeakReference(factory)
                                        : NO_FACTORY);
            return factory;
        }
    }


    // ---------- Private methods ----------

    /*
     * Returns the properties contained in the provider resource file
     * of an object's package.  Returns an empty hash table if the
     * object is null or the resource file cannot be found.  The
     * results are cached.
     *
     * @throws NamingException if an error occurs while reading the file.
     */
    private static Hashtable getProviderResource(Object obj)
            throws NamingException
    {
        if (obj == null) {
            return (new Hashtable(1));
        }
        synchronized (propertiesCache) {
            Class c = obj.getClass();

            Hashtable props = (Hashtable)propertiesCache.get(c);
            if (props != null) {
                return props;
            }
            props = new Properties();

            InputStream istream =
                helper.getResourceAsStream(c, PROVIDER_RESOURCE_FILE_NAME);

            if (istream != null) {
                try {
                    ((Properties)props).load(istream);
                } catch (IOException e) {
                    NamingException ne = new ConfigurationException(
                            "Error reading provider resource file for " + c);
                    ne.setRootCause(e);
                    throw ne;
                }
            }
            propertiesCache.put(c, props);
            return props;
        }
    }


    /*
     * Returns the Hashtable (never null) that results from merging
     * all application resource files available to this thread's
     * context class loader.  The properties file in <java.home>/lib
     * is also merged in.  The results are cached.
     *
     * SECURITY NOTES:
     * 1.  JNDI needs permission to read the application resource files.
     * 2.  Any class will be able to use JNDI to view the contents of
     * the application resource files in its own classpath.  Give
     * careful consideration to this before storing sensitive
     * information there.
     *
     * @throws NamingException if an error occurs while reading a resource
     *  file.
     */
    private static Hashtable getApplicationResources() throws NamingException {

        ClassLoader cl = helper.getContextClassLoader();

        synchronized (propertiesCache) {
            Hashtable result = (Hashtable)propertiesCache.get(cl);
            if (result != null) {
                return result;
            }

            try {
                NamingEnumeration resources =
                    helper.getResources(cl, APP_RESOURCE_FILE_NAME);
                while (resources.hasMore()) {
                    Properties props = new Properties();
                    props.load((InputStream)resources.next());

                    if (result == null) {
                        result = props;
                    } else {
                        mergeTables(result, props);
                    }
                }

                // Merge in properties from file in <java.home>/lib.
                InputStream istream =
                    helper.getJavaHomeLibStream(JRELIB_PROPERTY_FILE_NAME);
                if (istream != null) {
                    Properties props = new Properties();
                    props.load(istream);

                    if (result == null) {
                        result = props;
                    } else {
                        mergeTables(result, props);
                    }
                }

            } catch (IOException e) {
                NamingException ne = new ConfigurationException(
                        "Error reading application resource file");
                ne.setRootCause(e);
                throw ne;
            }
            if (result == null) {
                result = new Hashtable(11);
            }
            propertiesCache.put(cl, result);
            return result;
        }
    }

    /*
     * Merge the properties from one hash table into another.  Each
     * property in props2 that is not in props1 is added to props1.
     * For each property in both hash tables that is one of the
     * standard JNDI properties that specify colon-separated lists,
     * the values are concatenated and stored in props1.
     */
    private static void mergeTables(Hashtable props1, Hashtable props2) {
        Enumeration keys = props2.keys();

        while (keys.hasMoreElements()) {
            String prop = (String)keys.nextElement();
            Object val1 = props1.get(prop);
            if (val1 == null) {
                props1.put(prop, props2.get(prop));
            } else if (isListProperty(prop)) {
                String val2 = (String)props2.get(prop);
                props1.put(prop, ((String)val1) + ":" + val2);
            }
        }
    }

    /*
     * Is a property one of the standard JNDI properties that specify
     * colon-separated lists?
     */
    private static boolean isListProperty(String prop) {
        prop = prop.intern();
        for (int i = 0; i < listProperties.length; i++) {
            if (prop == listProperties[i]) {
                return true;
            }
        }
        return false;
    }
}
