FELIX-1043 Adding WebConsolePluginAdapter used as a wrapper around
a non-AbstractWebConsolePlugin servlet registered with the
felix.webconsole.title attribute.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@789241 13f79535-47bb-0310-9956-ffa450edef68
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 2bc1e08..2150f93 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
@@ -38,4 +38,16 @@
      */
     public static final String PLUGIN_LABEL = "felix.webconsole.label";
 
+    /**
+     * 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.
+     *
+     * @since 1.2.12
+     */
+    public static final String PLUGIN_TITLE = "felix.webconsole.title";
+
 }
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
new file mode 100644
index 0000000..1e2a056
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/WebConsolePluginAdapter.java
@@ -0,0 +1,117 @@
+/*
+ * 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.internal;
+
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+
+
+/**
+ * The <code>WebConsolePluginAdapter</code> is an adapter to the
+ * {@link AbstractWebConsolePlugin} for regular servlets registered with the
+ * {@link org.apache.felix.webconsole.WebConsoleConstants#PLUGIN_TITLE}
+ * service attribute.
+ */
+public class WebConsolePluginAdapter extends AbstractWebConsolePlugin
+{
+
+    /** serial UID */
+    private static final long serialVersionUID = 1L;
+
+    // the plugin label (aka address)
+    private final String label;
+
+    // the plugin title rendered in the top bar
+    private final String title;
+
+    // the actual plugin to forward rendering requests to
+    private final Servlet plugin;
+
+
+    public WebConsolePluginAdapter( String label, String title, Servlet plugin )
+    {
+        this.label = label;
+        this.title = title;
+        this.plugin = plugin;
+    }
+
+
+    //---------- AbstractWebConsolePlugin API
+
+    /**
+     * Returns the label of this plugin page as defined in the constructor.
+     */
+    public String getLabel()
+    {
+        return label;
+    }
+
+
+    /**
+     * Returns the title of this plugin page as defined in the constructor.
+     */
+    public String getTitle()
+    {
+        return title;
+    }
+
+
+    /**
+     * Call the plugin servlet's service method to render the content of this
+     * page.
+     */
+    protected void renderContent( HttpServletRequest req, HttpServletResponse res ) throws ServletException,
+        IOException
+    {
+        plugin.service( req, res );
+    }
+
+
+    //---------- Servlet API overwrite
+
+    /**
+     * Initializes this servlet as well as the plugin servlet.
+     */
+    public void init( ServletConfig config ) throws ServletException
+    {
+        // base classe initialization
+        super.init( config );
+
+        // plugin initialization
+        plugin.init( config );
+    }
+
+
+    /**
+     * Destroys this servlet as well as the plugin servlet.
+     */
+    public void destroy()
+    {
+        plugin.destroy();
+        super.destroy();
+    }
+}
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 d3cc447..d167847 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
@@ -46,9 +46,23 @@
     /** Pseudo class version ID to keep the IDE quite. */
     private static final long serialVersionUID = 1L;
 
-    public static final String ATTR_LABEL_MAP = OsgiManager.class.getName() + ".labelMap";
+    /**
+     * Old name of the request attribute provding the root to the web console.
+     * This attribute is no deprecated and replaced by
+     * {@link WebConsoleConstants#ATTR_APP_ROOT}.
+     *
+     * @deprecated use {@link WebConsoleConstants#ATTR_APP_ROOT} instead
+     */
+    private static final String ATTR_APP_ROOT_OLD = OsgiManager.class.getName() + ".appRoot";
 
-    public static final String ATTR_APP_ROOT = OsgiManager.class.getName() + ".appRoot";
+    /**
+     * Old name of the request attribute provding the mappings from label to
+     * page title. This attribute is no deprecated and replaced by
+     * {@link WebConsoleConstants#ATTR_LABEL_MAP}.
+     *
+     * @deprecated use {@link WebConsoleConstants#ATTR_LABEL_MAP} instead
+     */
+    private static final String ATTR_LABEL_MAP_OLD = OsgiManager.class.getName() + ".labelMap";
 
     /**
      * The name and value of a parameter which will prevent redirection to a
@@ -290,8 +304,13 @@
         Servlet plugin = ( Servlet ) plugins.get( label );
         if ( plugin != null )
         {
-            req.setAttribute( ATTR_LABEL_MAP, labelMap );
-            req.setAttribute( ATTR_APP_ROOT, request.getContextPath() + request.getServletPath() );
+            // the official request attributes
+//            req.setAttribute( WebConsoleConstants.ATTR_LABEL_MAP, labelMap );
+//            req.setAttribute( WebConsoleConstants.ATTR_APP_ROOT, request.getContextPath() + request.getServletPath() );
+
+            // deprecated request attributes
+            req.setAttribute( ATTR_LABEL_MAP_OLD, labelMap );
+            req.setAttribute( ATTR_APP_ROOT_OLD, request.getContextPath() + request.getServletPath() );
 
             plugin.service( req, res );
         }
@@ -525,6 +544,25 @@
                 Object operation = super.addingService( reference );
                 if ( operation instanceof Servlet )
                 {
+                    // wrap the servlet if it is not an AbstractWebConsolePlugin
+                    // but has a title in the service properties
+                    if ( !( operation instanceof AbstractWebConsolePlugin ) )
+                    {
+                        Object title = reference.getProperty( WebConsoleConstants.PLUGIN_TITLE );
+                        if ( title instanceof String )
+                        {
+                            WebConsolePluginAdapter pluginAdapter = new WebConsolePluginAdapter( ( String ) label,
+                                ( String ) title, ( Servlet ) operation );
+
+                            // ensure the AbstractWebConsolePlugin is correctly setup
+                            Bundle pluginBundle = reference.getBundle();
+                            pluginAdapter.activate( pluginBundle.getBundleContext() );
+
+                            // now use this adapter as the operation
+                            operation = pluginAdapter;
+                        }
+                    }
+
                     // TODO: check reference properties !!
                     osgiManager.bindServlet( ( String ) label, ( Servlet ) operation );
                 }
@@ -542,6 +580,14 @@
             {
                 // TODO: check reference properties !!
                 osgiManager.unbindServlet( ( String ) label );
+
+                // check whether the service is a WebConsolePluginAdapter in
+                // which case we have to deactivate it here (as we activated it
+                // while adding the service
+                if ( service instanceof WebConsolePluginAdapter )
+                {
+                    ( ( WebConsolePluginAdapter ) service ).deactivate();
+                }
             }
 
             super.removedService( reference, service );