The Apache Felix Web Console is extensible in various ways.
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.
Property | Description |
---|---|
felix.webconsole.label | A required string property with the label. The label is also used as a path segment in the URL to address the plugin. |
felix.webconsole.title | A required string property for the title. |
felix.webconsole.css | A 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:
Property | Description |
---|---|
felix.webconsole.appRoot | This 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.pluginRoot | This 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.
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.
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.
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:
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
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.
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.
To use the described templating, the plugin developer may provide the following:
VariableResolver
. The simplest thing is to get a default VariableResolver
calling the this.getVariableResolver(ServletRequest)
method.Bundle-Localization
header if the base file name is not the default OSGI-INF/l10n/bundle
.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 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 Name | Default Value | BrandingPlugin method name |
---|---|---|
webconsole.brand.name | Apache Felix Web Console | getBrandName() |
webconsole.product.name | Apache Felix | getProductName() |
webconsole.product.url | https://felix.apache.org | |
webconsole.product.image | /res/imgs/logo.png | |
webconsole.vendor.name | The Apache Software Foundation | getVendorName() |
webconsole.vendor.url | https://www.apache.org | getVendorURL() |
webconsole.vendor.image | /res/imgs/logo.png | getVendorImage() |
webconsole.favicon | /res/imgs/favicon.ico | getFavIcon() |
webconsole.stylesheet | /res/ui/webconsole.css | getMainStyleSheet() |
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.
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
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.
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.