/*
 * 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.felix.webconsole.internal.servlet;

import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

import javax.servlet.GenericServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.BrandingPlugin;
import org.apache.felix.webconsole.User;
import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.WebConsoleSecurityProvider;
import org.apache.felix.webconsole.WebConsoleSecurityProvider2;
import org.apache.felix.webconsole.WebConsoleSecurityProvider3;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
import org.apache.felix.webconsole.internal.Util;
import org.apache.felix.webconsole.internal.core.BundlesServlet;
import org.apache.felix.webconsole.internal.filter.FilteringResponseWrapper;
import org.apache.felix.webconsole.internal.i18n.ResourceBundleManager;
import org.apache.felix.webconsole.internal.servlet.PluginHolder.InternalPlugin;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

/**
 * The <code>OSGi Manager</code> is the actual Web Console Servlet which
 * is registered with the OSGi Http Service and which maintains registered
 * console plugins.
 */
public class OsgiManager extends GenericServlet
{

    /** Pseudo class version ID to keep the IDE quite. */
    private static final long serialVersionUID = 1L;

    /**
     * Old name of the request attribute providing the root to the web console.
     * This attribute is no deprecated and replaced by
     * {@link WebConsoleConstants#ATTR_APP_ROOT}.
     *
     * @deprecated use {@link WebConsoleConstants#ATTR_APP_ROOT} instead
     */
    private static final String ATTR_APP_ROOT_OLD = OsgiManager.class.getName()
        + ".appRoot";

    /**
     * Old name of the request attribute providing the mappings from label to
     * page title. This attribute is now deprecated and replaced by
     * {@link WebConsoleConstants#ATTR_LABEL_MAP}.
     *
     * @deprecated use {@link WebConsoleConstants#ATTR_LABEL_MAP} instead
     */
    private static final String ATTR_LABEL_MAP_OLD = OsgiManager.class.getName()
        + ".labelMap";

    /**
     * The name of the (internal) request attribute providing the categorized
     * label map structure.
     */
    public static final String ATTR_LABEL_MAP_CATEGORIZED = WebConsoleConstants.ATTR_LABEL_MAP + ".categorized";

    /**
     * The name and value of a parameter which will prevent redirection to a
     * render after the action has been executed (value is "_noredir_"). This
     * may be used by programmatic action submissions.
     */
    public static final String PARAM_NO_REDIRECT_AFTER_ACTION = "_noredir_";

    /**
     * The name of the cookie storing user-configured locale
     * See https://issues.apache.org/jira/browse/FELIX-2267
     */
    private static final String COOKIE_LOCALE = "felix-webconsole-locale"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_MANAGER_ROOT = "felix.webconsole.manager.root"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_REALM = "felix.webconsole.realm"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_USER_NAME = "felix.webconsole.username"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_PASSWORD = "felix.webconsole.password"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_LOG_LEVEL = "felix.webconsole.loglevel"; //$NON-NLS-1$

    private static final String FRAMEWORK_PROP_LOCALE = "felix.webconsole.locale"; //$NON-NLS-1$

    static final String FRAMEWORK_PROP_SECURITY_PROVIDERS = "felix.webconsole.security.providers"; //$NON-NLS-1$

    static final String SECURITY_PROVIDER_PROPERTY_NAME = "webconsole.security.provider.id"; //$NON-NLS-1$

    static final String PROP_MANAGER_ROOT = "manager.root"; //$NON-NLS-1$

    static final String PROP_DEFAULT_RENDER = "default.render"; //$NON-NLS-1$

    static final String PROP_REALM = "realm"; //$NON-NLS-1$

    static final String PROP_USER_NAME = "username"; //$NON-NLS-1$

    static final String PROP_PASSWORD = "password"; //$NON-NLS-1$

    static final String PROP_CATEGORY = "category"; //$NON-NLS-1$

    static final String PROP_ENABLED_PLUGINS = "plugins"; //$NON-NLS-1$

    static final String PROP_LOG_LEVEL = "loglevel"; //$NON-NLS-1$

    static final String PROP_LOCALE = "locale"; //$NON-NLS-1$

    static final String PROP_HTTP_SERVICE_SELECTOR = "http.service.filter"; //$NON-NLS-1$

    public static final int DEFAULT_LOG_LEVEL = LogService.LOG_WARNING;

    static final String DEFAULT_PAGE = BundlesServlet.NAME;

    static final String DEFAULT_REALM = "OSGi Management Console"; //$NON-NLS-1$

    static final String DEFAULT_USER_NAME = "admin"; //$NON-NLS-1$

    static final String DEFAULT_PASSWORD = "{sha-256}jGl25bVBBBW96Qi9Te4V37Fnqchz/Eu4qB9vKrRIqRg="; //$NON-NLS-1$

    static final String DEFAULT_CATEGORY = "Main"; //$NON-NLS-1$

    static final String DEFAULT_HTTP_SERVICE_SELECTOR = ""; //$NON-NLS-1$

