FELIX-1637 support additional CSS references in plugins:
* AbstractWebConsolePlugin extensions overwrite the getCssReferences() method
* Plain Servlet plugins provide a felix.webconsole.css service registration
property
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@818501 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
index cf190de..bba66c2 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
@@ -167,6 +167,25 @@
IOException;
+ /**
+ * 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><link></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;
+ }
+
+
protected BundleContext getBundleContext()
{
return bundleContext;
@@ -373,12 +392,14 @@
response.setCharacterEncoding( "utf-8" );
response.setContentType( "text/html" );
- PrintWriter pw = response.getWriter();
+ final PrintWriter pw = response.getWriter();
+
+ final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
String header = MessageFormat.format( getHeader(), new Object[]
- { adminTitle, getTitle(), ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT ), getLabel(),
- brandingPlugin.getFavIcon(), brandingPlugin.getMainStyleSheet(), brandingPlugin.getProductURL(),
- brandingPlugin.getProductName(), brandingPlugin.getProductImage() } );
+ { adminTitle, getTitle(), appRoot, getLabel(), brandingPlugin.getFavIcon(),
+ brandingPlugin.getMainStyleSheet(), brandingPlugin.getProductURL(), brandingPlugin.getProductName(),
+ brandingPlugin.getProductImage(), getCssLinks( appRoot ) } );
pw.println( header );
return pw;
@@ -574,10 +595,12 @@
// 2 application root path (ATTR_APP_ROOT)
// 3 console plugin label (from the URI)
// 4 branding favourite icon (BrandingPlugin.getFavIcon())
- // 5 branding favourite icon (BrandingPlugin.getMainStyleSheet())
- // 6 branding favourite icon (BrandingPlugin.getProductURL())
- // 7 branding favourite icon (BrandingPlugin.getProductName())
- // 8 branding favourite icon (BrandingPlugin.getProductImage())
+ // 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)
final String header = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
@@ -589,6 +612,7 @@
+ " <link href=\"{2}/res/ui/admin.css\" rel=\"stylesheet\" type=\"text/css\">"
+ " <link href=\"{2}{5}\" rel=\"stylesheet\" type=\"text/css\">"
+ + " {9}"
+ " <script language=\"JavaScript\">"
+ " appRoot = \"{2}\";"
@@ -624,4 +648,32 @@
+ "</html>";
return footer;
}
+
+
+ private String getCssLinks( final String appRoot )
+ {
+ // get the CSS references and return nothing if there are none
+ final String[] cssRefs = getCssReferences();
+ if ( cssRefs == null )
+ {
+ return "";
+ }
+
+ // build the CSS links from the references
+ final StringBuffer buf = new StringBuffer();
+ for ( int i = 0; i < cssRefs.length; i++ )
+ {
+ buf.append( "<link href='" );
+
+ final String cssRef = cssRefs[i];
+ if ( cssRef.startsWith( "/" ) )
+ {
+ buf.append( appRoot ).append( '/' );
+ }
+
+ buf.append( cssRef ).append( "' rel='stylesheet' type='text/css'>" );
+ }
+
+ return buf.toString();
+ }
}
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 a1b7050..20f05fe 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
@@ -32,9 +32,9 @@
* The URI address label under which the OSGi Manager plugin is called by
* the OSGi Manager (value is "felix.webconsole.label").
* <p>
- * Only {@link #SERVICE_NAME} services with this service registration
- * property set to a non-empty String values are accepted by the OSGi
- * Manager as a plugin.
+ * This service registration property must be set to a single non-empty
+ * String value. Otherwise the {@link #SERVICE_NAME Servlet} services will
+ * be ignored by the Felix Web Console and not be used as a plugin.
*/
public static final String PLUGIN_LABEL = "felix.webconsole.label";
@@ -42,15 +42,35 @@
* The title under which the OSGi Manager plugin is called by
* the OSGi Manager (value is "felix.webconsole.label").
* <p>
- * Only {@link #SERVICE_NAME} services with this service registration
- * property set to a non-empty String values are accepted by the OSGi
- * Manager as a plugin.
+ * For {@link #SERVICE_NAME Servlet} services not extending the
+ * {@link AbstractWebConsolePlugin} this property is required for the
+ * service to be used as a plugin. Otherwise the service is just ignored
+ * by the Felix Web Console.
*
* @since 2.0.0
*/
public static final String PLUGIN_TITLE = "felix.webconsole.title";
/**
+ * 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.
+ * <p>
+ * This property is expected to be a single string value, array of string
+ * values or a Collection (or Vector) of string values.
+ * <p>
+ * This service registration property is only used for plugins registered
+ * as {@link #SERVICE_NAME} services which do not extend the
+ * {@link AbstractWebConsolePlugin}. Extensions of the
+ * {@link AbstractWebConsolePlugin} should overwrite the
+ * {@link AbstractWebConsolePlugin#getCssReferences()} method to provide
+ * additional CSS resources.
+ *
+ * @since 2.0.0
+ */
+ public static final String PLUGIN_CSS_REFERENCES = "felix.webconsole.css";
+
+ /**
* The name of the request attribute providing the absolute path of the
* Web Console root (value is "felix.webconsole.appRoot"). This consists of
* the servlet context path (from <code>HttpServletRequest.getContextPath()</code>)
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/WebConsolePluginAdapter.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/WebConsolePluginAdapter.java
index 94d517d..2a79580 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/WebConsolePluginAdapter.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/WebConsolePluginAdapter.java
@@ -20,12 +20,17 @@
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.osgi.framework.ServiceReference;
/**
@@ -49,12 +54,16 @@
// the actual plugin to forward rendering requests to
private final Servlet plugin;
+ // the CSS references (null if none)
+ private final String[] cssReferences;
- public WebConsolePluginAdapter( String label, String title, Servlet plugin )
+
+ public WebConsolePluginAdapter( String label, String title, Servlet plugin, ServiceReference serviceReference )
{
this.label = label;
this.title = title;
this.plugin = plugin;
+ this.cssReferences = toStringArray( serviceReference.getProperty( WebConsoleConstants.PLUGIN_CSS_REFERENCES ) );
}
@@ -79,6 +88,17 @@
/**
+ * Returns the CSS references from the
+ * {@link WebConsoleConstants#PLUGIN_CSS_REFERENCES felix.webconsole.css}
+ * service registration property of the plugin.
+ */
+ protected String[] getCssReferences()
+ {
+ return cssReferences;
+ }
+
+
+ /**
* Call the plugin servlet's service method to render the content of this
* page.
*/
@@ -161,4 +181,45 @@
plugin.destroy();
super.destroy();
}
+
+
+ //---------- internal
+
+ private String[] toStringArray( final Object value )
+ {
+ if ( value instanceof String )
+ {
+ return new String[]
+ { ( String ) value };
+ }
+ else if ( value != null )
+ {
+ final Collection cssListColl;
+ if ( value.getClass().isArray() )
+ {
+ cssListColl = Arrays.asList( ( Object[] ) value );
+ }
+ else if ( value instanceof Collection )
+ {
+ cssListColl = ( Collection ) value;
+ }
+ else
+ {
+ cssListColl = null;
+ }
+
+ if ( cssListColl != null && !cssListColl.isEmpty() )
+ {
+ String[] entries = new String[cssListColl.size()];
+ int i = 0;
+ for ( Iterator cli = cssListColl.iterator(); cli.hasNext(); i++ )
+ {
+ entries[i] = String.valueOf( cli.next() );
+ }
+ return entries;
+ }
+ }
+
+ return null;
+ }
}
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 8d7714e..5da56b6 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
@@ -60,6 +60,9 @@
public static final String TITLE = "Configuration Status";
+ private static final String[] CSS_REFS =
+ { "res/ui/configurationrender.css" };
+
/**
* Formatter pattern to generate a relative path for the generation
* of the plain text or zip file representation of the status. The file
@@ -129,14 +132,19 @@
}
+ protected String[] getCssReferences()
+ {
+ return CSS_REFS;
+ }
+
+
protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
ConfigurationWriter pw = new HtmlConfigurationWriter( response.getWriter() );
String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
- pw.println( "<link href='" + appRoot + "/res/ui/configurationrender.css' rel='stylesheet' type='text/css'>" );
- pw.println( "<script src='" + appRoot + "/res/ui/tw-1.1.js' language='JavaScript'></script>" );
+ Util.script( pw, appRoot, "tw-1.1.js" );
Util.startScript( pw );
pw.println( " $(document).ready(function(){" );
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/LicenseServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/LicenseServlet.java
index 46a6dd4..29cdf36 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/LicenseServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/LicenseServlet.java
@@ -34,6 +34,7 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
import org.apache.felix.webconsole.internal.Util;
import org.json.JSONException;
@@ -48,6 +49,10 @@
public class LicenseServlet extends AbstractWebConsolePlugin implements OsgiManagerPlugin
{
+ private static final String[] CSS_REFS =
+ { "res/ui/license.css" };
+
+
public String getLabel()
{
return "licenses";
@@ -60,13 +65,18 @@
}
+ protected String[] getCssReferences()
+ {
+ return CSS_REFS;
+ }
+
+
protected void renderContent( HttpServletRequest req, HttpServletResponse res ) throws IOException
{
PrintWriter pw = res.getWriter();
- String appRoot = req.getContextPath() + req.getServletPath();
- pw.println( "<link href='" + appRoot + "/res/ui/license.css' rel='stylesheet' type='text/css'>" );
- pw.println( "<script src='" + appRoot + "/res/ui/license.js' language='JavaScript'></script>" );
+ final String appRoot = ( String ) req.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
+ Util.script( pw, appRoot, "license.js" );
Bundle[] bundles = getBundleContext().getBundles();
Util.sort( bundles );
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
index 06fcc52..77de81a 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
@@ -31,13 +31,18 @@
import org.apache.felix.shell.ShellService;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
+import org.apache.felix.webconsole.internal.Util;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
public class ShellServlet extends AbstractWebConsolePlugin implements OsgiManagerPlugin
{
+ private static final String[] CSS_REFS =
+ { "res/ui/shell.css" };
+
private ServiceTracker shellTracker;
@@ -109,14 +114,18 @@
}
- protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
- IOException
+ protected String[] getCssReferences()
+ {
+ return CSS_REFS;
+ }
+
+
+ protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
{
PrintWriter pw = response.getWriter();
- String appRoot = request.getContextPath() + request.getServletPath();
- pw.println( "<link href=\"" + appRoot + "/res/ui/shell.css\" rel=\"stylesheet\" type=\"text/css\" />" );
- pw.println( "<script src=\"" + appRoot + "/res/ui/shell.js\" type=\"text/javascript\"></script>" );
+ final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
+ Util.script( pw, appRoot, "shell.js" );
pw.println( "<br />" );
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
index 6590479..dd28596 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
@@ -516,7 +516,7 @@
if ( title instanceof String )
{
WebConsolePluginAdapter pluginAdapter = new WebConsolePluginAdapter( ( String ) label,
- ( String ) title, ( Servlet ) operation );
+ ( String ) title, ( Servlet ) operation, reference );
// ensure the AbstractWebConsolePlugin is correctly setup
Bundle pluginBundle = reference.getBundle();