/*
 * 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;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.webconsole.internal.servlet.OsgiManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.log.LogService;


/**
 * The Web Console can be extended by registering an OSGi service for the interface
 * {@link javax.servlet.Servlet} with the service property
 * <code>felix.webconsole.label</code> set to the label (last segment in the URL)
 * of the page. The respective service is called a Web Console Plugin or a plugin
 * for short.
 *
 * To help rendering the response the Apache Felix Web Console bundle provides two
 * options. One of the options is to extend the AbstractWebConsolePlugin overwriting
 * the {@link #renderContent(HttpServletRequest, HttpServletResponse)} method.
 */
public abstract class AbstractWebConsolePlugin extends HttpServlet
{

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

    /** The name of the request attribute containing the map of FileItems from the POST request */
    public static final String ATTR_FILEUPLOAD = "org.apache.felix.webconsole.fileupload"; //$NON-NLS-1$
    
    /** 
     * The name of the request attribute containing a {@link java.io.File} - upload repository path used by
     * {@link org.apache.commons.fileupload.disk.DiskFileItemFactory}.<p>
     * 
     * The Web Console plugin, that utilizes file upload capabilities of the web console SHOULD:
     * <ol>
     * <li>Obtain the file using {@link org.osgi.framework.BundleContext#getDataFile(String)}
     * <li>Set the file as request attribute
     * <li>Use {@link WebConsoleUtil#getParameter(HttpServletRequest, String)} to obtain the file(s)
     * </ol>
     * 
     * Without setting this attribute, your plugin will not work if there is a security manager enabled.
     * It is guaranteed, that your plugin has permissions to read/write/delete files to the location, 
     * provided by the bundle context.
     */
    public static final String ATTR_FILEUPLOAD_REPO = "org.apache.felix.webconsole.fileupload.repo"; //$NON-NLS-1$

    /**
     * Web Console Plugin typically consists of servlet and resources such as images,
     * scripts or style sheets.
     *
     * To load resources, a Resource Provider is used. The resource provider is an object,
     * that provides a method which name is specified by this constants and it is
     * 'getResource'.
     *
     *  @see #getResourceProvider()
     */
    public static final String GET_RESOURCE_METHOD_NAME = "getResource"; //$NON-NLS-1$

    /**
     * The header fragment read from the templates/main_header.html file
     */
    private static String HEADER;

    /**
     * The footer fragment read from the templates/main_footer.html file
     */
    private static String FOOTER;

    /**
     * The reference to the getResource method provided by the
     * {@link #getResourceProvider()}. This is <code>null</code> if there is
     * none or before the first check if there is one.
     *
     * @see #getGetResourceMethod()
     */
    private Method getResourceMethod;

    /**
     * flag indicating whether the getResource method has already been looked
     * up or not. This prevens the {@link #getGetResourceMethod()} method from
     * repeatedly looking up the resource method on plugins which do not have
     * one.
     */
    private boolean getResourceMethodChecked;

    private BundleContext bundleContext;

    private static BrandingPlugin brandingPlugin = DefaultBrandingPlugin.getInstance();

    private static int logLevel;


    //---------- HttpServlet Overwrites ----------------------------------------

    /**
     * Returns the title for this plugin as returned by {@link #getTitle()}
     *
     * @see javax.servlet.GenericServlet#getServletName()
     */
    public String getServletName()
    {
        return getTitle();
    }


    /**
     * This method should return category string which will be used to render
     * the plugin in the navigation menu. Default implementation returns null,
     * which will result in the plugin link rendered as top level menu item.
     * Concrete implementations wishing to be rendered as a sub-menu item under
     * a category should override this method and return a string or define
     * <code>felix.webconsole.category</code> OSGi property. Currently only
     * single level categories are supported. So, this should be a simple
     * String.
     *
     * @return category
     */
    public String getCategory()
    {
        return null;
    }


