/*
 * 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 org.apache.logging.log4j.jul;

//note: NO import of Logger, Level, LogManager to prevent conflicts JUL/log4j
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.LogRecord;

import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.status.StatusLogger;


/**
 * Bridge from JUL to log4j2.<br>
 * This is an alternative to log4j.jul.LogManager (running as complete JUL replacement),
 * especially useful for webapps running on a container for which the LogManager cannot or
 * should not be used.<br><br>
 *
 * Installation/usage:<ul>
 * <li> Declaratively inside JUL's <code>logging.properties</code>:<br>
 *    <code>handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler</code><br>
 *    (and typically also:   <code>org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true</code> )<br>
 *    Note: in a webapp running on Tomcat, you may create a <code>WEB-INF/classes/logging.properties</code>
 *    file to configure JUL for this webapp only: configured handlers and log levels affect your webapp only!
 *    This file is then the <i>complete</i> JUL configuration, so JUL's defaults (e.g. log level INFO) apply
 *    for stuff not explicitly defined therein.
 * <li> Programmatically by calling <code>install()</code> method,
 *    e.g. inside ServletContextListener static-class-init. or contextInitialized()
 * </ul>
 * Configuration (in JUL's <code>logging.properties</code>):<ul>
 * <li> Log4jBridgeHandler.<code>suffixToAppend</code><br>
 *        String, suffix to append to JUL logger names, to easily recognize bridged log messages.
 *        A dot "." is automatically prepended, so configuration for the basis logger is used<br>
 *        Example:  <code>Log4jBridgeHandler.suffixToAppend = _JUL</code><br>
 *        Useful, for example, if you use JSF because it logs exceptions and throws them afterwards;
 *        you can easily recognize the duplicates with this (or concentrate on the non-JUL-logs).
 * <li> Log4jBridgeHandler.<code>propagateLevels</code>   boolean, "true" to automatically propagate log4j log levels to JUL.
 * <li> Log4jBridgeHandler.<code>sysoutDebug</code>   boolean, perform some (developer) debug output to sysout
 * </ul>
 *
 * Log levels are translated with {@link LevelTranslator}, see also
 * <a href="https://logging.apache.org/log4j/2.x/log4j-jul/index.html#Default_Level_Conversions">log4j doc</a>.<br><br>
 *
 * Restrictions:<ul>
 * <li> Manually given source/location info in JUL (e.g. entering(), exiting(), throwing(), logp(), logrb() )
 *    will NOT be considered, i.e. gets lost in log4j logging.
 * <li> Log levels of JUL have to be adjusted according to log4j log levels:
 *      Either by using "propagateLevels" (preferred), or manually by specifying them explicitly,
 *      i.e. logging.properties and log4j2.xml have some redundancies.
 * <li> Only JUL log events that are allowed according to the JUL log level get to this handler and thus to log4j.
 *      This is only relevant and important if you NOT use "propagateLevels".
 *      If you set <code>.level = SEVERE</code> only error logs will be seen by this handler and thus log4j
 *      - even if the corresponding log4j log level is ALL.<br>
 *      On the other side, you should NOT set <code>.level = FINER  or  FINEST</code> if the log4j level is higher.
 *      In this case a lot of JUL log events would be generated, sent via this bridge to log4j and thrown away by the latter.<br>
 *      Note: JUL's default log level (i.e. none specified in logger.properties) is INFO.
 * </ul>
 *
 * (Credits: idea and concept originate from org.slf4j.bridge.SLF4JBridgeHandler;
 *   level propagation idea originates from logback/LevelChangePropagator;
 *   but no source code has been copied)
 */
public class Log4jBridgeHandler extends java.util.logging.Handler implements PropertyChangeListener {
    private static final org.apache.logging.log4j.Logger SLOGGER = StatusLogger.getLogger();

    // the caller of the logging is java.util.logging.Logger (for location info)
    private static final String FQCN = java.util.logging.Logger.class.getName();
    private static final String UNKNOWN_LOGGER_NAME = "unknown.jul.logger";
    private static final java.util.logging.Formatter julFormatter = new java.util.logging.SimpleFormatter();

    private boolean doDebugOutput = false;
    private String julSuffixToAppend = null;
    //not needed:  private boolean installAsLevelPropagator = false;


