Extending the Apache Felix Web Console

The Apache Felix Web Console is extensible in various ways.

Providing Web Console Plugins

The Web Console can be extended by registering an OSGi service for the interface jakarta.servlet.Servlet. The respective service is called a Web Console Plugin or a plugin for short.

The following table shows the required and optional registration properties.

PropertyDescription
felix.webconsole.labelA required string property with the label. The label is also used as a path segment in the URL to address the plugin.
felix.webconsole.titleA required string property for the title.
felix.webconsole.cssA single string, an array of strings or a collection of strings to be used as additional CSS resources which are automatically included in the head of the html page for the plugin. This property is optional.

If there are more than one plugin registered with the same label, the one with the highest service ranking is used.

Before calling the servlet the web console sets these request attributes helping the plugin rendering the response:

PropertyDescription
felix.webconsole.appRootThis request attribute of type String provides the absolute path of the Web Console root. This path consists of the servlet context path (from ServletRequest.getContextPath()) and the Web Console servlet path (from HttpServletRequest.getServletPath(), /system/console by default). This attribute can be used to provide absolute links to resources (images, CSS, scripts, etc.) or other plugins. This request attribute is available to client side JavaScript as the global appRoot variable.
felix.webconsole.pluginRootThis request attribute of type String provides the absolute path of the current plugin. This path consists of the servlet context path (from ServletRequest.getContextPath()), the Web Console servlet path (from HttpServletRequest.getServletPath(), /system/console by default) and the plugin label. This attribute can be used to provide absolute links to the plugin itself. This request attribute is available to client side JavaScript as the global pluginRoot variable.

The most basic plugin is a plain old Servlet whose service(ServletRequest, ServletResponse) method is called by the Apache Felix Web Console. For support is provided by extending the org.apache.felix.webconsole.servlet.AbstractServlet base class. In general the first approach is the preferred option as it does not create a dependency on web console API.

Plugin Logging

The web console does not provide anything special for logging from within a plugin. As the web console is using slf4j, it is advisable to use the same logging mechanism. However, plugins are free to use other logging APIs.

Providing Resources

All requests that are targetted at a plugin where the path starts with /res/ are automatically handled as requests to resources. In this case the resources are searched inside the bundle providing the plugin.

Web Console Output Templating

Templating and Internationalization support of the Web Console is based on Java Resource Bundles loaded from the plugin bundles and is transparent to the plugin itself.

All html output generated by the plugin is filtered by the web console. This writer filter recognizes variables of the pattern ${name} and tries to replace that part of the output with another string:

  • If a variable of that name exists, the value of that variable is used. See Variable Resolution below.
  • Otherwise if a resource bundle provides a translated string for the name, that string is used. See Resource Bundles below.
  • Otherwise the name itself is just placed in the output.

Example

Consider the plugin bundle provides a localization for the default german locale de:

OSGI-INF/l10n/bundle_de.properties:
Hello = Guten Tag

And the plugin defines a variable replacement and writes output with the following code:

 this.getVariableResolver().put("world", "Schweiz");
 response.getWriter().println("${Hello} ${world}");

The response sent to the client whose primary locale is de is then filtered to be:

Guten Tag Schweiz

Resource Bundles

Resources for the Resource Bundles is provided by the Web Console bundle on the one hand and by the bundle providing the plugin on the other hand. Resources are identified inside a bundle with the Bundle-Localization manifest header as described in Section 3.10 Localization in the Core Specification.

This also means, that additional translations may be provided by fragment bundles.

During request processing the Locale of the request (ServletRequest.getLocale()) is used to identify the actual resources to use. From this information a ResourceBundle is constructed from a collection of the resources provided by the plugin bundle and the resources provided by the Web Console.

Web Console Localization

The Web Console contains a single localization file OSGI-INF/l10n/bundle.properties. Fragments attached to the Web Console bundle may provide translations for these resources. All plugins of the Web Console itself will use a ReosurceBundle, which is only based on the localization of the Web Console itself.

Using Templating

To use the described templating, the plugin developer may provide the following:

  • Use templated strings in the generated response. Such templated strings will be replaced with variable values or localization strings as available.
  • Set variable mappings in a VariableResolver. The simplest thing is to get a default VariableResolver calling the this.getVariableResolver(ServletRequest) method.
  • Provide localization files and optionally set the Bundle-Localization header if the base file name is not the default OSGI-INF/l10n/bundle.

