/* 
 * 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 java.util.logging;

// BEGIN android-note
// this file contains cleaned up documentation and style for contribution
// upstream.
// javax.management support (MBeans) has been dropped.
// END android-note

import org.apache.harmony.logging.internal.nls.Messages;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 * {@code LogManager} is used to maintain configuration properties of the
 * logging framework, and to manage a hierarchical namespace of all named
 * {@code Logger} objects.
 * <p>
 * There is only one global {@code LogManager} instance in the
 * application, which can be get by calling static method
 * {@link #getLogManager()}. This instance is created and
 * initialized during class initialization and cannot be changed.
 * <p>
 * The {@code LogManager} class can be specified by
 * java.util.logging.manager system property, if the property is unavailable or
 * invalid, the default class {@link java.util.logging.LogManager} will
 * be used.
 * <p>
 * On initialization, {@code LogManager} reads its configuration from a
 * properties file, which by default is the "lib/logging.properties" in the JRE
 * directory.
 * <p>
 * However, two optional system properties can be used to customize the initial
 * configuration process of {@code LogManager}.
 * <ul>
 * <li>"java.util.logging.config.class"</li>
 * <li>"java.util.logging.config.file"</li>
 * </ul>
 * <p>
 * These two properties can be set in three ways, by the Preferences API, by the
 * "java" command line property definitions, or by system property definitions
 * passed to JNI_CreateJavaVM.
 * <p>
 * The "java.util.logging.config.class" should specifies a class name. If it is
 * set, this given class will be loaded and instantiated during
 * {@code LogManager} initialization, so that this object's default
 * constructor can read the initial configuration and define properties for
 * {@code LogManager}.
 * <p>
 * If "java.util.logging.config.class" property is not set, or it is invalid, or
 * some exception is thrown during the instantiation, then the
 * "java.util.logging.config.file" system property can be used to specify a
 * properties file. The {@code LogManager} will read initial
 * configuration from this file.
 * <p>
 * If neither of these properties is defined, or some exception is thrown
 * during these two properties using, the {@code LogManager} will read
 * its initial configuration from default properties file, as described above.
 * <p>
 * The global logging properties may include:
 * <ul>
 * <li>"handlers". This property's values should be a list of class names for
 * handler classes separated by whitespace, these classes must be subclasses of
 * {@code Handler} and each must have a default constructor, these
 * classes will be loaded, instantiated and registered as handlers on the root
 * {@code Logger} (the {@code Logger} named ""). These
 * {@code Handler}s maybe initialized lazily.</li>
 * <li>"config". The property defines a list of class names separated by
 * whitespace. Each class must have a default constructor, in which it can
 * update the logging configuration, such as levels, handlers, or filters for
 * some logger, etc. These classes will be loaded and instantiated during
 * {@code LogManager} configuration</li>
 * </ul>
 * <p>
 * This class, together with any handler and configuration classes associated
 * with it, <b>must</b> be loaded from the system classpath when
 * {@code LogManager} configuration occurs.
 * <p>
 * Besides global properties, the properties for loggers and Handlers can be
 * specified in the property files. The names of these properties will start
 * with the complete dot separated names for the handlers or loggers.
 * <p>
 * In the {@code LogManager}'s hierarchical namespace,
 * {@code Loggers} are organized based on their dot separated names. For
 * example, "x.y.z" is child of "x.y".
 * <p>
 * Levels for {@code Loggers} can be defined by properties whose name end
 * with ".level". Thus "alogger.level" defines a level for the logger named as
 * "alogger" and for all its children in the naming hierarchy. Log levels
 * properties are read and applied in the same order as they are specified in
 * the property file. The root logger's level can be defined by the property
 * named as ".level".
 * <p>
 * This class is thread safe. It is an error to synchronize on a
 * {@code LogManager} while synchronized on a {@code Logger}.
 */
public class LogManager {

    /** The line separator of the underlying OS. */
    private static final String lineSeparator = getPrivilegedSystemProperty("line.separator"); //$NON-NLS-1$

    /** The shared logging permission. */
    private static final LoggingPermission perm = new LoggingPermission(
            "control", null); //$NON-NLS-1$

    /** The singleton instance. */
    static LogManager manager;

    /**
     * The {@code String} value of the {@link LoggingMXBean}'s ObjectName.
     */
    public static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; //$NON-NLS-1$