    private static final String HEADER_AUTHORIZATION = "Authorization"; //$NON-NLS-1$

    private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; //$NON-NLS-1$

    /**
     * The default value for the {@link #PROP_MANAGER_ROOT} configuration
     * property (value is "/system/console").
     */
    static final String DEFAULT_MANAGER_ROOT = "/system/console"; //$NON-NLS-1$

    private static final String OLD_CONFIG_MANAGER_CLASS = "org.apache.felix.webconsole.internal.compendium.ConfigManager"; //$NON-NLS-1$
    private static final String NEW_CONFIG_MANAGER_CLASS = "org.apache.felix.webconsole.internal.configuration.ConfigManager"; //$NON-NLS-1$

    static final String[] PLUGIN_CLASSES = {
            "org.apache.felix.webconsole.internal.configuration.ConfigurationAdminConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.compendium.PreferencesConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.compendium.WireAdminConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.core.BundlesConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.core.PermissionsConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.core.ServicesConfigurationPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.misc.SystemPropertiesPrinter", //$NON-NLS-1$
            "org.apache.felix.webconsole.internal.misc.ThreadPrinter", }; //$NON-NLS-1$

    static final String[] PLUGIN_MAP = {
            NEW_CONFIG_MANAGER_CLASS, "configMgr", //$NON-NLS-1$ //$NON-NLS-2$
            "org.apache.felix.webconsole.internal.compendium.LogServlet", "logs", //$NON-NLS-1$ //$NON-NLS-2$
            "org.apache.felix.webconsole.internal.core.BundlesServlet", "bundles", //$NON-NLS-1$ //$NON-NLS-2$
            "org.apache.felix.webconsole.internal.core.ServicesServlet", "services", //$NON-NLS-1$ //$NON-NLS-2$
            "org.apache.felix.webconsole.internal.misc.LicenseServlet", "licenses", //$NON-NLS-1$ //$NON-NLS-2$
            "org.apache.felix.webconsole.internal.system.VMStatPlugin", "vmstat", //$NON-NLS-1$ //$NON-NLS-2$
    };

    private BundleContext bundleContext;

    private HttpServiceTracker httpServiceTracker;

    private volatile HttpService httpService;

    private PluginHolder holder;

    private ServiceTracker brandingTracker;

    private ServiceTracker<WebConsoleSecurityProvider, WebConsoleSecurityProvider> securityProviderTracker;

    private ServiceRegistration configurationListener;

    // list of OsgiManagerPlugin instances activated during init. All these
    // instances will have to be deactivated during destroy
    private List<OsgiManagerPlugin> osgiManagerPlugins = new ArrayList<>();

    private String webManagerRoot;

    // true if the OsgiManager is registered as a Servlet with the HttpService
    private boolean httpServletRegistered;

    // true if the resources have been registered with the HttpService
    private boolean httpResourcesRegistered;

    // default configuration from framework properties
    private Map<String, Object> defaultConfiguration;

    // configuration from Configuration Admin
    private volatile Map<String, Object> configuration;

    // See https://issues.apache.org/jira/browse/FELIX-2267
    private Locale configuredLocale;

    private Set<String> enabledPlugins;

    final ConcurrentSkipListSet<String> registeredSecurityProviders = new ConcurrentSkipListSet<String>();

    final Set<String> requiredSecurityProviders;

    ResourceBundleManager resourceBundleManager;

    private int logLevel = DEFAULT_LOG_LEVEL;

    private String defaultCategory = DEFAULT_CATEGORY;

