/*
 * 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.sling.commons.log.logback.internal;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.apache.sling.commons.log.logback.internal.AppenderTracker.AppenderInfo;
import org.apache.sling.commons.log.logback.internal.stacktrace.PackageInfoCollector;
import org.apache.sling.commons.log.logback.internal.util.SlingRollingFileAppender;
import org.apache.sling.commons.log.logback.internal.util.SlingStatusPrinter;
import org.apache.sling.commons.log.logback.webconsole.LogPanel;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.weaving.WeavingHook;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.gaffer.GafferUtil;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.jul.LevelChangePropagator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggerContextAwareBase;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.classic.util.EnvUtil;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.joran.GenericConfigurator;
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.status.OnConsoleStatusListener;
import ch.qos.logback.core.status.StatusListener;
import ch.qos.logback.core.status.StatusListenerAsList;
import ch.qos.logback.core.status.StatusUtil;

public class LogbackManager extends LoggerContextAwareBase {
    private static final String JUL_SUPPORT = "org.apache.sling.commons.log.julenabled";

    private static final String PREFIX = "org.apache.sling.commons.log";

    private static final String DEBUG = PREFIX + "." + "debug";

    private static final String PRINTER_URL = "slinglogs";

    private static final String RESET_EVENT_TOPIC = "org/apache/sling/commons/log/RESET";

    /**
     * Framework property specifying the root location used to resolve relative paths
     */
    private static final String SLING_LOG_ROOT = "sling.log.root";

    public static final String PACKAGE_INFO_COLLECTOR_DESC = "Sling Log Package Info Collector";

    private final BundleContext bundleContext;

    private final String rootDir;

    private final String contextName = "sling";

    private final LogConfigManager logConfigManager;

    private final List<LogbackResetListener> resetListeners = new ArrayList<LogbackResetListener>();

    private final org.slf4j.Logger log;

    /**
     * Acts as a bridge between Logback and OSGi
     */
    private final LoggerContextListener osgiIntegrationListener = new OsgiIntegrationListener();

    private final boolean debug;

    private final boolean started;

    private final Semaphore resetLock = new Semaphore(1);

    private final Object configChangedFlagLock = new Object();

    private boolean configChanged = false;

    private final AppenderTracker appenderTracker;

    private final ConfigSourceTracker configSourceTracker;

    private final FilterTracker filterTracker;

    private final TurboFilterTracker turboFilterTracker;

    private final List<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();

    private final List<ServiceTracker> serviceTrackers = new ArrayList<ServiceTracker>();

    private final boolean bridgeHandlerInstalled;

    private final PackageInfoCollector packageInfoCollector = new PackageInfoCollector();

    /**
     * Time at which reset started. Used as the threshold for logging error
     * messages from status printer
     */
    private volatile long resetStartTime;

    public LogbackManager(BundleContext bundleContext) throws InvalidSyntaxException {
        this.bundleContext = bundleContext;

        setLoggerContext((LoggerContext) LoggerFactory.getILoggerFactory());

        this.log = LoggerFactory.getLogger(getClass());
        this.rootDir = getRootDir(bundleContext);
        this.debug = Boolean.parseBoolean(bundleContext.getProperty(DEBUG));
        this.bridgeHandlerInstalled = installSlf4jBridgeHandler(bundleContext);

        this.appenderTracker = new AppenderTracker(bundleContext, getLoggerContext());
        this.configSourceTracker = new ConfigSourceTracker(bundleContext, this);
        this.filterTracker = new FilterTracker(bundleContext,this);
        this.turboFilterTracker = new TurboFilterTracker(bundleContext,getLoggerContext());

        getLoggerContext().setName(contextName);
        this.logConfigManager = new LogConfigManager(getLoggerContext(), bundleContext, rootDir, this);

        resetListeners.add(new LevelChangePropagatorChecker());
        resetListeners.add(logConfigManager);
        resetListeners.add(appenderTracker);
        resetListeners.add(configSourceTracker);
        resetListeners.add(filterTracker);
        resetListeners.add(turboFilterTracker);
        resetListeners.add(new RootLoggerListener()); //Should be invoked at last

        //Record trackers for shutdown later
        serviceTrackers.add(appenderTracker);
        serviceTrackers.add(configSourceTracker);
        serviceTrackers.add(filterTracker);
        serviceTrackers.add(turboFilterTracker);

        this.filterTracker.open();
        this.turboFilterTracker.open();
        getLoggerContext().addListener(osgiIntegrationListener);
        registerWebConsoleSupport();
        registerEventHandler();

        // initial configuration must be done synchronously (aka immediately)
        addInfo("LogbackManager: BEGIN initial configuration");
        failSafeConfigure();
        addInfo("LogbackManager: END initialconfiguration");

        // now open the gate for regular configuration
        started = true;

        //Now check once if any other config was added while we were starting
        logConfigManager.checkForNewConfigsWhileStarting(getLoggerContext());
    }

    public void shutdown() {
        if(bridgeHandlerInstalled){
            SLF4JBridgeHandler.uninstall();
        }

        logConfigManager.close();

        for(ServiceTracker tracker : serviceTrackers){
            tracker.close();
        }

        for (ServiceRegistration reg : registrations) {
            reg.unregister();
        }

        getLoggerContext().removeListener(osgiIntegrationListener);

        getLoggerContext().stop();
    }

    //-------------------------------------- Config reset handling ----------

    public void configChanged() {
        if (!started) {
            return;
        }

        /*
        Logback reset cannot be done concurrently. So when Logback is being reset
        we note down any new request for reset. Later when the thread which performs
        reset finishes, then it checks if any request for reset pending. if yes
        then it again tries to reschedules a job to perform reset in rescheduleIfConfigChanged

        Logback reset is done under a lock 'resetLock' so that Logback
        is not reconfigured concurrently. Only the thread which acquires the
        'resetLock' can submit the task for reload (actual reload done async)

        Once the reload is done the lock is released in LoggerReconfigurer#run

        The way locking works is any thread which changes config
        invokes configChanged. Here two things are possible

        1. Log reset in progress i.e. resetLock already acquired
           In this case the thread would just set the 'configChanged' flag to true

        2. No reset in progress. Thread would acquire the  resetLock and submit the
          job to reset Logback


        Any such change is synchronized with configChangedFlagLock such that a request
         for config changed is not missed
        */

        synchronized (configChangedFlagLock){
            if (resetLock.tryAcquire()) {
                configChanged = false;
                scheduleConfigReload();
            } else {
                configChanged = true;
                addInfo("LoggerContext reset in progress. Marking config changed to true");
            }
        }
    }

    private void rescheduleIfConfigChanged(){
        synchronized (configChangedFlagLock){
            //If config changed then only acquire a lock
            //and proceed to reload
            if(configChanged){
                if(resetLock.tryAcquire()){
                    configChanged = false;
                    scheduleConfigReload();
                }
                //else some other thread acquired the resetlock
                //and reset is in progress. That job would
                //eventually call rescheduleIfConfigChanged again
                //and configChanged request would be taken care of
            }
        }
    }

    private void scheduleConfigReload() {
        getLoggerContext().getExecutorService().submit(new Runnable() {
            @Override
            public void run() {
                // TODO Might be better to run a job to monitor refreshRequirement
                try {
                    failSafeConfigure();
                } finally {
                    resetLock.release();
                    addInfo("Re configuration done");
                    rescheduleIfConfigChanged();
                }
            }
        });
    }

    private void failSafeConfigure(){
        try {
            addInfo("Performing configuration");
            configure();
        } catch (Exception e) {
            log.warn("Error occurred while re-configuring logger", e);
            addError("Error occurred while re-configuring logger", e);
        }
    }

    public void fireResetCompleteListeners(){
        for(LogbackResetListener listener : resetListeners){
            addInfo("Firing reset listener - onResetComplete "+listener.getClass());
            listener.onResetComplete(getLoggerContext());
        }
    }

    public LogConfigManager getLogConfigManager() {
        return logConfigManager;
    }

    public AppenderTracker getAppenderTracker() {
        return appenderTracker;
    }

    public ConfigSourceTracker getConfigSourceTracker() {
        return configSourceTracker;
    }

    public void addSubsitutionProperties(InterpretationContext ic) {
        ic.addSubstitutionProperty("sling.home", rootDir);
    }

    public PackageInfoCollector getPackageInfoCollector() {
        return packageInfoCollector;
    }

    public URL getDefaultConfig() {
        return getClass().getClassLoader().getResource("logback-empty.xml");
    }

    public String getRootDir() {
        return rootDir;
    }

    private void configure() {
        ConfiguratorCallback cb = new DefaultCallback();

        // Check first for an explicit configuration file
        File configFile = logConfigManager.getLogbackConfigFile();
        if (configFile != null) {
            cb = new FilenameConfiguratorCallback(configFile);
        }

        configure(cb);
    }

    private void configure(ConfiguratorCallback cb) {
        long startTime = System.currentTimeMillis();
        StatusListener statusListener = new StatusListenerAsList();
        if (debug) {
            statusListener = new OnConsoleStatusListener();
        }

        getStatusManager().add(statusListener);
        addInfo("Resetting context: " + getLoggerContext().getName());
        resetContext(statusListener);

        StatusUtil statusUtil = new StatusUtil(getLoggerContext());
        JoranConfigurator configurator = createConfigurator();
        final List<SaxEvent> eventList = configurator.recallSafeConfiguration();
        final long threshold = System.currentTimeMillis();
        boolean success = false;
        try {
            cb.perform(configurator);
            if (statusUtil.hasXMLParsingErrors(threshold)) {
                cb.fallbackConfiguration(eventList, createConfigurator(), statusListener);
            }
            addInfo("Context: " + getLoggerContext().getName() + " reloaded.");
            success = true;
        } catch (Throwable t) {
            //Need to catch any error as Logback must work in all scenarios
            //The error would be dumped to sysout in later call to Status printer
            addError("Error occurred while configuring Logback", t);
        } finally {
            if(!success){
                cb.fallbackConfiguration(eventList, createConfigurator(), statusListener);
            }
            getStatusManager().remove(statusListener);
            SlingStatusPrinter.printInCaseOfErrorsOrWarnings(getLoggerContext(), resetStartTime, startTime, success);
        }
    }

    private JoranConfigurator createConfigurator() {
        SlingConfigurator configurator = new SlingConfigurator();
        configurator.setContext(getLoggerContext());
        return configurator;
    }

    private void resetContext(StatusListener statusListener) {
        getLoggerContext().reset();

        // after a reset the statusListenerAsList gets removed as a listener
        if (statusListener != null && !getStatusManager().getCopyOfStatusListenerList().contains(statusListener)) {
            getStatusManager().add(statusListener);
        }
    }

    private String getRootDir(BundleContext bundleContext) {
        String rootDir = bundleContext.getProperty(SLING_LOG_ROOT);
        if (rootDir == null) {
            rootDir = bundleContext.getProperty("sling.home");
            if (rootDir == null) {
                rootDir = new File(".").getAbsolutePath();
            }
        }
        addInfo("Using rootDir as " + rootDir);
        return rootDir;
    }

    //~-------------------------------------------------- Slf4j Bridge Handler Support

    /**
     * Installs the Slf4j BridgeHandler to route the JUL logs through Slf4j
     *
     * @return true only if the BridgeHandler is installed.
     */
    private static boolean installSlf4jBridgeHandler(BundleContext bundleContext){
        // SLING-2373
        if (Boolean.parseBoolean(bundleContext.getProperty(JUL_SUPPORT))) {
            // In config one must enable the LevelChangePropagator
            // http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
            // make sure configuration is empty unless explicitly set
            if (System.getProperty("java.util.logging.config.file") == null
                    && System.getProperty("java.util.logging.config.class") == null) {
                final Thread ct = Thread.currentThread();
                final ClassLoader old = ct.getContextClassLoader();
                try {
                    ct.setContextClassLoader(LogbackManager.class.getClassLoader());
                    System.setProperty("java.util.logging.config.class",
                            DummyLogManagerConfiguration.class.getName());
                    java.util.logging.LogManager.getLogManager().reset();
                } finally {
                    ct.setContextClassLoader(old);
                    System.clearProperty("java.util.logging.config.class");
                }
            }

            SLF4JBridgeHandler.install();
            return true;
        }
        return false;
    }

    /**
     * It checks if LevelChangePropagator is installed or not. If not then
     * it installs the propagator when Slf4j Bridge Handler is installed
     */
    private class LevelChangePropagatorChecker implements LogbackResetListener {

        @Override
        public void onResetStart(LoggerContext context) {

        }

        @Override
        public void onResetComplete(LoggerContext context) {
            List<LoggerContextListener> listenerList = context.getCopyOfListenerList();
            boolean levelChangePropagatorInstalled = false;
            for (LoggerContextListener listener : listenerList) {
                if (listener instanceof LevelChangePropagator) {
                    levelChangePropagatorInstalled = true;
                    break;
                }
            }

            //http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
            if (!levelChangePropagatorInstalled
                    && bridgeHandlerInstalled) {
                LevelChangePropagator propagator = new LevelChangePropagator();
                propagator.setContext(context);
                propagator.start();
                context.addListener(propagator);
                addInfo("Slf4j bridge handler found to be enabled. Installing the LevelChangePropagator");
            }
        }
    }

    /**
     * The <code>DummyLogManagerConfiguration</code> class is used as JUL
     * LogginManager configurator to preven reading platform default
     * configuration which just duplicate log output to be redirected to SLF4J.
     */
    @SuppressWarnings("UnusedDeclaration")
    public static class DummyLogManagerConfiguration {
    }

    // ~-------------------------------LoggerContextListener

    private class OsgiIntegrationListener implements LoggerContextListener {

        @Override
        public boolean isResetResistant() {
            // The integration listener has to survive resets from other causes
            // like reset when Logback detects change in config file and reloads
            // on
            // on its own in ReconfigureOnChangeFilter
            return true;
        }

        @Override
        public void onStart(LoggerContext context) {
        }

        @Override
        public void onReset(LoggerContext context) {
            addInfo("OsgiIntegrationListener : context reset detected. Adding LogManager to context map and firing"
                + " listeners");

            context.setPackagingDataEnabled(false);
            context.setMaxCallerDataDepth(logConfigManager.getMaxCallerDataDepth());
            registerPackageInfoCollector();

            // Attach a console appender to handle logging until we configure
            // one. This would be removed in RootLoggerListener.reset
            final Logger rootLogger = getLoggerContext().getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
            rootLogger.setLevel(Level.INFO);
            rootLogger.addAppender(logConfigManager.getDefaultAppender());

            // Now record the time of reset with a default appender attached to
            // root logger. We also add a milli second extra to account for logs which would have
            // got fired in same duration
            resetStartTime = System.currentTimeMillis() + TimeUnit.MILLISECONDS.toMillis(1);
            addInfo("Registered a default console based logger");

            context.putObject(LogbackManager.class.getName(), LogbackManager.this);
            for (LogbackResetListener l : resetListeners) {
                addInfo("Firing reset listener - onResetStart "+l.getClass());
                l.onResetStart(context);
            }
        }

        @Override
        public void onStop(LoggerContext context) {
        }

        @Override
        public void onLevelChange(Logger logger, Level level) {
        }

    }

    private class RootLoggerListener implements LogbackResetListener {

        @Override
        public void onResetStart(LoggerContext context) {

        }

        @Override
        public void onResetComplete(LoggerContext context) {
            // Remove the default console appender that we attached at start of
            // reset
            ch.qos.logback.classic.Logger root = context.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
            Iterator<Appender<ILoggingEvent>> appenderItr = root.iteratorForAppenders();

            //Root logger has at least 1 appender associated with it. Remove the one added by us
            if (appenderItr.hasNext()) {
                root.detachAppender(LogConfigManager.DEFAULT_CONSOLE_APPENDER_NAME);
                addInfo("Found appender attached with root logger. Detaching the default console based logger");
            } else {
                addInfo("No appender was found to be associated with root logger. Registering " +
                        "a Console based logger");
            }
        }
    }

    // ~--------------------------------Configurator Base

    private class SlingConfigurator extends JoranConfigurator {

        @Override
        protected void buildInterpreter() {
            super.buildInterpreter();
            addSubsitutionProperties(interpreter.getInterpretationContext());
        }
    }

    // ~--------------------------------Configuration Support

    private abstract class ConfiguratorCallback {
        abstract void perform(JoranConfigurator configurator) throws JoranException;

        /**
         * Logic based on
         * ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter.
         * ReconfiguringThread
         */
        public void fallbackConfiguration(List<SaxEvent> eventList, JoranConfigurator configurator,
                StatusListener statusListener) {
            URL mainURL = getMainUrl();
            if (mainURL != null) {
                if (eventList != null) {
                    addWarn("Falling back to previously registered safe configuration.");
                    try {
                        resetContext(statusListener);
                        GenericConfigurator.informContextOfURLUsedForConfiguration(context, mainURL);
                        configurator.doConfigure(eventList);
                        addInfo("Re-registering previous fallback configuration once more as a fallback configuration point");
                        configurator.registerSafeConfiguration(eventList);
                    } catch (JoranException e) {
                        addError("Unexpected exception thrown by a configuration considered safe.", e);
                    }
                } else {
                    addWarn("No previous configuration to fall back on.");
                }
            }
        }

        protected URL getMainUrl() {
            return null;
        }
    }

    private class FilenameConfiguratorCallback extends ConfiguratorCallback {
        private final File configFile;

        public FilenameConfiguratorCallback(File configFile) {
            this.configFile = configFile;
        }

        @Override
        public void perform(JoranConfigurator configurator) throws JoranException {
            final String path = configFile.getAbsolutePath();
            addInfo("Configuring from " + path);
            if (configFile.getName().endsWith("xml")) {
                configurator.doConfigure(configFile);
            } else if (configFile.getName().endsWith("groovy")) {
                if (EnvUtil.isGroovyAvailable()) {
                    // avoid directly referring to GafferConfigurator so as to
                    // avoid
                    // loading groovy.lang.GroovyObject . See also
                    // http://jira.qos.ch/browse/LBCLASSIC-214
                    GafferUtil.runGafferConfiguratorOn(getLoggerContext(), this, configFile);
                } else {
                    addError("Groovy classes are not available on the class path. ABORTING INITIALIZATION.");
                }
            }
        }

        @Override
        protected URL getMainUrl() {
            try {
                return configFile.toURI().toURL();
            } catch (MalformedURLException e) {
                addWarn("Cannot convert file to url " + configFile.getAbsolutePath(), e);
                return null;
            }
        }
    }

    private class DefaultCallback extends ConfiguratorCallback {
        @Override
        public void perform(JoranConfigurator configurator) throws JoranException {
            configurator.doConfigure(getMainUrl());
        }

        @Override
        protected URL getMainUrl() {
            return getDefaultConfig();
        }
    }

    // ~ ----------------------------------------------WebConsole Support

    public LoggerStateContext determineLoggerState() {
        final List<Logger> loggers = getLoggerContext().getLoggerList();
        final LoggerStateContext ctx = new LoggerStateContext(loggers, packageInfoCollector);

        //Distinguish between Logger configured via
        //1. OSGi Config - The ones configured via ConfigAdmin
        //2. Other means - Configured via Logback config or any other means
        for (LogConfig lc : logConfigManager.getLogConfigs()) {
            for (String category : lc.getCategories()) {
                ctx.osgiConfiguredLoggers.put(category, lc);
            }
        }

        for (Logger logger : loggers) {
            boolean hasOnlySlingRollingAppenders = true;
            Iterator<Appender<ILoggingEvent>> itr = logger.iteratorForAppenders();
            while (itr.hasNext()) {
                Appender<ILoggingEvent> a = itr.next();
                if (a.getName() != null && !ctx.appenders.containsKey(a.getName())) {
                    ctx.appenders.put(a.getName(), a);
                }

                if(!(a instanceof SlingRollingFileAppender)){
                    hasOnlySlingRollingAppenders = false;
                }
            }

            if(logger.getLevel() == null){
                continue;
            }

            boolean configuredViaOSGiConfig =
                    ctx.osgiConfiguredLoggers.containsKey(logger.getName());
            if (!configuredViaOSGiConfig
                    || (configuredViaOSGiConfig && !hasOnlySlingRollingAppenders))
                    {
                ctx.nonOSgiConfiguredLoggers.add(logger);
            }

        }


        return ctx;
    }

    public class LoggerStateContext {
        final LoggerContext loggerContext = getLoggerContext();

        final List<Logger> allLoggers;

        /**
         * List of logger which have explicitly defined level or appenders set
         */
        final List<Logger> nonOSgiConfiguredLoggers = new ArrayList<Logger>();

        final Map<String,LogConfig> osgiConfiguredLoggers = new HashMap<String, LogConfig>();

        final Map<String, Appender<ILoggingEvent>> appenders = new HashMap<String, Appender<ILoggingEvent>>();

        final Map<Appender<ILoggingEvent>, AppenderInfo> dynamicAppenders =
                new HashMap<Appender<ILoggingEvent>, AppenderInfo>();

        final Map<ServiceReference,TurboFilter> turboFilters;

        final PackageInfoCollector packageInfoCollector;

        LoggerStateContext(List<Logger> allLoggers, PackageInfoCollector packageInfoCollector) {
            this.allLoggers = allLoggers;
            this.packageInfoCollector = packageInfoCollector;
            for (AppenderTracker.AppenderInfo ai : getAppenderTracker().getAppenderInfos()) {
                dynamicAppenders.put(ai.appender, ai);
            }
            this.turboFilters = turboFilterTracker.getFilters();
        }

        int getNumberOfLoggers() {
            return allLoggers.size();
        }

        int getNumOfDynamicAppenders() {
            return getAppenderTracker().getAppenderInfos().size();
        }

        int getNumOfAppenders() {
            return appenders.size();
        }

        boolean isDynamicAppender(Appender<ILoggingEvent> a) {
            return dynamicAppenders.containsKey(a);
        }

        ServiceReference getTurboFilterRef(TurboFilter tf){
            for(Map.Entry<ServiceReference,TurboFilter> e : turboFilters.entrySet()){
                if(e.getValue().equals(tf)){
                    return e.getKey();
                }
            }
            return null;
        }

        Collection<Appender<ILoggingEvent>> getAllAppenders() {
            return appenders.values();
        }

        Map<String,Appender<ILoggingEvent>> getAppenderMap(){
            return Collections.unmodifiableMap(appenders);
        }
    }

    private void registerWebConsoleSupport() {
        Dictionary<String,Object> panelProps = new Hashtable<>();
        panelProps.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
        panelProps.put(Constants.SERVICE_DESCRIPTION, "Sling Log Panel Support");
        registrations.add(bundleContext.registerService(LogPanel.class.getName(),
                new SlingLogPanel(this, bundleContext), panelProps));

        Dictionary<String,Object> printerProps = new Hashtable<>();
        printerProps.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
        printerProps.put(Constants.SERVICE_DESCRIPTION, "Sling Log Configuration Printer");
        printerProps.put("felix.webconsole.label", PRINTER_URL);
        printerProps.put("felix.webconsole.title", "Log Files");
        printerProps.put("felix.webconsole.configprinter.modes", "always");

        // TODO need to see to add support for Inventory Feature
        registrations.add(bundleContext.registerService(SlingConfigurationPrinter.class.getName(),
            new SlingConfigurationPrinter(this), printerProps));
    }

    private void registerEventHandler() {
        Dictionary<String,Object> props = new Hashtable<>();
        props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
        props.put(Constants.SERVICE_DESCRIPTION, "Sling Log Reset Event Handler");
        props.put("event.topics", new String[] {
            RESET_EVENT_TOPIC
        });

        registrations.add(bundleContext.registerService("org.osgi.service.event.EventHandler", new ServiceFactory() {
            private Object instance;

            @Override
            public Object getService(Bundle bundle, ServiceRegistration serviceRegistration) {
                synchronized (this) {
                    if (this.instance == null) {
                        this.instance = new ConfigResetRequestHandler(LogbackManager.this);
                    }
                    return instance;
                }
            }

            @Override
            public void ungetService(Bundle bundle, ServiceRegistration serviceRegistration, Object o) {
            }
        }, props));
    }

    private void registerPackageInfoCollector() {
        //Weaving hook once registered would not be removed upon config changed
        if (logConfigManager.isPackagingDataEnabled()) {
            Dictionary<String,Object> props = new Hashtable<>();
            props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
            props.put(Constants.SERVICE_DESCRIPTION, PACKAGE_INFO_COLLECTOR_DESC);

            registrations.add(bundleContext.registerService(WeavingHook.class.getName(),
                    packageInfoCollector, props));
        }
    }


}