    /**
     * Renders the web console page for the request. This consist of the
     * following five parts called in order:
     * <ol>
     * <li>Send back a requested resource
     * <li>{@link #startResponse(HttpServletRequest, HttpServletResponse)}</li>
     * <li>{@link #renderTopNavigation(HttpServletRequest, PrintWriter)}</li>
     * <li>{@link #renderContent(HttpServletRequest, HttpServletResponse)}</li>
     * <li>{@link #endResponse(PrintWriter)}</li>
     * </ol>
     * <p>
     * <b>Note</b>: If a resource is sent back for the request only the first
     * step is executed. Otherwise the first step is a null-operation actually
     * and the latter four steps are executed in order.
     * <p>
     * If the {@link #isHtmlRequest(HttpServletRequest)} method returns
     * <code>false</code> only the
     * {@link #renderContent(HttpServletRequest, HttpServletResponse)} method is
     * called.
     *
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
     *      javax.servlet.http.HttpServletResponse)
     */
    protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
        IOException
    {
        if ( !spoolResource( request, response ) )
        {
            // detect if this is an html request
            if ( isHtmlRequest(request) )
            {
                // start the html response, write the header, open body and main div
                PrintWriter pw = startResponse( request, response );

                // render top navigation
                renderTopNavigation( request, pw );

                // wrap content in a separate div
                pw.println( "<div id='content'>" ); //$NON-NLS-1$
                renderContent( request, response );
                pw.println( "</div>" ); //$NON-NLS-1$

                // close the main div, body, and html
                endResponse( pw );
            }
            else
            {
                renderContent( request, response );
            }
        }
    }

    /**
     * Detects whether this request is intended to have the headers and
     * footers of this plugin be rendered or not. This method always returns
     * <code>true</code> and may be overwritten by plugins to detect
     * from the actual request, whether or not to render the header and
     * footer.
     *
     * @param request the original request passed from the HTTP server
     * @return <code>true</code> if the page should have headers and footers rendered
     */
    protected boolean isHtmlRequest( final HttpServletRequest request )
    {
        return true;
    }


    //---------- AbstractWebConsolePlugin API ----------------------------------

    /**
     * This method is called from the Felix Web Console to ensure the
     * AbstractWebConsolePlugin is correctly setup.
     *
     * It is called right after the Web Console receives notification for
     * plugin registration.
     *
     * @param bundleContext the context of the plugin bundle
     */
    public void activate( BundleContext bundleContext )
    {
        this.bundleContext = bundleContext;
    }


    /**
     * This method is called, by the Web Console to de-activate the plugin and release
     * all used resources.
     */
    public void deactivate()
    {
        this.bundleContext = null;
    }


    /**
     * This method is used to render the content of the plug-in. It is called internally
     * from the Web Console.
     *
     * @param req the HTTP request send from the user
     * @param res the HTTP response object, where to render the plugin data.
     * @throws IOException if an input or output error is
     *  detected when the servlet handles the request
     * @throws ServletException  if the request for the GET
     *  could not be handled
     */
    protected abstract void renderContent( HttpServletRequest req, HttpServletResponse res ) throws ServletException,
        IOException;

    /**
     * Retrieves the label. This is the last component in the servlet path.
     *
     * This method MUST be overridden, if the {@link #AbstractWebConsolePlugin()}
     * constructor is used.
     *
     * @return the label.
     */
    public abstract String getLabel();

    /**
     * Retrieves the title of the plug-in. It is displayed in the page header
     * and is also included in the title of the HTML document.
     *
     * This method MUST be overridden, if the {@link #AbstractWebConsolePlugin()}
     * constructor is used.
     *
     * @return the plugin title.
     */
    public abstract String getTitle();

    /**
     * Returns a list of CSS reference paths or <code>null</code> if no
     * additional CSS files are provided by the plugin.
     * <p>
     * The result is an array of strings which are used as the value of
     * the <code>href</code> attribute of the <code>&lt;link&gt;</code> elements
     * placed in the head section of the HTML generated. If the reference is
     * a relative path, it is turned into an absolute path by prepending the
     * value of the {@link WebConsoleConstants#ATTR_APP_ROOT} request attribute.
     *
     * @return The list of additional CSS files to reference in the head
     *      section or <code>null</code> if no such CSS files are required.
     */
    protected String[] getCssReferences()
    {
        return null;
    }

