// Copyright: http://wiki.apache.org/myfaces/Trinidad_and_Common_Logging
// All Rights Reserved.
package org.apache.wiki


import java.text.MessageFormat;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Writes JDK log messages to commons logging.
 */
public class JavaLoggingToCommonLoggingRedirector {
        static JDKLogHandler activeHandler;

        /**
         * Activates this feature.
         */
        public static void activate() {
                try {
                        Logger rootLogger = LogManager.getLogManager().getLogger("");
                        // remove old handlers
                        for (Handler handler : rootLogger.getHandlers()) {
                                rootLogger.removeHandler(handler);
                        }
                        // add our own
                        activeHandler = new JDKLogHandler();
                        activeHandler.setLevel(Level.ALL);
                        rootLogger.addHandler(activeHandler);
                        rootLogger.setLevel(Level.ALL);
                        // done, let's check it right away!!!

                        Logger.getLogger(JavaLoggingToCommonLoggingRedirector.class.getName()).info("activated: sending JDK log messages to Commons Logging");
                } catch (Exception exc) {
                        LogFactory.getLog(JavaLoggingToCommonLoggingRedirector.class).error("activation failed", exc);
                }
        }

        public static void deactivate() {
                Logger.getLogger(JavaLoggingToCommonLoggingRedirector.class.getName()).info("deactivating...");
                Logger rootLogger = LogManager.getLogManager().getLogger("");
                rootLogger.removeHandler(activeHandler);
        }

        protected static class JDKLogHandler extends Handler {
                private Map<String, Log> cachedLogs = new ConcurrentHashMap<String, Log>();

                private Log getLog(String logName) {
                        Log log = cachedLogs.get(logName);
                        if (log == null) {
                                log = LogFactory.getLog(logName);
                                cachedLogs.put(logName, log);
                        }
                        return log;
                }

                @Override
                public void publish(LogRecord record) {
                        Log log = getLog(record.getLoggerName());
                        // raw Message
                        String message = record.getMessage();
                        // try to localize ...
                        ResourceBundle bundle = record.getResourceBundle();
                        if (bundle != null) {
                            try {
                              message = bundle.getString(message);
                            }
                            catch (MissingResourceException e) {
                              // switch back to raw Message
                              message = record.getMessage();
                            }
                        }
                        // Format message
                        // Do the formatting.
                        try {
                          Object parameters[] = record.getParameters();
                          if (parameters != null && parameters.length != 0) {
                            // Check for the first few parameters ?
                            if (message.indexOf("{0}") >= 0 ||
                                message.indexOf("{1}") >= 0 ||
                                message.indexOf("{2}") >= 0 ||
                                message.indexOf("{3}") >= 0) {
                               message = MessageFormat.format(message, parameters);
                            }
                          }
                        }
                        catch (Exception ex) {
                          // ignore Exception
                        }
                        Throwable exception = record.getThrown();
                        Level level = record.getLevel();
                        if (level == Level.SEVERE) {
                                log.error(message, exception);
                        } else if (level == Level.WARNING) {
                                log.warn(message, exception);
                        } else if (level == Level.INFO) {
                                log.info(message, exception);
                        } else if (level == Level.CONFIG) {
                                log.debug(message, exception);
                        } else {
                                log.trace(message, exception);
                        }
                }

                @Override
                public void flush() {
                  // nothing to do
                }

                @Override
                public void close() {
                  // nothing to do
                }
        }
}