    /**
     * Adds a new Log4jBridgeHandler instance to JUL's root logger.
     * This is a programmatic alternative to specify
     * <code>handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler</code>
     * and its configuration in logging.properties.<br>
     * @param removeHandlersForRootLogger  true to remove all other installed handlers on JUL root level
     */
    public static void install(boolean removeHandlersForRootLogger, String suffixToAppend, boolean propagateLevels) {
        java.util.logging.Logger rootLogger = getJulRootLogger();
        if (removeHandlersForRootLogger) {
            for (java.util.logging.Handler hdl : rootLogger.getHandlers()) {
                rootLogger.removeHandler(hdl);
            }
        }
        rootLogger.addHandler(new Log4jBridgeHandler(false, suffixToAppend, propagateLevels));
        // note: filter-level of Handler defaults to ALL, so nothing to do here
    }

    private static java.util.logging.Logger getJulRootLogger() {
        return java.util.logging.LogManager.getLogManager().getLogger("");
    }


    /** Initialize this handler by reading out JUL configuration. */
    public Log4jBridgeHandler() {
        final java.util.logging.LogManager julLogMgr = java.util.logging.LogManager.getLogManager();
        final String className = this.getClass().getName();
        init(Boolean.parseBoolean(julLogMgr.getProperty(className + ".sysoutDebug")),
                julLogMgr.getProperty(className + ".appendSuffix"),
                Boolean.parseBoolean(julLogMgr.getProperty(className + ".propagateLevels")) );

    }

    /** Initialize this handler with given configuration. */
    public Log4jBridgeHandler(boolean debugOutput, String suffixToAppend, boolean propagateLevels) {
           init(debugOutput, suffixToAppend, propagateLevels);
       }


    /** Perform init. of this handler with given configuration (typical use is for constructor). */
       protected void init(boolean debugOutput, String suffixToAppend, boolean propagateLevels) {
           this.doDebugOutput = debugOutput;
        if (debugOutput) {
            new Exception("DIAGNOSTIC ONLY (sysout):  Log4jBridgeHandler instance created (" + this + ")")
                    .printStackTrace(System.out);    // is no error thus no syserr
        }

        if (suffixToAppend != null) {
            suffixToAppend = suffixToAppend.trim();    // remove spaces
            if (suffixToAppend.isEmpty()) {
                suffixToAppend = null;
            } else if (suffixToAppend.charAt(0) != '.') {    // always make it a sub-logger
                suffixToAppend = '.' + suffixToAppend;
            }
        }
        this.julSuffixToAppend = suffixToAppend;

        //not needed:  this.installAsLevelPropagator = propagateLevels;
        if (propagateLevels) {
            @SuppressWarnings("resource")    // no need to close the AutoCloseable ctx here
            LoggerContext context = LoggerContext.getContext(false);
            context.addPropertyChangeListener(this);
            propagateLogLevels(context.getConfiguration());
            // note: java.util.logging.LogManager.addPropertyChangeListener() could also
            // be set here, but a call of JUL.readConfiguration() will be done on purpose
        }

        SLOGGER.debug("Log4jBridgeHandler init. with: suffix='{}', lvlProp={}, instance={}",
                suffixToAppend, propagateLevels, this);
    }


    @Override
    public void close() {
        // cleanup and remove listener and JUL logger references
        julLoggerRefs = null;
        LoggerContext.getContext(false).removePropertyChangeListener(this);
        if (doDebugOutput) {
            System.out.println("sysout:  Log4jBridgeHandler close(): " + this);
        }
    }


    @Override
    public void publish(LogRecord record) {
        if (record == null) {    // silently ignore null records
            return;
        }

        org.apache.logging.log4j.Logger log4jLogger = getLog4jLogger(record);
        String msg = julFormatter.formatMessage(record);    // use JUL's implementation to get real msg
        /* log4j allows nulls:
        if (msg == null) {
            // JUL allows nulls, but other log system may not
            msg = "<null log msg>";
        } */
        org.apache.logging.log4j.Level log4jLevel = LevelTranslator.toLevel(record.getLevel());
        Throwable thrown = record.getThrown();
        if (log4jLogger instanceof ExtendedLogger) {
            // relevant for location information
            try {
                ((ExtendedLogger) log4jLogger).logIfEnabled(FQCN, log4jLevel, null, msg, thrown);
            } catch (NoClassDefFoundError e) {
                // sometimes there are problems with log4j.ExtendedStackTraceElement, so try a workaround
                log4jLogger.warn("Log4jBridgeHandler: ignored exception when calling 'ExtendedLogger': {}", e.toString());
                log4jLogger.log(log4jLevel, msg, thrown);
            }
        } else {
            log4jLogger.log(log4jLevel, msg, thrown);
        }
    }


    @Override
    public void flush() {
        // nothing to do
    }