    /**
     * Get the {@code LoggingMXBean} instance. this implementation always throws
     * an UnsupportedOperationException.
     *
     * @return the {@code LoggingMXBean} instance
     */
    public static LoggingMXBean getLoggingMXBean() {
      // BEGIN android-added
      throw new UnsupportedOperationException();
      // END android-added
      // BEGIN android-removed
      // try {
      //     ObjectName loggingMXBeanName = new ObjectName(LOGGING_MXBEAN_NAME);
      //     MBeanServer platformBeanServer = ManagementFactory
      //             .getPlatformMBeanServer();
      //     Set<?> loggingMXBeanSet = platformBeanServer.queryMBeans(
      //             loggingMXBeanName, null);
      //
      //     if (loggingMXBeanSet.size() != 1) {
      //         // logging.21=There Can Be Only One logging MX bean.
      //         throw new AssertionError(Messages.getString("logging.21")); //$NON-NLS-1$
      //     }
      //
      //     Iterator<?> i = loggingMXBeanSet.iterator();
      //     ObjectInstance loggingMXBeanOI = (ObjectInstance) i.next();
      //     String lmxbcn = loggingMXBeanOI.getClassName();
      //     Class<?> lmxbc = Class.forName(lmxbcn);
      //     Method giMethod = lmxbc.getDeclaredMethod("getInstance"); //$NON-NLS-1$
      //     giMethod.setAccessible(true);
      //     LoggingMXBean lmxb = (LoggingMXBean) giMethod.invoke(null,
      //             new Object[] {});
      //
      //     return lmxb;
      // } catch (Exception e) {
      //     // TODO
      //     // e.printStackTrace();
      // }
      // // logging.22=Exception occurred while getting the logging MX bean.
      // throw new AssertionError(Messages.getString("logging.22")); //$NON-NLS-1$
      // END android-removed
    }

    // FIXME: use weak reference to avoid heap memory leak
    private Hashtable<String, Logger> loggers;

    /** The configuration properties */
    private Properties props;

    /** the property change listener */
    private PropertyChangeSupport listeners;

