FELIX-2570 Allow ConfigurationPrinter services to output HTML code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1022523 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/ConfigurationPrinter.java b/webconsole/src/main/java/org/apache/felix/webconsole/ConfigurationPrinter.java
index 72ffd12..c8a2d9b 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/ConfigurationPrinter.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/ConfigurationPrinter.java
@@ -42,20 +42,36 @@
      */
     String SERVICE = ConfigurationPrinter.class.getName();
 
-    /** The default mode - this printer is used in the web console and the zip.
-     * @since 3.0 */
+    /**
+     * The default mode - this printer is used in the web console and the zip.
+     *
+     * @since 3.0
+     */
     String MODE_ALWAYS = "always";
 
-    /** The web mode - this printer is used in the web console.
-     * since 3.0 */
+    /**
+     * The web mode - this printer is used in the web console.
+     * <p>
+     * Output of the configuration printer is HTML-escaped unless the
+     * {@link WebConsoleConstants#CONFIG_PRINTER_WEB_UNESCAPED} service
+     * registration property is set to <code>true</code>.
+     *
+     * @since 3.0
+     */
     String MODE_WEB = "web";
 
-    /** The zip mode - this printer is used in the zip.
-     * @since 3.0 */
+    /**
+     * The zip mode - this printer is used in the zip.
+     *
+     * @since 3.0
+     */
     String MODE_ZIP = "zip";
 
-    /** The txt mode - this printer is used in the txt.
-     * @since 3.0 */
+    /**
+     * The txt mode - this printer is used in the txt.
+     *
+     * @since 3.0
+     */
     String MODE_TXT = "txt";
 
     /**
@@ -64,6 +80,7 @@
      * {@link #MODE_ALWAYS} is used.
      * The value of this property is either a single string or an
      * array of strings.
+     *
      * @since 3.0
      * @deprecated Use {@link WebConsoleConstants#CONFIG_PRINTER_MODES}
      */
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
index e08f4d0..94cbe2b 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
@@ -18,9 +18,6 @@
  */
 package org.apache.felix.webconsole;
 
-import java.util.Locale;
-import java.util.Map;
-
 /**
  * WebConsoleConstants provides some common constants that are used by plugin
  * developers.
@@ -73,11 +70,23 @@
      * If a service has a {@link #PLUGIN_LABEL}, {@link #PLUGIN_TITLE} and
      * this property, it is treated as a configuration printer servce.
      *
-     * @since 3.1.4
+     * @since 3.1.2; Web Console Bundle 3.1.4
      */
     public static final String CONFIG_PRINTER_MODES = "felix.webconsole.configprinter.modes";
 
     /**
+     * Name of the optional service registration property indicating that a
+     * {@link ConfigurationPrinter} service will provide HTML output when used
+     * in {@link ConfigurationPrinter#MODE_WEB web} mode. If this property is
+     * set to <code>true</code> the configuration printer is expected to
+     * generate HTML output which will not be escaped. Otheriwse output in web
+     * mode is escaped for plain text use.
+     *
+     * @since 3.1.2; Web Console Bundle 3.1.4
+     */
+    public static final String CONFIG_PRINTER_WEB_UNESCAPED = "felix.webconsole.configprinter.web.unescaped";
+
+    /**
      * The name of the service registration properties providing references
      * to addition CSS files that should be loaded when rendering the header
      * for a registered plugin.
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationPrinterAdapter.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationPrinterAdapter.java
index b44be99..fecafe0 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationPrinterAdapter.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationPrinterAdapter.java
@@ -35,6 +35,7 @@
     public String title;
     public String label;
     private final String[] modes;
+    private final boolean escapeHtml;
     private Method modeAwarePrintMethod;
     private Method printMethod;
     private Method attachmentMethod;
@@ -95,12 +96,27 @@
         if ( cfgPrinter != null )
         {
             Object label =  ref.getProperty( WebConsoleConstants.PLUGIN_LABEL);
+            boolean webUnescaped;
+            Object ehObj = ref.getProperty( WebConsoleConstants.CONFIG_PRINTER_WEB_UNESCAPED );
+            if ( ehObj instanceof Boolean )
+            {
+                webUnescaped = ( ( Boolean ) ehObj ).booleanValue();
+            }
+            else if ( ehObj instanceof String )
+            {
+                webUnescaped = Boolean.valueOf( ( String ) ehObj ).booleanValue();
+            }
+            else
+            {
+                webUnescaped = false;
+            }
             return new ConfigurationPrinterAdapter(
                     cfgPrinter,
                     printMethod,
                     title,
                     (label instanceof String ? (String)label : null),
-                    modes);
+                    modes,
+                    !webUnescaped);
         }
         return null;
     }
@@ -109,11 +125,13 @@
             final Method printMethod,
             final String title,
             final String label,
-            final Object modes )
+            final Object modes,
+            final boolean escapeHtml )
     {
         this.printer = printer;
         this.title = title;
         this.label = label;
+        this.escapeHtml = escapeHtml;
         if ( printMethod != null )
         {
             if ( printMethod.getParameterTypes().length > 1 )
@@ -182,6 +200,11 @@
         return false;
     }
 
+    public boolean escapeHtml()
+    {
+        return escapeHtml;
+    }
+
     public final void printConfiguration( final PrintWriter pw,
             final String mode )
     {
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
index 73593a9..7fd85a2 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ConfigurationRender.java
@@ -156,7 +156,7 @@
 
             final String name = getRequestedPrinterName(request);
 
-            ConfigurationWriter pw = new HtmlConfigurationWriter( response.getWriter() );
+            HtmlConfigurationWriter pw = new HtmlConfigurationWriter( response.getWriter() );
             pw.println ( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" );
             pw.println ( "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" );
             pw.println ( "<html xmlns=\"http://www.w3.org/1999/xhtml\">" );
@@ -168,7 +168,9 @@
                 for (Iterator i = printers.iterator(); i.hasNext();)
                 {
                     final ConfigurationPrinterAdapter desc = (ConfigurationPrinterAdapter) i.next();
+                    pw.enableFilter( desc.escapeHtml() );
                     printConfigurationPrinter( pw, desc, ConfigurationPrinter.MODE_WEB );
+                    pw.enableFilter( false );
                     pw.println( "</div></body></html>" );
                     return;
                 }
@@ -226,7 +228,7 @@
         for (Iterator i = printers.iterator(); i.hasNext();)
         {
             final ConfigurationPrinterAdapter desc = (ConfigurationPrinterAdapter) i.next();
-            if ( desc.match(ConfigurationPrinter.MODE_WEB) )
+            if ( desc.match( ConfigurationPrinter.MODE_WEB ) )
             {
                 final String label = desc.label;
                 final String title = desc.title;
@@ -487,15 +489,19 @@
         }
 
 
+        void enableFilter( final boolean doFilter )
+        {
+            this.doFilter = doFilter;
+        }
+
+
         public void title( String title )
         {
-            doFilter = true;
         }
 
 
         public void end()
         {
-            doFilter = false;
         }