    public OsgiManager(BundleContext bundleContext)
    {
        this.bundleContext = bundleContext;
        this.holder = new PluginHolder(bundleContext);

        // new plugins setup
        for (int i = 0; i < PLUGIN_MAP.length; i++)
        {
            final String pluginClassName = PLUGIN_MAP[i++];
            final String label = PLUGIN_MAP[i];
            holder.addInternalPlugin(this, pluginClassName, label);
        }

        // setup the included plugins
        ClassLoader classLoader = getClass().getClassLoader();
        for (int i = 0; i < PLUGIN_CLASSES.length; i++)
        {
            String pluginClassName = PLUGIN_CLASSES[i];

            try
            {
                final Class<?> pluginClass = classLoader.loadClass(pluginClassName);
                final Object plugin = pluginClass.getDeclaredConstructor().newInstance();

                if (plugin instanceof OsgiManagerPlugin)
                {
                    final OsgiManagerPlugin p = (OsgiManagerPlugin)plugin;
                    p.activate(bundleContext);
                    osgiManagerPlugins.add(p);
                }
                if (plugin instanceof BrandingPlugin)
                {
                    AbstractWebConsolePlugin.setBrandingPlugin((BrandingPlugin) plugin);
                }
            }
            catch (NoClassDefFoundError ncdfe)
            {
                String message = ncdfe.getMessage();
                if (message == null)
                {
                    // no message, construct it
                    message = "Class definition not found (NoClassDefFoundError)";
                }
                else if (message.indexOf(' ') < 0)
                {
                    // message is just a class name, try to be more descriptive
                    message = "Class " + message + " missing";
                }
                log(LogService.LOG_INFO, pluginClassName + " not enabled. Reason: "
                    + message);
            }
            catch (Throwable t)
            {
                log(LogService.LOG_INFO, "Failed to instantiate plugin "
                    + pluginClassName + ". Reason: " + t);
            }
        }

        // the resource bundle manager
        resourceBundleManager = new ResourceBundleManager(getBundleContext());

        // start the configuration render, providing the resource bundle manager
        //ConfigurationRender cr = new ConfigurationRender(resourceBundleManager);
        //cr.activate(bundleContext);
        //osgiManagerPlugins.add(cr);
        //holder.addOsgiManagerPlugin(cr);

        // start tracking external plugins after setting up our own plugins
        holder.open();

        // accept new console branding service
        brandingTracker = new BrandingServiceTracker(this);
        brandingTracker.open();

        this.requiredSecurityProviders = splitCommaSeparatedString(bundleContext.getProperty(FRAMEWORK_PROP_SECURITY_PROVIDERS));

        // add support for pluggable security
        securityProviderTracker = new ServiceTracker<>(bundleContext, WebConsoleSecurityProvider.class,
                                          new UpdateDependenciesStateCustomizer());
        securityProviderTracker.open();

        // load the default configuration from the framework
        this.defaultConfiguration = new HashMap<>();
        this.defaultConfiguration.put( PROP_MANAGER_ROOT,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_MANAGER_ROOT, DEFAULT_MANAGER_ROOT ) );
        this.defaultConfiguration.put( PROP_REALM,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_REALM, DEFAULT_REALM ) );
        this.defaultConfiguration.put( PROP_USER_NAME,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_USER_NAME, DEFAULT_USER_NAME ) );
        this.defaultConfiguration.put( PROP_PASSWORD,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_PASSWORD, DEFAULT_PASSWORD ) );
        this.defaultConfiguration.put( PROP_LOG_LEVEL,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_LOG_LEVEL, DEFAULT_LOG_LEVEL ) );
        this.defaultConfiguration.put( PROP_LOCALE,
            ConfigurationUtil.getProperty( bundleContext, FRAMEWORK_PROP_LOCALE, null ) );

        // configure and start listening for configuration
        updateConfiguration(null);

        // register managed service as a service factory
        this.configurationListener = bundleContext.registerService( "org.osgi.service.cm.ManagedService", //$NON-NLS-1$
            new ServiceFactory()
            {
                public Object getService( Bundle bundle, ServiceRegistration registration )
                {
                    /*
                     * Explicitly load the class through the class loader to dynamically
                     * wire the API if not wired yet. Implicit loading by creating a
                     * class instance does not seem to properly work wiring the API
                     * in time.
                     */
                    try
                    {
                        OsgiManager.this.getClass().getClassLoader()
                            .loadClass( "org.osgi.service.metatype.MetaTypeProvider" );
                        return new ConfigurationMetatypeSupport( OsgiManager.this );
                    }
                    catch ( ClassNotFoundException cnfe )
                    {
                        // ignore
                    }

                    return new ConfigurationSupport( OsgiManager.this );
                }


                public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
                {
                    // do nothing
                }
            }, new Hashtable<String, Object>()
            {
                {
                    put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" ); //$NON-NLS-1$
                    put( Constants.SERVICE_DESCRIPTION, "OSGi Management Console Configuration Receiver" ); //$NON-NLS-1$
                    put( Constants.SERVICE_PID, getConfigurationPid() );
                }
            } );
    }

    void updateRegistrationState() {
        if (this.httpService != null) {
            if (this.registeredSecurityProviders.containsAll(this.requiredSecurityProviders)) {
                // register HTTP service
                registerHttpService();
                return;
            } else {
                log(LogService.LOG_INFO, "Not all requirements met for the Web Console. Required security providers: "
                        + this.registeredSecurityProviders + " Registered security providers: " + this.registeredSecurityProviders);
            }
        }
        // Not all requirements met, unregister service.
        unregisterHttpService();
    }

    public void dispose()
    {
        // dispose off held plugins
        holder.close();

        // dispose off the resource bundle manager
        if (resourceBundleManager != null)
        {
            resourceBundleManager.dispose();
            resourceBundleManager = null;
        }

        // stop listening for brandings
        if (brandingTracker != null)
        {
            brandingTracker.close();
            brandingTracker = null;
        }

        // deactivate any remaining plugins
        for (Iterator<OsgiManagerPlugin> pi = osgiManagerPlugins.iterator(); pi.hasNext();)
        {
            OsgiManagerPlugin plugin = pi.next();
            plugin.deactivate();
        }

        // simply remove all operations, we should not be used anymore
        this.osgiManagerPlugins.clear();

        // now drop the HttpService and continue with further destroyals
        if (httpServiceTracker != null)
        {
            httpServiceTracker.close();
            httpServiceTracker = null;
        }

        // stop listening for configuration
        if (configurationListener != null)
        {
            configurationListener.unregister();
            configurationListener = null;
        }

        // stop tracking security provider
        if (securityProviderTracker != null)
        {
            securityProviderTracker.close();
            securityProviderTracker = null;
        }

        this.bundleContext = null;
    }

    //---------- Servlet API

    /**
     * @see javax.servlet.GenericServlet#init()
     */
    public void init()
    {
        // base class initialization not needed, since the GenericServlet.init
        // is an empty method

        holder.setServletContext(getServletContext());

    }

    /**
     * @see javax.servlet.GenericServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
     */
    public void service(final ServletRequest req, final ServletResponse res)
        throws ServletException, IOException
    {
        // don't really expect to be called within a non-HTTP environment
        try
        {
            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
            {
                public Object run() throws Exception
                {
                    service((HttpServletRequest) req, (HttpServletResponse) res);
                    return null;
                }
            });
        }
        catch (PrivilegedActionException e)
        {
            Exception x = e.getException();
            if (x instanceof IOException)
            {
                throw (IOException) x;
            }
            else if (x instanceof ServletException)
            {
                throw (ServletException) x;
            }
            else
            {
                throw new IOException(x.toString());
            }
        }
    }

    private void ensureLocaleCookieSet(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        Cookie[] cookies = request.getCookies();
        boolean hasCookie = false;
        for(int i=0; cookies != null && i<cookies.length;i++) {
            if (COOKIE_LOCALE.equals(cookies[i].getName()) ) {
                hasCookie = true;
                break;
            }
        }
        if (!hasCookie) {
            Cookie cookie = new Cookie(COOKIE_LOCALE, locale.toString());
            cookie.setPath((String)request.getAttribute(WebConsoleConstants.ATTR_APP_ROOT));
            cookie.setMaxAge(20 * 365 * 24 * 60 * 60); // 20 years
            response.addCookie(cookie);
        }
    }

    void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        // check whether we are not at .../{webManagerRoot}
        final String pathInfo = request.getPathInfo();
        if (pathInfo == null || pathInfo.equals("/")) //$NON-NLS-1$
        {
            String path = request.getRequestURI();
            if (!path.endsWith("/")) //$NON-NLS-1$
            {
                path = path.concat("/"); //$NON-NLS-1$
            }
            path = path.concat(holder.getDefaultPluginLabel());
            response.setContentLength(0);
            response.sendRedirect(path);
            return;
        }

        if (pathInfo.equals("/logout")) { //$NON-NLS-1$
            logout(request, response);
            return;
        }

        int slash = pathInfo.indexOf("/", 1); //$NON-NLS-1$
        if (slash < 2)
        {
            slash = pathInfo.length();
        }

        final Locale locale = getConfiguredLocale(request);
        final String label = pathInfo.substring(1, slash);
        AbstractWebConsolePlugin plugin = getConsolePlugin(label);
        if (plugin != null)
        {
            final Map labelMap = holder.getLocalizedLabelMap( resourceBundleManager, locale, this.defaultCategory );
            final Object flatLabelMap = labelMap.remove( WebConsoleConstants.ATTR_LABEL_MAP );

            // the official request attributes
            request.setAttribute(WebConsoleConstants.ATTR_LANG_MAP, getLangMap());
            request.setAttribute(WebConsoleConstants.ATTR_LABEL_MAP, flatLabelMap);
            request.setAttribute( ATTR_LABEL_MAP_CATEGORIZED, labelMap );
            request.setAttribute(WebConsoleConstants.ATTR_APP_ROOT,
                request.getContextPath() + request.getServletPath());
            request.setAttribute(WebConsoleConstants.ATTR_PLUGIN_ROOT,
                request.getContextPath() + request.getServletPath() + '/' + label);

            // deprecated request attributes
            request.setAttribute(ATTR_LABEL_MAP_OLD, flatLabelMap);
            request.setAttribute(ATTR_APP_ROOT_OLD,
                request.getContextPath() + request.getServletPath());

            // fix for https://issues.apache.org/jira/browse/FELIX-3408
            ensureLocaleCookieSet(request, response, locale);

            // wrap the response for localization and template variable replacement
            request = wrapRequest(request, locale);
            response = wrapResponse(request, response, plugin);

            plugin.service(request, response);
        }
        else
        {
            final String body404 = MessageFormat.format(
                resourceBundleManager.getResourceBundle(bundleContext.getBundle(), locale).getString(
                    "404"), //$NON-NLS-1$
                new Object[] { request.getContextPath() + request.getServletPath() + '/'
                    + BundlesServlet.NAME });
            response.setCharacterEncoding("utf-8"); //$NON-NLS-1$
            response.setContentType("text/html"); //$NON-NLS-1$
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.getWriter().println(body404);
        }
    }

    private final void logout(HttpServletRequest request, HttpServletResponse response)
        throws IOException
    {
        // check if special logout cookie is set, this is used to prevent
        // from an endless loop with basic auth
        Cookie[] cookies = request.getCookies();
        boolean found = false;
        if ( cookies != null )
        {
            for(int i=0;i<cookies.length;i++)
            {
                if ( cookies[i].getName().equals("logout") ) //$NON-NLS-1$
                {
                    found = true;
                    break;
                }
            }
        }
        if ( found )
        {
            // redirect to main page
            String url = request.getRequestURI();
            final int lastSlash = url.lastIndexOf('/');
            final Cookie c = new Cookie("logout", "true"); //$NON-NLS-1$ //$NON-NLS-2$
            c.setMaxAge(0);
            response.addCookie(c);
            response.sendRedirect(url.substring(0, lastSlash));
            return;
        }
        Object securityProvider = securityProviderTracker.getService();
        if (securityProvider instanceof WebConsoleSecurityProvider3)
        {
            ((WebConsoleSecurityProvider3) securityProvider).logout(request, response);
        }
        else
        {
            // if the security provider doesn't support logout, we try to
            // logout the default basic authentication mechanism
            // See https://issues.apache.org/jira/browse/FELIX-3006

            // check for basic authentication
            String auth = request.getHeader(HEADER_AUTHORIZATION); //$NON-NLS-1$
            if (null != auth && auth.toLowerCase().startsWith("basic ")) { //$NON-NLS-1$
                Map<String, Object> config = getConfiguration();
                String realm = ConfigurationUtil.getProperty(config, PROP_REALM, DEFAULT_REALM);
                response.setHeader(HEADER_WWW_AUTHENTICATE, "Basic realm=\"" +  realm + "\""); //$NON-NLS-1$ //$NON-NLS-2$
                response.addCookie(new Cookie("logout", "true")); //$NON-NLS-1$ //$NON-NLS-2$
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }

        // clean-up
        request.removeAttribute(HttpContext.REMOTE_USER);
        request.removeAttribute(HttpContext.AUTHORIZATION);
        request.removeAttribute(WebConsoleSecurityProvider2.USER_ATTRIBUTE);
        request.removeAttribute(User.USER_ATTRIBUTE);
    }

    private final AbstractWebConsolePlugin getConsolePlugin(final String label)
    {
        // backwards compatibility for the former "install" action which is
        // used by the Maven Sling Plugin
        if ("install".equals(label)) //$NON-NLS-1$
        {
            return holder.getPlugin(BundlesServlet.NAME);
        }

        AbstractWebConsolePlugin plugin = holder.getPlugin( label );
        if ( plugin == null && label.indexOf( '.' ) > 0 )
        {
            int last = 0;
            for ( int dot = label.indexOf( '.', last ); plugin == null && dot > last; last = dot + 1, dot = label
                .indexOf( '.', last ) )
            {
                final String pluginLabel = label.substring( 0, dot );
                plugin = holder.getPlugin( pluginLabel );
            }
        }
        return plugin;
    }

    // See https://issues.apache.org/jira/browse/FELIX-2267
    private final Locale getConfiguredLocale(HttpServletRequest request)
    {
        Locale locale = null;

        Cookie[] cookies = request.getCookies();
        for (int i = 0; cookies != null && i < cookies.length; i++)
        {
            if (COOKIE_LOCALE.equals(cookies[i].getName()))
            {
                locale = Util.parseLocaleString(cookies[i].getValue());
                break;
            }
        }

        // TODO: check UserAdmin ?

        if (locale == null)
            locale = configuredLocale;
        if (locale == null)
            locale = request.getLocale();
        // this should never happen as request.getLocale()
        // must return a locale (and not null). But just as a sanity check.
        if (locale == null)
            locale = Locale.ENGLISH;

        return locale;
    }

    /**
     * @see javax.servlet.GenericServlet#destroy()
     */
    public void destroy()
    {
        // base class destroy not needed, since the GenericServlet.destroy
        // is an empty method

        holder.setServletContext(null);
    }

    //---------- internal

    BundleContext getBundleContext()
    {
        return bundleContext;
    }

    /**
     * Returns the Service PID used to retrieve configuration and to describe
     * the configuration properties.
     */
    String getConfigurationPid()
    {
        return getClass().getName();
    }


    /**
     * Calls the <code>ServletContext.log(String)</code> method if the
     * configured log level is less than or equal to the given <code>level</code>.
     * <p>
     * Note, that the <code>level</code> parameter is only used to decide whether
     * the <code>GenericServlet.log(String)</code> method is called or not. The
     * actual implementation of the <code>GenericServlet.log</code> method is
     * outside of the control of this method.
     * <p>
     * If the servlet has not been initialized yet or has already been destroyed
     * the message is printed to stderr.
     *
     * @param level The log level at which to log the message
     * @param message The message to log
     */
    void log(int level, String message)
    {
        if (logLevel >= level)
        {
            ServletConfig config = getServletConfig();
            if ( config != null )
            {
                ServletContext context = config.getServletContext();
                if ( context != null )
                {
                    context.log( message );
                    return;
                }
            }

            System.err.println( message );
        }
    }

    /**
     * Calls the <code>ServletContext.log(String, Throwable)</code> method if
     * the configured log level is less than or equal to the given
     * <code>level</code>.
     * <p>
     * Note, that the <code>level</code> parameter is only used to decide whether
     * the <code>GenericServlet.log(String, Throwable)</code> method is called
     * or not. The actual implementation of the <code>GenericServlet.log</code>
     * method is outside of the control of this method.
     * <p>
     * If the servlet has not been initialized yet or has already been destroyed
     * the message is printed to stderr.
     *
     * @param level The log level at which to log the message
     * @param message The message to log
     * @param t The <code>Throwable</code> to log with the message
     */
    void log(int level, String message, Throwable t)
    {
        if (logLevel >= level)
        {
            ServletConfig config = getServletConfig();
            if ( config != null )
            {
                ServletContext context = config.getServletContext();
                if ( context != null )
                {
                    context.log( message, t );
                    return;
                }
            }

            System.err.println( message );
            if ( t != null )
            {
                t.printStackTrace( System.err );
            }
        }
    }

    private HttpServletRequest wrapRequest(final HttpServletRequest request,
        final Locale locale)
    {
        return new HttpServletRequestWrapper(request)
        {
            /**
             * @see javax.servlet.ServletRequestWrapper#getLocale()
             */
            public Locale getLocale()
            {
                return locale;
            }
        };
    }

    private HttpServletResponse wrapResponse(final HttpServletRequest request,
        final HttpServletResponse response, final AbstractWebConsolePlugin plugin)
    {
        final Locale locale = request.getLocale();
        final ResourceBundle resourceBundle = resourceBundleManager.getResourceBundle(
            plugin.getBundle(), locale);
        return new FilteringResponseWrapper(response, resourceBundle, request);
    }

    private static class HttpServiceTracker extends ServiceTracker<HttpService, HttpService>
    {
        private final OsgiManager osgiManager;

        private final String httpServiceSelector;

        static HttpServiceTracker create(OsgiManager osgiManager,
            String httpServiceSelector)
        {
            // got a service selector filter
            if (httpServiceSelector != null && httpServiceSelector.length() > 0)
            {
                try
                {
                    final String filterString = "(&(" + Constants.OBJECTCLASS + "=" //$NON-NLS-1$ //$NON-NLS-2$
                        + HttpService.class.getName() + ")(" + httpServiceSelector + "))"; //$NON-NLS-1$ //$NON-NLS-2$
                    Filter filter = osgiManager.getBundleContext().createFilter(
                        filterString);
                    return new HttpServiceTracker(osgiManager, httpServiceSelector,
                        filter);
                }
                catch (InvalidSyntaxException ise)
                {
                    // TODO: log or throw or ignore ....
                }
            }

            // no filter or illegal filter string
            return new HttpServiceTracker(osgiManager);
        }

        private HttpServiceTracker(final OsgiManager osgiManager)
        {
            super(osgiManager.getBundleContext(), HttpService.class, null);
            this.osgiManager = osgiManager;
            this.httpServiceSelector = null;
        }

        private HttpServiceTracker(final OsgiManager osgiManager, final String httpServiceSelector, final Filter httpServiceFilter)
        {
            super(osgiManager.getBundleContext(), httpServiceFilter, null);
            this.osgiManager = osgiManager;
            this.httpServiceSelector = httpServiceSelector;
        }

        boolean isSameSelector(final String newHttpServiceSelector)
        {
            if (newHttpServiceSelector != null)
            {
                return newHttpServiceSelector.equals(httpServiceSelector);
            }
            return httpServiceSelector == null;
        }

        public HttpService addingService(ServiceReference<HttpService> reference)
        {
            HttpService service = super.addingService(reference);
            osgiManager.bindHttpService(service);
            return service;
        }

        public void removedService(ServiceReference<HttpService> reference, HttpService service)
        {
            osgiManager.unbindHttpService(service);

            super.removedService(reference, service);
        }
    }

    private static class BrandingServiceTracker extends ServiceTracker<BrandingPlugin, BrandingPlugin>
    {
        BrandingServiceTracker(OsgiManager osgiManager)
        {
            super(osgiManager.getBundleContext(), BrandingPlugin.class, null);
        }

        public BrandingPlugin addingService(ServiceReference<BrandingPlugin> reference)
        {
            BrandingPlugin plugin = super.addingService(reference);
            AbstractWebConsolePlugin.setBrandingPlugin( plugin);
            return plugin;
        }

        public void removedService(ServiceReference<BrandingPlugin> reference, BrandingPlugin service)
        {
            AbstractWebConsolePlugin.setBrandingPlugin(null);
            super.removedService(reference, service);
        }

    }

    protected void bindHttpService(HttpService httpService)
    {
        // do not bind service, when we are already bound
        if (this.httpService != null)
        {
            log(LogService.LOG_DEBUG,
                "bindHttpService: Already bound to an HTTP Service, ignoring further services");
            return;
        }

        this.httpService = httpService;
        updateRegistrationState();
    }

    synchronized void registerHttpService() {
        Map<String, Object> config = getConfiguration();

        // get authentication details
        String realm = ConfigurationUtil.getProperty(config, PROP_REALM, DEFAULT_REALM);
        String userId = ConfigurationUtil.getProperty(config, PROP_USER_NAME, DEFAULT_USER_NAME);
        String password = ConfigurationUtil.getProperty(config, PROP_PASSWORD, DEFAULT_PASSWORD);

        // register the servlet and resources
        try
        {
            HttpContext httpContext = new OsgiManagerHttpContext(bundleContext, httpService,
                securityProviderTracker, userId, password, realm);

            Dictionary<String, String> servletConfig = toStringConfig(config);

            if (!httpServletRegistered) {
                // register this servlet and take note of this
                httpService.registerServlet(this.webManagerRoot, this, servletConfig,
                    httpContext);
                httpServletRegistered = true;
            }

            if (!httpResourcesRegistered) {
                // register resources and take of this
                httpService.registerResources(this.webManagerRoot + "/res", "/res",
                    httpContext);
                httpResourcesRegistered = true;
            }
        }
        catch (Exception e)
        {
            log(LogService.LOG_ERROR, "bindHttpService: Problem setting up", e);
        }
    }

    protected void unbindHttpService(HttpService httpService)
    {
        if (this.httpService != httpService)
        {
            log(LogService.LOG_DEBUG,
                "unbindHttpService: Ignoring unbind of an HttpService to which we are not registered");
            return;
        }

        unregisterHttpService();

        // drop the service reference
        this.httpService = null;
    }

    synchronized void unregisterHttpService() {
        if (httpService == null)
            return;

        if (httpResourcesRegistered)
        {
            try
            {
                httpService.unregister(this.webManagerRoot + "/res");
            }
            catch (Throwable t)
            {
                log(LogService.LOG_WARNING,
                    "unbindHttpService: Failed unregistering Resources", t);
            }
            httpResourcesRegistered = false;
        }

        if (httpServletRegistered)
        {
            try
            {
                httpService.unregister(this.webManagerRoot);
            }
            catch (Throwable t)
            {
                log(LogService.LOG_WARNING,
                    "unbindHttpService: Failed unregistering Servlet", t);
            }
            httpServletRegistered = false;
        }
    }


    private Map<String, Object> getConfiguration()
    {
        return configuration;
    }


    Map<String, Object> getDefaultConfiguration()
    {
        return defaultConfiguration;
    }


    synchronized void updateConfiguration( Dictionary<String, Object> osgiConfig )
    {
        Map<String, Object> config = new HashMap<String, Object>( this.defaultConfiguration );

        if ( osgiConfig != null )
        {
            for ( Enumeration<String> keys = osgiConfig.keys(); keys.hasMoreElements(); )
            {
                final String key = keys.nextElement();
                config.put( key, osgiConfig.get( key ) );
            }
        }

        configuration = config;

        final Object locale = config.get(PROP_LOCALE);
        configuredLocale = locale == null || locale.toString().trim().length() == 0 //
        ? null : Util.parseLocaleString(locale.toString().trim());

        logLevel = ConfigurationUtil.getProperty(config, PROP_LOG_LEVEL, DEFAULT_LOG_LEVEL);
        AbstractWebConsolePlugin.setLogLevel(logLevel);

        // default plugin page configuration
        holder.setDefaultPluginLabel(ConfigurationUtil.getProperty(config, PROP_DEFAULT_RENDER, DEFAULT_PAGE));

        // get the web manager root path
        String newWebManagerRoot = ConfigurationUtil.getProperty(config, PROP_MANAGER_ROOT, DEFAULT_MANAGER_ROOT);
        if (!newWebManagerRoot.startsWith("/")) //$NON-NLS-1$
        {
            newWebManagerRoot = "/" + newWebManagerRoot; //$NON-NLS-1$
        }

        // default category
        this.defaultCategory = ConfigurationUtil.getProperty( config, PROP_CATEGORY, DEFAULT_CATEGORY );

        // get the HTTP Service selector (and dispose tracker for later
        // recreation)
        final String newHttpServiceSelector = ConfigurationUtil.getProperty(config,
            PROP_HTTP_SERVICE_SELECTOR, DEFAULT_HTTP_SERVICE_SELECTOR);
        if (httpServiceTracker != null
            && !httpServiceTracker.isSameSelector(newHttpServiceSelector))
        {
            httpServiceTracker.close();
            httpServiceTracker = null;
        }

        // get enabled plugins
        String[] plugins = ConfigurationUtil.getStringArrayProperty(config, PROP_ENABLED_PLUGINS);
        enabledPlugins = null == plugins ? null : new HashSet<String>(Arrays.asList(plugins));
        // check for moved config manager class (see FELIX-4074)
        if ( enabledPlugins != null )
        {
            if ( enabledPlugins.remove(OLD_CONFIG_MANAGER_CLASS) )
            {
                enabledPlugins.add(NEW_CONFIG_MANAGER_CLASS);
            }
        }
        initInternalPlugins();

        // might update HTTP service registration
        HttpService httpService = this.httpService;
        if (httpService != null)
        {
            // unbind old location first
            unbindHttpService(httpService);

            // switch location
            this.webManagerRoot = newWebManagerRoot;

            // bind new location now
            bindHttpService(httpService);
        }
        else
        {
            // just set the configured location (FELIX-2034)
            this.webManagerRoot = newWebManagerRoot;
        }

        // create or recreate the HTTP service tracker with the new selector
        if (httpServiceTracker == null)
        {
            httpServiceTracker = HttpServiceTracker.create(this, newHttpServiceSelector);
            httpServiceTracker.open();
        }
    }

    private void initInternalPlugins()
    {
        for (int i = 0; i < PLUGIN_MAP.length; i++)
        {
            final String pluginClassName = PLUGIN_MAP[i++];
            final String label = PLUGIN_MAP[i];
            boolean active = holder.getPlugin(label) != null;
            boolean disabled = isPluginDisabled(pluginClassName);
            if (disabled)
            {
                if (active)
                {
                    holder.removeOsgiManagerPlugin(label);
                }
            }
            else
            {
                if (!active)
                {
                    holder.addInternalPlugin(this, pluginClassName, label);
                }
            }
        }
    }

    /**
     * Returns <code>true</code> if the list of enabled plugins is
     * configured but the plugin is not contained in that list.
     * <p>
     * This method is intended to be used only for {@link InternalPlugin#isEnabled()}
     */
    boolean isPluginDisabled(String pluginClass)
    {
        return enabledPlugins != null && !enabledPlugins.contains( pluginClass );
    }


    private Dictionary<String, String> toStringConfig( Map<String, Object> config )
    {
        Dictionary<String, String> stringConfig = new Hashtable<>();
        for ( Iterator<Map.Entry<String, Object>> ei = config.entrySet().iterator(); ei.hasNext(); )
        {
            Entry<String, Object> entry = ei.next();
            stringConfig.put( entry.getKey(), String.valueOf( entry.getValue() ) );
        }
        return stringConfig;
    }

    static Set<String> splitCommaSeparatedString(final String str) {
        if (str == null)
            return Collections.emptySet();

        final Set<String> values = new HashSet<String>();
        for (final String s : str.split(",")) {
            String trimmed = s.trim();
            if (trimmed.length() > 0) {
                values.add(trimmed);
            }
        }
        return Collections.unmodifiableSet(values);
    }

    private Map langMap;


    private final Map getLangMap()
    {
        if (null != langMap)
            return langMap;
        final Map map = new HashMap();
        final Bundle bundle = bundleContext.getBundle();
        final Enumeration e = bundle.findEntries("res/flags", null, false); //$NON-NLS-1$
        while (e != null && e.hasMoreElements())
        {
            final URL img = (URL) e.nextElement();
            final String name = FilenameUtils.getBaseName(img.getFile());
            try
            {
                final String locale = new Locale(name, "").getDisplayLanguage(); //$NON-NLS-1$
                map.put(name, null != locale ? locale : name);
            }
            catch (Throwable t)
            {
                t.printStackTrace();
                /* ignore invalid locale? */
            }
        }
        return langMap = map;
    }

    class UpdateDependenciesStateCustomizer implements ServiceTrackerCustomizer<WebConsoleSecurityProvider, WebConsoleSecurityProvider> {
        @Override
        public WebConsoleSecurityProvider addingService(ServiceReference<WebConsoleSecurityProvider> reference) {
            Object nameObj = reference.getProperty(SECURITY_PROVIDER_PROPERTY_NAME);
            if (nameObj instanceof String) {
                String name = (String) nameObj;
                registeredSecurityProviders.add(name);
                updateRegistrationState();
            }
            return bundleContext.getService(reference);
        }

        @Override
        public void modifiedService(ServiceReference<WebConsoleSecurityProvider> reference, WebConsoleSecurityProvider service) {
            removedService(reference, service);
            addingService(reference);
        }

        @Override
        public void removedService(ServiceReference<WebConsoleSecurityProvider> reference, WebConsoleSecurityProvider service) {
            Object nameObj = reference.getProperty(SECURITY_PROVIDER_PROPERTY_NAME);
            if (nameObj instanceof String) {
                String name = (String) nameObj;
                registeredSecurityProviders.remove(name);
                updateRegistrationState();
            }
        }

    }
}