    /**
     * Return the log4j-Logger instance that will be used for logging.
     * Handles null name case and appends configured suffix.
     */
    private org.apache.logging.log4j.Logger getLog4jLogger(LogRecord record) {
        String name = record.getLoggerName();
        if (name == null) {
            name = UNKNOWN_LOGGER_NAME;
        } else if (julSuffixToAppend != null) {
            name += julSuffixToAppend;
        }
        return org.apache.logging.log4j.LogManager.getLogger(name);
    }


/////  log level propagation code


    @Override
    // impl. for PropertyChangeListener
    public void propertyChange(PropertyChangeEvent evt) {
        SLOGGER.debug("Log4jBridgeHandler.propertyChange(): {}", evt);
        if (LoggerContext.PROPERTY_CONFIG.equals(evt.getPropertyName())  &&  evt.getNewValue() instanceof Configuration) {
            propagateLogLevels((Configuration) evt.getNewValue());
        }
    }


    /** Save "hard" references to configured JUL loggers. (is lazy init.) */
    private Set<java.util.logging.Logger> julLoggerRefs;
    /** Perform developer tests? (Should be unused/outcommented for real code) */
    //private static final boolean DEVTEST = false;


    private void propagateLogLevels(Configuration config) {
        SLOGGER.debug("Log4jBridgeHandler.propagateLogLevels(): {}", config);
        // clear or init. saved JUL logger references
        // JUL loggers have to be explicitly referenced because JUL internally uses
        // weak references so not instantiated loggers may be garbage collected
        // and their level config gets lost then.
        if (julLoggerRefs == null) {
            julLoggerRefs = new HashSet<>();
        } else {
            julLoggerRefs.clear();
        }

        //if (DEVTEST)  debugPrintJulLoggers("Start of propagation");
        // walk through all log4j configured loggers and set JUL level accordingly
        final Map<String, LoggerConfig> log4jLoggers = config.getLoggers();
        //java.util.List<String> outTxt = new java.util.ArrayList<>();    // DEVTEST / DEV-DEBUG ONLY
        for (LoggerConfig lcfg : log4jLoggers.values()) {
            java.util.logging.Logger julLog = java.util.logging.Logger.getLogger(lcfg.getName());    // this also fits for root = ""
            java.util.logging.Level julLevel = LevelTranslator.toJavaLevel(lcfg.getLevel());    // lcfg.getLevel() never returns null
            julLog.setLevel(julLevel);
            julLoggerRefs.add(julLog);    // save an explicit reference to prevent GC
            //if (DEVTEST)  outTxt.add("propagating '" + lcfg.getName() + "' / " + lcfg.getLevel() + "  ->  " + julLevel);
        } // for
        //if (DEVTEST)  java.util.Collections.sort(outTxt, String.CASE_INSENSITIVE_ORDER);
        //if (DEVTEST)  for (String s : outTxt)  System.out.println("+ " + s);
        //if (DEVTEST)  debugPrintJulLoggers("After propagation");

        // cleanup JUL: reset all log levels not explicitly given by log4j
        // This has to happen after propagation because JUL creates and inits. the loggers lazily
        // so a nested logger might be created during the propagation-for-loop above and gets
        // its JUL-configured level not until then.
        final java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
        for (Enumeration<String> en = julMgr.getLoggerNames();  en.hasMoreElements(); ) {
            java.util.logging.Logger julLog = julMgr.getLogger(en.nextElement());
            if (julLog != null  &&  julLog.getLevel() != null  &&  !"".equals(julLog.getName())
                    &&  !log4jLoggers.containsKey(julLog.getName()) ) {
                julLog.setLevel(null);
            }
        } // for
        //if (DEVTEST)  debugPrintJulLoggers("After JUL cleanup");
    }


    /* DEV-DEBUG ONLY  (comment out for release) *xx/
    private void debugPrintJulLoggers(String infoStr) {
        if (!DEVTEST)  return;
        java.util.logging.LogManager julMgr = java.util.logging.LogManager.getLogManager();
        System.out.println("sysout:  " + infoStr + " - for " + julMgr);
        java.util.List<String> txt = new java.util.ArrayList<>();
        int n = 1;
        for (Enumeration<String> en = julMgr.getLoggerNames();  en.hasMoreElements(); ) {
            String ln = en.nextElement();
            java.util.logging.Logger lg = julMgr.getLogger(ln);
            if (lg == null) {
                txt.add("(!null-Logger '" + ln + "')  #" + n);
            } else if (lg.getLevel() == null) {
                txt.add("(null-Level Logger '" + ln + "')  #" + n);
            } else {
                txt.add("Logger '" + ln + "',  lvl = " + lg.getLevel() + "  #" + n);
            }
            n++;
        } // for
        java.util.Collections.sort(txt, String.CASE_INSENSITIVE_ORDER);
        for (String s : txt) {
            System.out.println("  - " + s);
        }
    } /**/

}
