/*
 * Copyright (c) 2001, 2008, 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 sun.rmi.runtime;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.OutputStream;
import java.rmi.server.LogStream;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Formatter;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
import java.util.Map;
import java.util.HashMap;

/**
 * Utility which provides an abstract "logger" like RMI internal API
 * which can be directed to use one of two types of logging
 * infrastructure: the java.util.logging API or the
 * java.rmi.server.LogStream API.  The default behavior is to use the
 * java.util.logging API.  The LogStream API may be used instead by
 * setting the system property sun.rmi.log.useOld to true.
 *
 * For backwards compatibility, supports the RMI system logging
 * properties which pre-1.4 comprised the only way to configure RMI
 * logging.  If the java.util.logging API is used and RMI system log
 * properties are set, the system properties override initial RMI
 * logger values as appropriate. If the java.util.logging API is
 * turned off, pre-1.4 logging behavior is used.
 *
 * @author Laird Dornin
 * @since 1.4
 */
public abstract class Log {

    /** Logger re-definition of old RMI log values */
    public static final Level BRIEF = Level.FINE;
    public static final Level VERBOSE = Level.FINER;

    /* selects log implementation */
    private static final LogFactory logFactory;
    static {
        boolean useOld =
            Boolean.valueOf(java.security.AccessController.
                doPrivileged(new sun.security.action.GetPropertyAction(
                    "sun.rmi.log.useOld"))).booleanValue();

        /* set factory to select the logging facility to use */
        logFactory = (useOld ? (LogFactory) new LogStreamLogFactory() :
                      (LogFactory) new LoggerLogFactory());
    }

    /** "logger like" API to be used by RMI implementation */
    public abstract boolean isLoggable(Level level);
    public abstract void log(Level level, String message);
    public abstract void log(Level level, String message, Throwable thrown);

    /** get and set the RMI server call output stream */
    public abstract void setOutputStream(OutputStream stream);
    public abstract PrintStream getPrintStream();

    /** factory interface enables Logger and LogStream implementations */
    private static interface LogFactory {
        Log createLog(String loggerName, String oldLogName, Level level);
    }

    /* access log objects */

    /**
     * Access log for a tri-state system property.
     *
     * Need to first convert override value to a log level, taking
     * care to interpret a range of values between BRIEF, VERBOSE and
     * SILENT.
     *
     * An override < 0 is interpreted to mean that the logging
     * configuration should not be overridden. The level passed to the
     * factories createLog method will be null in this case.
     *
     * Note that if oldLogName is null and old logging is on, the
     * returned LogStreamLog will ignore the override parameter - the
     * log will never log messages.  This permits new logs that only
     * write to Loggers to do nothing when old logging is active.
     *
     * Do not call getLog multiple times on the same logger name.
     * Since this is an internal API, no checks are made to ensure
     * that multiple logs do not exist for the same logger.
     */
    public static Log getLog(String loggerName, String oldLogName,
                             int override)
    {
        Level level;

        if (override < 0) {
            level = null;
        } else if (override == LogStream.SILENT) {
            level = Level.OFF;
        } else if ((override > LogStream.SILENT) &&
                   (override <= LogStream.BRIEF)) {
            level = BRIEF;
        } else if ((override > LogStream.BRIEF) &&
                   (override <= LogStream.VERBOSE))
        {
            level = VERBOSE;
        } else {
            level = Level.FINEST;
        }
        return logFactory.createLog(loggerName, oldLogName, level);
    }

    /**
     * Access logs associated with boolean properties
     *
     * Do not call getLog multiple times on the same logger name.
     * Since this is an internal API, no checks are made to ensure
     * that multiple logs do not exist for the same logger.
     */
    public static Log getLog(String loggerName, String oldLogName,
                             boolean override)
    {
        Level level = (override ? VERBOSE : null);
        return logFactory.createLog(loggerName, oldLogName, level);
    }

    /**
     * Factory to create Log objects which deliver log messages to the
     * java.util.logging API.
     */
    private static class LoggerLogFactory implements LogFactory {
        LoggerLogFactory() {}

        /*
         * Accessor to obtain an arbitrary RMI logger with name
         * loggerName.  If the level of the logger is greater than the
         * level for the system property with name, the logger level
         * will be set to the value of system property.
         */
        public Log createLog(final String loggerName, String oldLogName,
                             final Level level)
        {
            Logger logger = Logger.getLogger(loggerName);
            return new LoggerLog(logger, level);
        }
    }

    /**
     * Class specialized to log messages to the java.util.logging API
     */
    private static class LoggerLog extends Log {

        /* alternate console handler for RMI loggers */
        private static final Handler alternateConsole =
                java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction<Handler>() {
                    public Handler run() {
                            InternalStreamHandler alternate =
                                new InternalStreamHandler(System.err);
                            alternate.setLevel(Level.ALL);
                            return alternate;
                        }
                });

        /** handler to which messages are copied */
        private InternalStreamHandler copyHandler = null;

        /* logger to which log messages are written */
        private final Logger logger;

        /* used as return value of RemoteServer.getLog */
        private LoggerPrintStream loggerSandwich;