    /**
     * Returns the <code>BundleContext</code> with which this plugin has been
     * activated. If the plugin has not be activated by calling the
     * {@link #activate(BundleContext)} method, this method returns
     * <code>null</code>.
     *
     * @return the bundle context or <code>null</code> if the bundle is not activated.
     */
    protected BundleContext getBundleContext()
    {
        return bundleContext;
    }


    /**
     * Returns the <code>Bundle</code> pertaining to the
     * {@link #getBundleContext() bundle context} with which this plugin has
     * been activated. If the plugin has not be activated by calling the
     * {@link #activate(BundleContext)} method, this method returns
     * <code>null</code>.
     *
     * @return the bundle or <code>null</code> if the plugin is not activated.
     */
    public final Bundle getBundle()
    {
        final BundleContext bundleContext = getBundleContext();
        return ( bundleContext != null ) ? bundleContext.getBundle() : null;
    }

    /**
     * Returns the object which might provide resources. The class of this
     * object is used to find the <code>getResource</code> method.
     * <p>
     * This method may be overwritten by extensions. This base class
     * implementation returns this instance.
     *
     * @return The resource provider object or <code>null</code> if no
     *      resources will be provided by this plugin.
     */
    protected Object getResourceProvider()
    {
        return this;
    }


    /**
     * Returns a method which is called on the
     * {@link #getResourceProvider() resource provider} class to return an URL
     * to a resource which may be spooled when requested. The method has the
     * following signature:
     * <pre>
     * [modifier] URL getResource(String path);
     * </pre>
     * Where the <i>[modifier]</i> may be <code>public</code>, <code>protected</code>
     * or <code>private</code> (if the method is declared in the class of the
     * resource provider). It is suggested to use the <code>private</code>
     * modifier if the method is declared in the resource provider class or
     * the <code>protected</code> modifier if the method is declared in a
     * base class of the resource provider.
     *
     * @return The <code>getResource(String)</code> method or <code>null</code>
     *      if the {@link #getResourceProvider() resource provider} is
     *      <code>null</code> or does not provide such a method.
     */
    private final Method getGetResourceMethod()
    {
        // return what we know of the getResourceMethod, if we already checked
        if (getResourceMethodChecked) {
            return getResourceMethod;
        }

        Method tmpGetResourceMethod = null;
        Object resourceProvider = getResourceProvider();
        if ( resourceProvider != null )
        {
            try
            {
                Class cl = resourceProvider.getClass();
                while ( tmpGetResourceMethod == null && cl != Object.class )
                {
                    Method[] methods = cl.getDeclaredMethods();
                    for ( int i = 0; i < methods.length; i++ )
                    {
                        Method m = methods[i];
                        if ( GET_RESOURCE_METHOD_NAME.equals( m.getName() ) && m.getParameterTypes().length == 1
                            && m.getParameterTypes()[0] == String.class && m.getReturnType() == URL.class )
                        {
                            // ensure modifier is protected or public or the private
                            // method is defined in the plugin class itself
                            int mod = m.getModifiers();
                            if ( Modifier.isProtected( mod ) || Modifier.isPublic( mod )
                                || ( Modifier.isPrivate( mod ) && cl == resourceProvider.getClass() ) )
                            {
                                m.setAccessible( true );
                                tmpGetResourceMethod = m;
                                break;
                            }
                        }
                    }
                    cl = cl.getSuperclass();
                }
            }
            catch ( Throwable t )
            {
                tmpGetResourceMethod = null;
            }
        }

        // set what we have found and prevent future lookups
        getResourceMethod = tmpGetResourceMethod;
        getResourceMethodChecked = true;

        // now also return the method
        return getResourceMethod;
    }


