/*
 * 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 untill 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));
        }
    }


}