        /** creates a Log which will delegate to the given logger */
        private LoggerLog(final Logger logger, final Level level) {
            this.logger = logger;

            if (level != null){
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                            if (!logger.isLoggable(level)) {
                                logger.setLevel(level);
                            }
                            logger.addHandler(alternateConsole);
                            return null;
                        }
                    }
                );
            }
        }

        public boolean isLoggable(Level level) {
            return logger.isLoggable(level);
        }

        public void log(Level level, String message) {
            if (isLoggable(level)) {
                String[] source = getSource();
                logger.logp(level, source[0], source[1],
                           Thread.currentThread().getName() + ": " + message);
            }
        }

        public void log(Level level, String message, Throwable thrown) {
            if (isLoggable(level)) {
                String[] source = getSource();
                logger.logp(level, source[0], source[1],
                    Thread.currentThread().getName() + ": " +
                           message, thrown);
            }
        }

        /**
         * Set the output stream associated with the RMI server call
         * logger.
         *
         * Calling code needs LoggingPermission "control".
         */
        public synchronized void setOutputStream(OutputStream out) {
            if (out != null) {
                if (!logger.isLoggable(VERBOSE)) {
                    logger.setLevel(VERBOSE);
                }
                copyHandler = new InternalStreamHandler(out);
                copyHandler.setLevel(Log.VERBOSE);
                logger.addHandler(copyHandler);
            } else {
                /* ensure that messages are not logged */
                if (copyHandler != null) {
                    logger.removeHandler(copyHandler);
                }
                copyHandler = null;
            }
        }

        public synchronized PrintStream getPrintStream() {
            if (loggerSandwich == null) {
                loggerSandwich = new LoggerPrintStream(logger);
            }
            return loggerSandwich;
        }
    }

    /**
     * Subclass of StreamHandler for redirecting log output.  flush
     * must be called in the publish and close methods.
     */
    private static class InternalStreamHandler extends StreamHandler {
        InternalStreamHandler(OutputStream out) {
            super(out, new SimpleFormatter());
        }

        public void publish(LogRecord record) {
            super.publish(record);
            flush();
        }

        public void close() {
            flush();
        }
    }

    /**
     * PrintStream which forwards log messages to the logger.  Class
     * is needed to maintain backwards compatibility with
     * RemoteServer.{set|get}Log().
     */
    private static class LoggerPrintStream extends PrintStream {

        /** logger where output of this log is sent */
        private final Logger logger;

        /** record the last character written to this stream */
        private int last = -1;

        /** stream used for buffering lines */
        private final ByteArrayOutputStream bufOut;

        private LoggerPrintStream(Logger logger)
        {
            super(new ByteArrayOutputStream());
            bufOut = (ByteArrayOutputStream) super.out;
            this.logger = logger;
        }

        public void write(int b) {
            if ((last == '\r') && (b == '\n')) {
                last = -1;
                return;
            } else if ((b == '\n') || (b == '\r')) {
                try {
                    /* write the converted bytes of the log message */
                    String message =
                        Thread.currentThread().getName() + ": " +
                        bufOut.toString();
                    logger.logp(Level.INFO, "LogStream", "print", message);
                } finally {
                    bufOut.reset();
                }
            } else {
                super.write(b);
            }
            last = b;
        }

        public void write(byte b[], int off, int len) {
            if (len < 0) {
                throw new ArrayIndexOutOfBoundsException(len);
            }
            for (int i = 0; i < len; i++) {
                write(b[off + i]);
            }
        }

        public String toString() {
            return "RMI";
        }
    }

    /**
     * Factory to create Log objects which deliver log messages to the
     * java.rmi.server.LogStream API
     */
    private static class LogStreamLogFactory implements LogFactory {
        LogStreamLogFactory() {}

        /* create a new LogStreamLog for the specified log */
        public Log createLog(String loggerName, String oldLogName,
                             Level level)
        {
            LogStream stream = null;
            if (oldLogName != null) {
                stream = LogStream.log(oldLogName);
            }
            return new LogStreamLog(stream, level);
        }
    }

    /**
     * Class specialized to log messages to the
     * java.rmi.server.LogStream API
     */
    private static class LogStreamLog extends Log {
        /** Log stream to which log messages are written */
        private final LogStream stream;

        /** the level of the log as set by associated property */
        private int levelValue = Level.OFF.intValue();

        private LogStreamLog(LogStream stream, Level level) {
            if ((stream != null) && (level != null)) {
                /* if the stream or level is null, dont log any
                 * messages
                 */
                levelValue = level.intValue();
            }
            this.stream = stream;
        }

        public synchronized boolean isLoggable(Level level) {
            return (level.intValue() >= levelValue);
        }

        public void log(Level messageLevel, String message) {
            if (isLoggable(messageLevel)) {
                String[] source = getSource();
                stream.println(unqualifiedName(source[0]) +
                               "." + source[1] + ": " + message);
            }
        }

        public void log(Level level, String message, Throwable thrown) {
            if (isLoggable(level)) {
                /*
                 * keep output contiguous and maintain the contract of
                 * RemoteServer.getLog
                 */
                synchronized (stream) {
                    String[] source = getSource();
                    stream.println(unqualifiedName(source[0]) + "." +
                                   source[1] + ": " + message);
                    thrown.printStackTrace(stream);
                }
            }
        }

        public PrintStream getPrintStream() {
            return stream;
        }

        public synchronized void setOutputStream(OutputStream out) {
            if (out != null) {
                if (VERBOSE.intValue() < levelValue) {
                    levelValue = VERBOSE.intValue();
                }
                stream.setOutputStream(out);
            } else {
                /* ensure that messages are not logged */
                levelValue = Level.OFF.intValue();
            }
        }

        /*
         * Mimic old log messages that only contain unqualified names.
         */
        private static String unqualifiedName(String name) {
            int lastDot = name.lastIndexOf(".");
            if (lastDot >= 0) {
                name = name.substring(lastDot + 1);
            }
            name = name.replace('$', '.');
            return name;
        }
    }

    /**
     * Obtain class and method names of code calling a log method.
     */
    private static String[] getSource() {
        StackTraceElement[] trace = (new Exception()).getStackTrace();
        return new String[] {
            trace[3].getClassName(),
            trace[3].getMethodName()
        };
    }
}