    static {
        // init LogManager singleton instance
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                String className = System
                        .getProperty("java.util.logging.manager"); //$NON-NLS-1$

                if (null != className) {
                    manager = (LogManager) getInstanceByClass(className);
                }
                if (null == manager) {
                    manager = new LogManager();
                }

                // read configuration
                try {
                    manager.readConfiguration();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // if global logger has been initialized, set root as its parent
                Logger root = new Logger("", null); //$NON-NLS-1$
                root.setLevel(Level.INFO);
                Logger.global.setParent(root);

                manager.addLogger(root);
                manager.addLogger(Logger.global);
                return null;
            }
        });
    }

    /**
     * Default constructor. This is not public because there should be only one
     * {@code LogManager} instance, which can be get by
     * {@code LogManager.getLogManager()}. This is protected so that
     * application can subclass the object.
     */
    protected LogManager() {
        loggers = new Hashtable<String, Logger>();
        props = new Properties();
        listeners = new PropertyChangeSupport(this);
        // add shutdown hook to ensure that the associated resource will be
        // freed when JVM exits
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                Runtime.getRuntime().addShutdownHook(new Thread() {
                    @Override
                    public void run() {
                        reset();
                    }
                });
                return null;
            }
        });
    }

    /*
     * Package private utilities Returns the line separator of the underlying
     * OS.
     */
    static String getSystemLineSeparator() {
        return lineSeparator;
    }

    /**
     * Check that the caller has {@code LoggingPermission("control")} so
     * that it is trusted to modify the configuration for logging framework. If
     * the check passes, just return, otherwise {@code SecurityException}
     * will be thrown.
     *
     * @throws SecurityException
     *             if there is a security manager in operation and the invoker
     *             of this method does not have the required security permission
     *             {@code LoggingPermission("control")}
     */
    public void checkAccess() {
        if (null != System.getSecurityManager()) {
            System.getSecurityManager().checkPermission(perm);
        }
    }

    /**
     * Add a given logger into the hierarchical namespace. The
     * {@code Logger.addLogger()} factory methods call this method to add newly
     * created Logger. This returns false if a logger with the given name has
     * existed in the namespace
     * <p>
     * Note that the {@code LogManager} may only retain weak references to
     * registered loggers. In order to prevent {@code Logger} objects from being
     * unexpectedly garbage collected it is necessary for <i>applications</i>
     * to maintain references to them.
     * </p>
     *
     * @param logger
     *            the logger to be added.
     * @return true if the given logger is added into the namespace
     *         successfully, false if the given logger exists in the namespace.
     */
    public synchronized boolean addLogger(Logger logger) {
        String name = logger.getName();
        if (null != loggers.get(name)) {
            return false;
        }
        addToFamilyTree(logger, name);
        loggers.put(name, logger);
        logger.setManager(this);
        return true;
    }

    private void addToFamilyTree(Logger logger, String name) {
        Logger parent = null;
        // find parent
        int lastSeparator;
        String parentName = name;
        while ((lastSeparator = parentName.lastIndexOf('.')) != -1) {
            parentName = parentName.substring(0, lastSeparator);
            parent = loggers.get(parentName);
            if (parent != null) {
                setParent(logger, parent);
                break;
            } else if (getProperty(parentName + ".level") != null || //$NON-NLS-1$
                    getProperty(parentName + ".handlers") != null) { //$NON-NLS-1$
                parent = Logger.getLogger(parentName);
                setParent(logger, parent);
                break;
            }
        }
        if (parent == null && null != (parent = loggers.get(""))) { //$NON-NLS-1$
            setParent(logger, parent);
        }

        // find children
        // TODO: performance can be improved here?
        Collection<Logger> allLoggers = loggers.values();
        for (final Logger child : allLoggers) {
            Logger oldParent = child.getParent();
            if (parent == oldParent
                    && (name.length() == 0 || child.getName().startsWith(
                            name + '.'))) {
                final Logger thisLogger = logger;
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        child.setParent(thisLogger);
                        return null;
                    }
                });
                if (null != oldParent) {
                    // -- remove from old parent as the parent has been changed
                    oldParent.children.remove(child);
                }
            }
        }
    }

    /**
     * Get the logger with the given name.
     *
     * @param name
     *            name of logger
     * @return logger with given name, or {@code null} if nothing is found.
     */
    public synchronized Logger getLogger(String name) {
        return loggers.get(name);
    }

    /**
     * Get a {@code Enumeration} of all registered logger names.
     *
     * @return enumeration of registered logger names
     */
    public synchronized Enumeration<String> getLoggerNames() {
        return loggers.keys();
    }

    /**
     * Get the global {@code LogManager} instance.
     *
     * @return the global {@code LogManager} instance
     */
    public static LogManager getLogManager() {
        return manager;
    }

    /**
     * Get the value of property with given name.
     *
     * @param name
     *            the name of property
     * @return the value of property
     */
    public String getProperty(String name) {
        return props.getProperty(name);
    }

    /**
     * Re-initialize the properties and configuration. The initialization
     * process is same as the {@code LogManager} instantiation.
     * <p>
     * Notice : No {@code PropertyChangeEvent} are fired.
     * </p>
     *
     * @throws IOException
     *             if any IO related problems happened.
     * @throws SecurityException
     *             if security manager exists and it determines that caller does
     *             not have the required permissions to perform this action.
     */
    public void readConfiguration() throws IOException {
        checkAccess();
        // check config class
        String configClassName = System
                .getProperty("java.util.logging.config.class"); //$NON-NLS-1$
        if (null == configClassName
                || null == getInstanceByClass(configClassName)) {
            // if config class failed, check config file
            String configFile = System
                    .getProperty("java.util.logging.config.file"); //$NON-NLS-1$

            if (null == configFile) {
                // if cannot find configFile, use default logging.properties
                configFile = new StringBuilder().append(
                        System.getProperty("java.home")).append(File.separator) //$NON-NLS-1$
                        .append("lib").append(File.separator).append( //$NON-NLS-1$
                                "logging.properties").toString(); //$NON-NLS-1$
            }

            InputStream input = null;
            try {
                // BEGIN android-removed
                // input = new BufferedInputStream(new FileInputStream(configFile));
                // END android-removed

                // BEGIN android-added
                try {
                    input = new BufferedInputStream(
                            new FileInputStream(configFile), 8192);
                } catch (Exception ex) {
                    // consult fixed resource as a last resort
                    input = new BufferedInputStream(
                            getClass().getResourceAsStream(
                                    "logging.properties"), 8192);
                }
                // END android-added
                readConfigurationImpl(input);
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (Exception e) {// ignore
                    }
                }
            }
        }
    }

    // use privilege code to get system property
    static String getPrivilegedSystemProperty(final String key) {
        return AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                return System.getProperty(key);
            }
        });
    }

    // use SystemClassLoader to load class from system classpath
    static Object getInstanceByClass(final String className) {
        try {
            Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass(
                    className);
            return clazz.newInstance();
        } catch (Exception e) {
            try {
                Class<?> clazz = Thread.currentThread().getContextClassLoader()
                        .loadClass(className);
                return clazz.newInstance();
            } catch (Exception innerE) {
                // logging.20=Loading class "{0}" failed
                System.err.println(Messages.getString("logging.20", className)); //$NON-NLS-1$
                System.err.println(innerE);
                return null;
            }
        }

    }

    // actual initialization process from a given input stream
    private synchronized void readConfigurationImpl(InputStream ins)
            throws IOException {
        reset();
        props.load(ins);

        // update handlers for the root logger only
        Logger root = loggers.get("");
        if (root != null) {
            root.setManager(this);
        }

        // parse property "config" and apply setting
        String configs = props.getProperty("config"); //$NON-NLS-1$
        if (null != configs) {
            StringTokenizer st = new StringTokenizer(configs, " "); //$NON-NLS-1$
            while (st.hasMoreTokens()) {
                String configerName = st.nextToken();
                getInstanceByClass(configerName);
            }
        }

        // set levels for logger
        Collection<Logger> allLoggers = loggers.values();
        for (Logger logger : allLoggers) {
            String property = props.getProperty(logger.getName() + ".level"); //$NON-NLS-1$
            if (null != property) {
                logger.setLevel(Level.parse(property));
            }
        }
        listeners.firePropertyChange(null, null, null);
    }

    /**
     * Re-initialize the properties and configuration from the given
     * {@code InputStream}
     * <p>
     * Notice : No {@code PropertyChangeEvent} are fired.
     * </p>
     *
     * @param ins
     *            the input stream
     * @throws IOException
     *             if any IO related problems happened.
     * @throws SecurityException
     *             if security manager exists and it determines that caller does
     *             not have the required permissions to perform this action.
     */
    public void readConfiguration(InputStream ins) throws IOException {
        checkAccess();
        readConfigurationImpl(ins);
    }

    /**
     * Reset configuration.
     * <p>
     * All handlers are closed and removed from any named loggers. All loggers'
     * level is set to null, except the root logger's level is set to
     * {@code Level.INFO}.
     * </p>
     *
     * @throws SecurityException
     *             if security manager exists and it determines that caller does
     *             not have the required permissions to perform this action.
     */
    public synchronized void reset() {
        checkAccess();
        props = new Properties();
        Enumeration<String> names = getLoggerNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            Logger logger = getLogger(name);
            if (logger != null) {
                logger.reset();
            }
        }
        Logger root = loggers.get(""); //$NON-NLS-1$
        if (null != root) {
            root.setLevel(Level.INFO);
        }
    }

    /**
     * Add a {@code PropertyChangeListener}, which will be invoked when
     * the properties are reread.
     *
     * @param l
     *            the {@code PropertyChangeListener} to be added.
     * @throws SecurityException
     *             if security manager exists and it determines that caller does
     *             not have the required permissions to perform this action.
     */
    public void addPropertyChangeListener(PropertyChangeListener l) {
        if (l == null) {
            throw new NullPointerException();
        }
        checkAccess();
        listeners.addPropertyChangeListener(l);
    }

    /**
     * Remove a {@code PropertyChangeListener}, do nothing if the given
     * listener is not found.
     *
     * @param l
     *            the {@code PropertyChangeListener} to be removed.
     * @throws SecurityException
     *             if security manager exists and it determines that caller does
     *             not have the required permissions to perform this action.
     */
    public void removePropertyChangeListener(PropertyChangeListener l) {
        checkAccess();
        listeners.removePropertyChangeListener(l);
    }

    /**
     * Returns a named logger associated with the supplied resource bundle.
     *
     * @param resourceBundleName the resource bundle to associate, or null for
     *      no associated resource bundle.
     */
    synchronized Logger getOrCreate(String name, String resourceBundleName) {
        Logger result = getLogger(name);
        if (result == null) {
            result = new Logger(name, resourceBundleName);
            addLogger(result);
        }
        return result;
    }


    /**
     * Sets the parent of this logger in the namespace. Callers must first
     * {@link #checkAccess() check security}.
     *
     * @param newParent
     *            the parent logger to set.
     */
    synchronized void setParent(Logger logger, Logger newParent) {
        logger.parent = newParent;

        if (logger.levelObjVal == null) {
            setLevelRecursively(logger, null);
        }
        newParent.children.add(logger);
    }

    /**
     * Sets the level on {@code logger} to {@code newLevel}. Any child loggers
     * currently inheriting their level from {@code logger} will be updated
     * recursively.
     *
     * @param newLevel the new minimum logging threshold. If null, the logger's
     *      parent level will be used; or {@code Level.INFO} for loggers with no
     *      parent.
     */
    synchronized void setLevelRecursively(Logger logger, Level newLevel) {
        int previous = logger.levelIntVal;
        logger.levelObjVal = newLevel;

        if (newLevel == null) {
            logger.levelIntVal = logger.parent != null
                    ? logger.parent.levelIntVal
                    : Level.INFO.intValue();
        } else {
            logger.levelIntVal = newLevel.intValue();
        }

        if (previous != logger.levelIntVal) {
            for (Logger child : logger.children) {
                if (child.levelObjVal == null) {
                    setLevelRecursively(child, null);
                }
            }
        }
    }
}
