FELIX-3237 Implement a Web Console plugin
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1203903 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
index 441a153..7c81303 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
@@ -16,6 +16,8 @@
*/
package org.apache.felix.http.whiteboard.internal;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.apache.felix.http.whiteboard.internal.tracker.FilterTracker;
import org.apache.felix.http.whiteboard.internal.tracker.HttpContextTracker;
@@ -23,16 +25,18 @@
import org.apache.felix.http.whiteboard.internal.tracker.HttpServiceTracker;
import org.apache.felix.http.whiteboard.internal.manager.ExtenderManagerImpl;
import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
+import org.apache.felix.http.whiteboard.internal.manager.HttpWhiteboardWebConsolePlugin;
import org.apache.felix.http.base.internal.AbstractActivator;
import org.apache.felix.http.base.internal.logger.SystemLogger;
-
import java.util.ArrayList;
+import java.util.Hashtable;
public final class WhiteboardActivator
extends AbstractActivator
{
private final ArrayList<ServiceTracker> trackers;
private ExtenderManager manager;
+ private ServiceRegistration httpPlugin;
public WhiteboardActivator()
{
@@ -47,6 +51,14 @@
addTracker(new FilterTracker(getBundleContext(), this.manager));
addTracker(new ServletTracker(getBundleContext(), this.manager));
addTracker(new HttpServiceTracker(getBundleContext(), this.manager));
+
+ HttpWhiteboardWebConsolePlugin plugin = new HttpWhiteboardWebConsolePlugin((ExtenderManagerImpl) this.manager);
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ props.put("felix.webconsole.label", plugin.getLabel());
+ props.put("felix.webconsole.title", plugin.getTitle());
+ props.put(Constants.SERVICE_DESCRIPTION, "Felix Http Whiteboard WebConsole Plugin");
+ httpPlugin = getBundleContext().registerService("javax.servlet.Servlet", plugin, props);
+
SystemLogger.info("Http service whiteboard started");
}
@@ -59,6 +71,8 @@
protected void doStop()
throws Exception
{
+ this.httpPlugin.unregister();
+
for (ServiceTracker tracker : this.trackers) {
tracker.close();
}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java
index 435fb4d..6f02502 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java
@@ -22,7 +22,7 @@
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
-public final class DefaultHttpContext
+public final class DefaultHttpContext
implements HttpContext
{
private Bundle bundle;
@@ -50,4 +50,10 @@
{
return true;
}
+
+ @Override
+ public String toString()
+ {
+ return getClass().getSimpleName() + " (" + Integer.toHexString(System.identityHashCode(this)) + ")";
+ }
}
\ No newline at end of file
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
index 4b0bda6..909ab85 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
@@ -18,6 +18,7 @@
import java.util.Collection;
import java.util.HashMap;
+import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.Servlet;
@@ -134,7 +135,7 @@
return;
}
- ServletMapping mapping = new ServletMapping(getHttpContext(ref), service, alias);
+ ServletMapping mapping = new ServletMapping(getHttpContext(ref), service, alias);
addInitParams(ref, mapping);
addMapping(service, mapping);
}
@@ -213,4 +214,16 @@
mapping.unregister(this.httpService);
}
}
+
+ Map<String, HttpContext> getHttpContexts() {
+ return this.contextManager.getHttpContexts();
+ }
+
+ Map<Object, AbstractMapping> getMappings()
+ {
+ synchronized (this)
+ {
+ return new HashMap<Object, AbstractMapping>(this.mapping);
+ }
+ }
}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
index 8ae62b4..275aa4f 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
@@ -38,9 +38,24 @@
this.ranking = ranking;
}
+ Filter getFilter()
+ {
+ return filter;
+ }
+
+ int getRanking()
+ {
+ return ranking;
+ }
+
+ String getPattern()
+ {
+ return pattern;
+ }
+
public void register(HttpService httpService)
- {
- if (httpService instanceof ExtHttpService) {
+ {
+ if (httpService instanceof ExtHttpService) {
register((ExtHttpService)httpService);
}
}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
index e5f105e..58d4f74 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
@@ -20,6 +20,7 @@
import org.osgi.service.http.HttpContext;
import org.apache.felix.http.base.internal.logger.SystemLogger;
import java.util.HashMap;
+import java.util.Map;
public final class HttpContextManager
{
@@ -48,7 +49,7 @@
this.contextMap.put(context, id);
SystemLogger.debug("Added context with id [" + contextId + "]");
} else {
- SystemLogger.debug("Reusing context with id [" + contextId + "]");
+ SystemLogger.debug("Reusing context with id [" + contextId + "]");
}
return context;
@@ -68,4 +69,9 @@
this.idMap.put(id, context);
this.contextMap.put(context, id);
}
+
+ public synchronized Map<String, HttpContext> getHttpContexts()
+ {
+ return new HashMap<String, HttpContext>(this.idMap);
+ }
}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java
new file mode 100755
index 0000000..9e57b9b
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java
@@ -0,0 +1,159 @@
+/*
+ * 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.http.whiteboard.internal.manager;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.service.http.HttpContext;
+
+@SuppressWarnings("serial")
+public class HttpWhiteboardWebConsolePlugin extends HttpServlet
+{
+
+ private final ExtenderManagerImpl extMgr;
+
+ public String getLabel()
+ {
+ return "httpwhiteboard";
+ }
+
+ public String getTitle()
+ {
+ return "Http Whiteboard";
+ }
+
+ public HttpWhiteboardWebConsolePlugin(final ExtenderManagerImpl extMgr)
+ {
+ this.extMgr = extMgr;
+ }
+
+ @Override
+ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ // only handle GET requests, ensure no error message for other requests
+ if ("GET".equals(req.getMethod()) || "HEAD".equals(req.getMethod()))
+ {
+ super.service(req, resp);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
+ {
+
+ PrintWriter pw = resp.getWriter();
+
+ pw.println("<table class='content' width='100%' cellspacing='0' cellpadding='0'>");
+
+ printHttpContextServices(pw);
+
+ pw.println("<tr><td colspan='2'> </td></tr>");
+
+ final Map<Object, AbstractMapping> mappings = extMgr.getMappings();
+ printServletMappings(pw, mappings);
+
+ pw.println("<tr><td colspan='2'> </td></tr>");
+
+ printFilterMappings(pw, mappings);
+
+ pw.println("</table>");
+ }
+
+ private void printHttpContextServices(PrintWriter pw)
+ {
+ pw.println("<tr>");
+ pw.println("<th class='content container' colspan='4'>Registered HttpContext Services</td>");
+ pw.println("</tr>");
+ pw.println("<tr>");
+ pw.println("<th class='content'>Context ID</td>");
+ pw.println("<th class='content' colspan='3'>HttpContext</td>");
+ pw.println("</tr>");
+
+ final Map<String, HttpContext> contexts = extMgr.getHttpContexts();
+ for (Map.Entry<String, HttpContext> handler : contexts.entrySet())
+ {
+ pw.println("<tr class='content'>");
+ pw.println("<td class='content'>" + handler.getKey() + "</td>");
+ pw.println("<td class='content' colspan='3'>" + handler.getValue() + "</td>");
+ pw.println("</tr>");
+ }
+ }
+
+ private void printServletMappings(PrintWriter pw, Map<Object, AbstractMapping> mappings)
+ {
+ pw.println("<tr>");
+ pw.println("<th class='content container' colspan='4'>Registered Filter and Servlet Services</td>");
+ pw.println("</tr>");
+ pw.println("<tr>");
+ pw.println("<th class='content'>Alias</td>");
+ pw.println("<th class='content'>Servlet</td>");
+ pw.println("<th class='content'>Init Parameter</td>");
+ pw.println("<th class='content'>HttpContext</td>");
+ pw.println("</tr>");
+
+ for (Map.Entry<Object, AbstractMapping> handler : mappings.entrySet())
+ {
+ if (handler.getValue() instanceof ServletMapping)
+ {
+ ServletMapping sm = (ServletMapping) handler.getValue();
+ pw.println("<tr class='content'>");
+ pw.println("<td class='content'>" + sm.getAlias() + "</td>");
+ pw.println("<td class='content'>" + sm.getServlet() + "</td>");
+ pw.println("<td class='content'>" + sm.getInitParams() + "</td>");
+ pw.println("<td class='content'>" + sm.getContext() + "</td>");
+ pw.println("</tr>");
+ }
+ }
+ }
+
+ private void printFilterMappings(PrintWriter pw, Map<Object, AbstractMapping> mappings)
+ {
+ pw.println("<tr>");
+ pw.println("<th class='content container' colspan='4'>Registered Filter and Servlet Services</td>");
+ pw.println("</tr>");
+ pw.println("<tr>");
+ pw.println("<th class='content'>Pattern</td>");
+ pw.println("<th class='content'>Filter (Ranking)</td>");
+ pw.println("<th class='content'>Init Parameter</td>");
+ pw.println("<th class='content'>HttpContext</td>");
+ pw.println("</tr>");
+
+ for (Map.Entry<Object, AbstractMapping> handler : mappings.entrySet())
+ {
+ if (handler.getValue() instanceof FilterMapping)
+ {
+ FilterMapping fm = (FilterMapping) handler.getValue();
+ pw.println("<tr class='content'>");
+ pw.println("<td class='content'>" + fm.getPattern() + "</td>");
+ pw.println("<td class='content'>" + fm.getFilter() + " (" + fm.getRanking() + ")</td>");
+ pw.println("<td class='content'>" + fm.getInitParams() + "</td>");
+ pw.println("<td class='content'>" + fm.getContext() + "</td>");
+ pw.println("</tr>");
+ }
+ }
+ }
+
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
index 0a283e9..362e582 100644
--- a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
@@ -35,6 +35,16 @@
this.alias = alias;
}
+ String getAlias()
+ {
+ return this.alias;
+ }
+
+ Servlet getServlet()
+ {
+ return this.servlet;
+ }
+
public void register(HttpService httpService)
{
try {