    /**
     * 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> paramter 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
     */
    public 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> paramter 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.
     *
     * @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
     */
    public 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 );
            }
        }
    }
    
    /**
     * If the request addresses a resource which may be served by the
     * <code>getResource</code> method of the
     * {@link #getResourceProvider() resource provider}, this method serves it
     * and returns <code>true</code>. Otherwise <code>false</code> is returned.
     * <code>false</code> is also returned if the resource provider has no
     * <code>getResource</code> method.
     * <p>
     * If <code>true</code> is returned, the request is considered complete and
     * request processing terminates. Otherwise request processing continues
     * with normal plugin rendering.
     *
     * @param request The request object
     * @param response The response object
     * @return <code>true</code> if the request causes a resource to be sent back.
     *
     * @throws IOException If an error occurs accessing or spooling the resource.
     */
    private final boolean spoolResource(final HttpServletRequest request, 
        final HttpServletResponse response) throws IOException
    {
        try
        {
            // We need to call spoolResource0 in privileged block because it uses reflection, which
            // requires the following set of permissions:
            // (java.lang.RuntimePermission "getClassLoader")
            // (java.lang.RuntimePermission "accessDeclaredMembers")
            // (java.lang.reflect.ReflectPermission "suppressAccessChecks")
            // See also https://issues.apache.org/jira/browse/FELIX-4652
            final Boolean ret = AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>()
            {

                public Boolean run() throws Exception
                {
                    return spoolResource0(request, response) ? Boolean.TRUE : Boolean.FALSE;
                }
            });
            return ret.booleanValue();
        }
        catch (PrivilegedActionException e)
        {
            final Exception x = e.getException();
            throw x instanceof IOException ? (IOException) x : new IOException(
                x.toString());
        }
    }

    final boolean spoolResource0( HttpServletRequest request, HttpServletResponse response ) throws IOException
    {
        // no resource if no resource accessor
        Method getResourceMethod = getGetResourceMethod();
        if ( getResourceMethod == null )
        {
            return false;
        }

        String pi = request.getPathInfo();
        try
        {

            // check for a resource, fail if none
            URL url = ( URL ) getResourceMethod.invoke( getResourceProvider(), new Object[]
                { pi } );
            if ( url == null ) {
                return false;
            }

            // open the connection and the stream (we use the stream to be able
            // to at least hint to close the connection because there is no
            // method to explicitly close the conneciton, unfortunately)
            URLConnection connection = url.openConnection();
            try ( InputStream ins = connection.getInputStream()) {
                // FELIX-2017 Equinox may return an URL for a non-existing
                // resource but then (instead of throwing) return null on
                // getInputStream. We should account for this situation and
                // just assume a non-existing resource in this case.
                if (ins == null) {
                    return false;
                }

                // check whether we may return 304/UNMODIFIED
                long lastModified = connection.getLastModified();
                if ( lastModified > 0 )
                {
                    long ifModifiedSince = request.getDateHeader( "If-Modified-Since" ); //$NON-NLS-1$
                    if ( ifModifiedSince >= ( lastModified / 1000 * 1000 ) )
                    {
                        // Round down to the nearest second for a proper compare
                        // A ifModifiedSince of -1 will always be less
                        response.setStatus( HttpServletResponse.SC_NOT_MODIFIED );

                        return true;
                    }

                    // have to send, so set the last modified header now
                    response.setDateHeader( "Last-Modified", lastModified ); //$NON-NLS-1$
                }

                // describe the contents
                response.setContentType( getServletContext().getMimeType( pi ) );
                response.setIntHeader( "Content-Length", connection.getContentLength() ); //$NON-NLS-1$

                // spool the actual contents
                OutputStream out = response.getOutputStream();
                byte[] buf = new byte[2048];
                int rd;
                while ( ( rd = ins.read( buf ) ) >= 0 )
                {
                    out.write( buf, 0, rd );
                }

                // over and out ...
                return true;
            }

        } catch ( IllegalAccessException | InvocationTargetException ignore ) {
            // log or throw ???
        }

        return false;
    }


    /**
     * This method is responsible for generating the top heading of the page.
     *
     * @param request the HTTP request coming from the user
     * @param response the HTTP response, where data is rendered
     * @return the writer that was used for generating the response.
     * @throws IOException on I/O error
     * @see #endResponse(PrintWriter)
     */
    protected PrintWriter startResponse( HttpServletRequest request, HttpServletResponse response ) throws IOException
    {
        response.setCharacterEncoding( "utf-8" ); //$NON-NLS-1$
        response.setContentType( "text/html" ); //$NON-NLS-1$

        final PrintWriter pw = response.getWriter();

        final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );

        // support localization of the plugin title
        String title = getTitle();
        if ( title.startsWith( "%" ) ) //$NON-NLS-1$
        {
            title = "${" + title.substring( 1 ) + "}"; //$NON-NLS-1$ //$NON-NLS-2$
        }

        VariableResolver resolver = WebConsoleUtil.getVariableResolver(request);
        if (resolver instanceof DefaultVariableResolver) {
            DefaultVariableResolver r = (DefaultVariableResolver) resolver;
            r.put("head.title", title); //$NON-NLS-1$
            r.put("head.label", getLabel()); //$NON-NLS-1$
            r.put("head.cssLinks", getCssLinks(appRoot)); //$NON-NLS-1$
            r.put("brand.name", brandingPlugin.getBrandName()); //$NON-NLS-1$
            r.put("brand.product.url", brandingPlugin.getProductURL()); //$NON-NLS-1$
            r.put("brand.product.name", brandingPlugin.getProductName()); //$NON-NLS-1$
            r.put("brand.product.img", toUrl( brandingPlugin.getProductImage(), appRoot )); //$NON-NLS-1$
            r.put("brand.favicon", toUrl( brandingPlugin.getFavIcon(), appRoot )); //$NON-NLS-1$
            r.put("brand.css", toUrl( brandingPlugin.getMainStyleSheet(), appRoot )); //$NON-NLS-1$
        }
        pw.println( getHeader() );

        return pw;
    }


    /**
     * This method is called to generate the top level links with the available plug-ins.
     *
     * @param request the HTTP request coming from the user
     * @param pw the writer, where the HTML data is rendered
     */
    protected void renderTopNavigation( HttpServletRequest request, PrintWriter pw )
    {
        // assume pathInfo to not be null, else this would not be called
        String current = request.getPathInfo();
        int slash = current.indexOf( "/", 1 ); //$NON-NLS-1$
        if ( slash < 0 )
        {
            slash = current.length();
        }
        current = current.substring( 1, slash );

        String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );

        Map menuMap = ( Map ) request.getAttribute( OsgiManager.ATTR_LABEL_MAP_CATEGORIZED );
        this.renderMenu( menuMap, appRoot, pw );

        // render lang-box
        Map langMap = (Map) request.getAttribute(WebConsoleConstants.ATTR_LANG_MAP);
        if (null != langMap && !langMap.isEmpty())
        {
            // determine the currently selected locale from the request and fail-back
            // to the default locale if not set
            // if locale is missing in locale map, the default 'en' locale is used
            Locale reqLocale = request.getLocale();
            String locale = null != reqLocale ? reqLocale.getLanguage()
                : Locale.getDefault().getLanguage();
            if (!langMap.containsKey(locale))
            {
                locale = Locale.getDefault().getLanguage();
            }
            if (!langMap.containsKey(locale))
            {
                locale = "en"; //$NON-NLS-1$
            }

            pw.println("<div id='langSelect'>"); //$NON-NLS-1$
            pw.println(" <span>"); //$NON-NLS-1$
            printLocaleElement(pw, appRoot, locale, langMap.get(locale));
            pw.println(" </span>"); //$NON-NLS-1$
            pw.println(" <span class='flags ui-helper-hidden'>"); //$NON-NLS-1$
            for (Iterator li = langMap.keySet().iterator(); li.hasNext();)
            {
                // <img src="us.gif" alt="en" title="English"/>
                final Object l = li.next();
                if (!l.equals(locale))
                {
                    printLocaleElement(pw, appRoot, l, langMap.get(l));
                }
            }

            pw.println(" </span>"); //$NON-NLS-1$
            pw.println("</div>"); //$NON-NLS-1$
        }
    }


    protected void renderMenu( Map menuMap, String appRoot, PrintWriter pw )
    {
        if ( menuMap != null )
        {
            SortedMap categoryMap = sortMenuCategoryMap( menuMap, appRoot );
            pw.println( "<ul id=\"navmenu\">" );
            renderSubmenu( categoryMap, appRoot, pw, 0 );
            pw.println("<li class=\"logoutButton navMenuItem-0\">");
            pw.println("<a href=\"" + appRoot + "/logout\">${logout}</a>");
            pw.println("</li>");
            pw.println( "</ul>" );
        }
    }


    private void renderMenu( Map menuMap, String appRoot, PrintWriter pw, int level )
    {
        pw.println( "<ul class=\"navMenuLevel-" + level + "\">" );
        renderSubmenu( menuMap, appRoot, pw, level );
        pw.println( "</ul>" );
    }


    private void renderSubmenu( Map menuMap, String appRoot, PrintWriter pw, int level )
    {
        String liStyleClass = " class=\"navMenuItem-" + level + "\"";
        Iterator itr = menuMap.keySet().iterator();
        while ( itr.hasNext() )
        {
            String key = ( String ) itr.next();
            MenuItem menuItem = ( MenuItem ) menuMap.get( key );
            pw.println( "<li" + liStyleClass + ">" + menuItem.getLink() );
            Map subMenu = menuItem.getSubMenu();
            if ( subMenu != null )
            {
                renderMenu( subMenu, appRoot, pw, level + 1 );
            }
            pw.println( "</li>" );
        }
    }


    private static final void printLocaleElement( PrintWriter pw, String appRoot, Object langCode, Object langName )
    {
        pw.print("  <img src='"); //$NON-NLS-1$
        pw.print(appRoot);
        pw.print("/res/flags/"); //$NON-NLS-1$
        pw.print(langCode);
        pw.print(".gif' alt='"); //$NON-NLS-1$
        pw.print(langCode);
        pw.print("' title='"); //$NON-NLS-1$
        pw.print(langName);
        pw.println("'/>"); //$NON-NLS-1$
    }

    /**
     * This method is responsible for generating the footer of the page.
     *
     * @param pw the writer, where the HTML data is rendered
     * @see #startResponse(HttpServletRequest, HttpServletResponse)
     */
    protected void endResponse( PrintWriter pw )
    {
        pw.println(getFooter());
    }


    /**
     * An utility method, that is used to filter out simple parameter from file
     * parameter when multipart transfer encoding is used.
     *
     * This method processes the request and sets a request attribute
     * {@link #ATTR_FILEUPLOAD}. The attribute value is a {@link Map}
     * where the key is a String specifying the field name and the value
     * is a {@link org.apache.commons.fileupload.FileItem}.
     *
     * @param request the HTTP request coming from the user
     * @param name the name of the parameter
     * @return if not multipart transfer encoding is used - the value is the
     *  parameter value or <code>null</code> if not set. If multipart is used,
     *  and the specified parameter is field - then the value of the parameter
     *  is returned.
     * @deprecated use {@link WebConsoleUtil#getParameter(HttpServletRequest, String)}
     */
    public static final String getParameter( HttpServletRequest request, String name )
    {
        return WebConsoleUtil.getParameter(request, name);
    }

    /**
     * Utility method to handle relative redirects.
     * Some application servers like Web Sphere handle relative redirects differently
     * therefore we should make an absolute URL before invoking send redirect.
     *
     * @param request the HTTP request coming from the user
     * @param response the HTTP response, where data is rendered
     * @param redirectUrl the redirect URI.
     * @throws IOException If an input or output exception occurs
     * @throws IllegalStateException   If the response was committed or if a partial
     *  URL is given and cannot be converted into a valid URL
     * @deprecated use {@link WebConsoleUtil#sendRedirect(HttpServletRequest, HttpServletResponse, String)}
     */
    protected void sendRedirect(final HttpServletRequest request,
                                final HttpServletResponse response,
                                String redirectUrl) throws IOException {
        WebConsoleUtil.sendRedirect(request, response, redirectUrl);
    }

    /**
     * Returns the {@link BrandingPlugin} currently used for web console
     * branding.
     *
     * @return the brandingPlugin
     */
    public static BrandingPlugin getBrandingPlugin() {
        return AbstractWebConsolePlugin.brandingPlugin;
    }

    /**
     * Sets the {@link BrandingPlugin} to use globally by all extensions of
     * this class for branding.
     * <p>
     * Note: This method is intended to be used internally by the Web Console
     * to update the branding plugin to use.
     *
     * @param brandingPlugin the brandingPlugin to set
     */
    public static final void setBrandingPlugin(BrandingPlugin brandingPlugin) {
        if(brandingPlugin == null){
            AbstractWebConsolePlugin.brandingPlugin = DefaultBrandingPlugin.getInstance();
        } else {
            AbstractWebConsolePlugin.brandingPlugin = brandingPlugin;
        }
    }


    /**
     * Sets the log level to be applied for calls to the {@link #log(int, String)}
     * and {@link #log(int, String, Throwable)} methods.
     * <p>
     * Note: This method is intended to be used internally by the Web Console
     * to update the log level according to the Web Console configuration.
     *
     * @param logLevel the maximum allowed log level. If message is logged with
     *        lower level it will not be forwarded to the logger.
     */
    public static final void setLogLevel( int logLevel )
    {
        AbstractWebConsolePlugin.logLevel = logLevel;
    }


    private final String getHeader()
    {
        // MessageFormat pattern place holder
        //  0 main title (brand name)
        //  1 console plugin title
        //  2 application root path (ATTR_APP_ROOT)
        //  3 console plugin label (from the URI)
        //  4 branding favourite icon (BrandingPlugin.getFavIcon())
        //  5 branding main style sheet (BrandingPlugin.getMainStyleSheet())
        //  6 branding product URL (BrandingPlugin.getProductURL())
        //  7 branding product name (BrandingPlugin.getProductName())
        //  8 branding product image (BrandingPlugin.getProductImage())
        //  9 additional HTML code to be inserted into the <head> section
        //    (for example plugin provided CSS links)
        if ( HEADER == null )
        {
            HEADER = readTemplateFile( AbstractWebConsolePlugin.class, "/templates/main_header.html" ); //$NON-NLS-1$
        }
        return HEADER;
    }


    private final String getFooter()
    {
        if ( FOOTER == null )
        {
            FOOTER = readTemplateFile( AbstractWebConsolePlugin.class, "/templates/main_footer.html" ); //$NON-NLS-1$
        }
        return FOOTER;
    }

    /**
     * Reads the <code>templateFile</code> as a resource through the class
     * loader of this class converting the binary data into a string using
     * UTF-8 encoding.
     * <p>
     * If the template file cannot read into a string and an exception is
     * caused, the exception is logged and an empty string returned.
     *
     * @param templateFile The absolute path to the template file to read.
     * @return The contents of the template file as a string or and empty
     *      string if the template file fails to be read.
     *
     * @throws NullPointerException if <code>templateFile</code> is
     *      <code>null</code>
     * @throws RuntimeException if an <code>IOException</code> is thrown reading
     *      the template file into a string. The exception provides the
     *      exception thrown as its cause.
     */
    protected final String readTemplateFile( final String templateFile ) {
        return readTemplateFile( getClass(), templateFile );
    }

    private final String readTemplateFile( final Class clazz, final String templateFile) {
        
        try(InputStream templateStream = clazz.getResourceAsStream( templateFile )) {
            if ( templateStream != null ) {
                try ( final StringWriter w = new StringWriter()) {
                    final byte[] buf = new byte[2048];
                    int l;
                    while ( ( l = templateStream.read(buf)) > 0 ) {
                        w.write(new String(buf, 0, l, StandardCharsets.UTF_8));
                    }
                    String str = w.toString();
                    switch ( str.charAt(0) )
                    { // skip BOM
                        case 0xFEFF: // UTF-16/UTF-32, big-endian
                        case 0xFFFE: // UTF-16, little-endian
                        case 0xEFBB: // UTF-8
                            return str.substring(1);
                    }
                    return str;
                    }
            }
        }
        catch ( IOException e )
        {
            // don't use new Exception(message, cause) because cause is 1.4+
            throw new RuntimeException( "readTemplateFile: Error loading " + templateFile + ": " + e ); //$NON-NLS-1$ //$NON-NLS-2$
        }

        // template file does not exist, return an empty string
        log( LogService.LOG_ERROR, "readTemplateFile: File '" + templateFile + "' not found through class " + clazz ); //$NON-NLS-1$ //$NON-NLS-2$
        return ""; //$NON-NLS-1$
    }


    private final String getCssLinks( final String appRoot )
    {
        // get the CSS references and return nothing if there are none
        final String[] cssRefs = getCssReferences();
        if ( cssRefs == null )
        {
            return ""; //$NON-NLS-1$
        }

        // build the CSS links from the references
        final StringBuffer buf = new StringBuffer();
        for ( int i = 0; i < cssRefs.length; i++ )
        {
            buf.append( "<link href='" ); //$NON-NLS-1$
            buf.append( toUrl( cssRefs[i], appRoot ) );
            buf.append( "' rel='stylesheet' type='text/css' />" ); //$NON-NLS-1$
        }

        return buf.toString();
    }


    /**
     * If the <code>url</code> starts with a slash, it is considered an absolute
     * path (relative URL) which must be prefixed with the Web Console
     * application root path. Otherwise the <code>url</code> is assumed to
     * either be a relative path or an absolute URL, both must not be prefixed.
     *
     * @param url The url path to optionally prefix with the application root
     *          path
     * @param appRoot The application root path to optionally put in front of
     *          the url.
     * @throws NullPointerException if <code>url</code> is <code>null</code>.
     */
    private static final String toUrl( final String url, final String appRoot )
    {
        if ( url.startsWith( "/" ) ) //$NON-NLS-1$
        {
            return appRoot + url;
        }
        return url;
    }


    private SortedMap sortMenuCategoryMap( Map map, String appRoot )
    {
        SortedMap sortedMap = new TreeMap<>( String.CASE_INSENSITIVE_ORDER );
        Iterator keys = map.keySet().iterator();
        while ( keys.hasNext() )
        {
            String key = ( String ) keys.next();
            if ( key.startsWith( "category." ) )
            {
                SortedMap categoryMap = sortMenuCategoryMap( ( Map ) map.get( key ), appRoot );
                String title = key.substring( key.indexOf( '.' ) + 1 );
                if ( sortedMap.containsKey( title ) )
                {
                    ( ( MenuItem ) sortedMap.get( title ) ).setSubMenu( categoryMap );
                }
                else
                {
                    String link = "<a href=\"#\">" + title + "</a>";
                    MenuItem menuItem = new MenuItem( link, categoryMap );
                    sortedMap.put( title, menuItem );
                }
            }
            else
            {
                String title = ( String ) map.get( key );
                String link = "<a href=\"" + appRoot + "/" + key + "\">" + title + "</a>";
                if ( sortedMap.containsKey( title ) )
                {
                    ( ( MenuItem ) sortedMap.get( title ) ).setLink( link );
                }
                else
                {
                    MenuItem menuItem = new MenuItem( link );
                    sortedMap.put( title, menuItem );
                }
            }

        }
        return sortedMap;
    }

    private static class MenuItem
    {
    private String link;
        private Map subMenu;


        public MenuItem( String link )
        {
            this.link = link;
        }


        public MenuItem( String link, Map subMenu )
        {
            super();
            this.link = link;
            this.subMenu = subMenu;
        }


        public String getLink()
        {
            return link;
        }


        public void setLink( String link )
        {
            this.link = link;
        }


        public Map getSubMenu()
        {
            return subMenu;
        }


        public void setSubMenu( Map subMenu )
        {
            this.subMenu = subMenu;
        }
    }
}