Legacy Plugin Support

The Web Console supports plugins written for older versions of the Web Console leveraging the javax.servlet.Servlet interface. The support requires the javax.servlet API to be available at runtime as well as the Apache Felix Http Wrappers API. If both dependencies are provided at runtime, the legacy support is automatically enabled.

For more information refer to the legacy plugins.

Branding the Web Console

Branding the Web Consle mainly concerns hooking into the looks of the Web Console providing vendor-provided setup like CSS, Logo, Main Title, Vendor URL, etc.

Branding for the Web Console can be provided in two ways: By registering a BrandingPlugin service or by providing a branding properties files. The Web Console uses the branding from the BrandingPlugin service registered with the highest ranking.

The BrandingPlugin interface provides the following information used for branding:

// Returns an indicative name of the branding plugin
// This value is used as the Window/Page title together with the
// title of the respective plugin
String getBrandName();

// Returns the name of the product in which the web console is contained
// and to which the web console is branded.
String getProductName();

// Returns an (absolute) URL to a web site representing the product to
// which the web console is branded.
String getProductURL();

// Returns an absolute path to an image to be rendered as the logo of the
// branding product.
String getProductImage();

// Returns the name of the branding product vendor.
String getVendorName();

// Returns an (absolute) URL to the web site of the branding product
// vendor.
String getVendorURL();

// Returns an absolute path to an image to be rendered as the logo of the
// branding product vendor.
String getVendorImage();

// Returns the absolute path to an icon to be used as the web console
// "favicon".
String getFavIcon();

// Returns the absolute path to a CSS file to be used as the main CSS for
// the basic admin site.
String getMainStyleSheet();

If no BrandingPlugin service is registered, the DefaultBrandingPlugin is used.

The DefaultBrandingPlugin reads the /META-INF/webconsole.properties from the web console bundle to setup the branding using the following properties:

Propery NameDefault ValueBrandingPlugin method name
webconsole.brand.nameApache Felix Web ConsolegetBrandName()
webconsole.product.nameApache FelixgetProductName()
webconsole.product.urlhttps://felix.apache.org
webconsole.product.image/res/imgs/logo.png
webconsole.vendor.nameThe Apache Software FoundationgetVendorName()
webconsole.vendor.urlhttps://www.apache.orggetVendorURL()
webconsole.vendor.image/res/imgs/logo.pnggetVendorImage()
webconsole.favicon/res/imgs/favicon.icogetFavIcon()
webconsole.stylesheet/res/ui/webconsole.cssgetMainStyleSheet()

Note: The /META-INF/webconsole.properties file is not contained in the Apache Felix Web Console bundle itself. It may be provided by a Fragment Bundle attaching to the Apache Felix Web Console bundle.

Web Console Security Provider

An additional service controlling the access to the web console can be deployed by registering a service implementing the org.apache.felix.webconsole.spi.SecurityProvider interface.

It is possible to require a SecurityProvider service to be present in order for the Web Console to become active. This can be used to prevent bypassing the security provider if this is provided asynchronously. To do this, the SecurityProvider service needs to be registered with a Service Registration property to identify itself:

“webconsole.security.provider.id” = “my.security.provider”

Then the Web Console can be informed about the security providers it needs to operate by setting the following OSGi Framework property:

“felix.webconsole.security.providers” = “my.security.provider”

With this property specified, the Web Console will not activate until the service with the specified property is present. Local login as typically done with admin/password is disabled when this property is specified.

The SecurityProvider interfacew

The SecurityProvider interface defines three methods:

boolean authorize( Object user, String role );

Object authenticate( HttpServletRequest request, HttpServletResponse response );

void logout(HttpServletRequest request, HttpServletResponse response);

Both, the authenticate as well as the logout method are in full control of authentication and thus have to extract the user credentials from the request and can also fail the request.

The method authorize is currently not used.

Sample

A sample of a SecurityProvider service (using the legacy interface) is in the Apache Sling implementation SlingWebConsoleSecurityProvider2. This implementation uses a JCR implementation to login to the repository and thus validate the credentials.