Author: fmeschbe
Date: Thu Sep 4 00:40:03 2008
New Revision: 691895
URL: http://svn.apache.org/viewvc?rev=691895&view=rev
Log:
SLING-644 Add plugin for the Felix Web Console
Added:
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
Modified:
incubator/sling/trunk/extensions/bundleresource/pom.xml
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
Modified: incubator/sling/trunk/extensions/bundleresource/pom.xml
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/bundleresource/pom.xml?rev=691895&r1=691894&r2=691895&view=diff
==============================================================================
--- incubator/sling/trunk/extensions/bundleresource/pom.xml (original)
+++ incubator/sling/trunk/extensions/bundleresource/pom.xml Thu Sep 4 00:40:03
2008
@@ -37,19 +37,21 @@
</description>
<scm>
-
<connection>scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/extensions/bundleresource</connection>
-
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/extensions/bundleresource</developerConnection>
-
<url>http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/bundleresource</url>
+ <connection>
+
scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/extensions/bundleresource
+ </connection>
+ <developerConnection>
+
scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/extensions/bundleresource
+ </developerConnection>
+ <url>
+
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/bundleresource
+ </url>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
- <artifactId>maven-scr-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
@@ -58,8 +60,12 @@
org.apache.sling.bundleresource.impl.Activator
</Bundle-Activator>
<Private-Package>
- org.apache.sling.bundleresource.*
+ org.apache.sling.bundleresource.*,
+ org.osgi.util.tracker
</Private-Package>
+ <DynamicImport-Package>
+ org.apache.felix.webconsole
+ </DynamicImport-Package>
</instructions>
</configuration>
</plugin>
@@ -95,11 +101,17 @@
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.webconsole</artifactId>
+ <version>1.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.osgi.compendium</artifactId>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
Modified:
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/Activator.java?rev=691895&r1=691894&r2=691895&view=diff
==============================================================================
---
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
(original)
+++
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
Thu Sep 4 00:40:03 2008
@@ -18,6 +18,7 @@
*/
package org.apache.sling.bundleresource.impl;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -37,6 +38,26 @@
*/
public static final String BUNDLE_RESOURCE_ROOTS =
"Sling-Bundle-Resources";
+ /**
+ * Fully qualified name of the Web Console Plugin class. This class will be
+ * loaded dynamically to prevent issues if the Felix Web Console is not
+ * installed in the system (value is
+ * "org.apache.sling.bundleresource.impl.BundleResourceWebConsolePlugin").
+ */
+ private static final String CONSOLE_PLUGIN_CLASS =
"org.apache.sling.bundleresource.impl.BundleResourceWebConsolePlugin";
+
+ /**
+ * Name of the initialization method to call on the Web Console Plugin
class
+ * (value is "initPlugin").
+ */
+ private static final String METHOD_INIT = "initPlugin";
+
+ /**
+ * Name of the shutdown method to call on the Web Console Plugin class
+ * (value is "destroyPlugin").
+ */
+ private static final String METHOD_DESTROY = "destroyPlugin";
+
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -63,9 +84,17 @@
"activate: Problem while registering bundle resources for
existing bundles",
t);
}
+
+ // hackery thing to prevent problems if the web console is not present
+ callMethod(CONSOLE_PLUGIN_CLASS, METHOD_INIT,
+ new Class<?>[] { BundleContext.class }, new Object[] { context });
+
}
public void stop(BundleContext context) throws Exception {
+ // hackery thing to prevent problems if the web console is not present
+ callMethod(CONSOLE_PLUGIN_CLASS, METHOD_DESTROY, null, null);
+
context.removeBundleListener(this);
this.bundleContext = null;
}
@@ -112,4 +141,36 @@
}
}
+ /**
+ * Helper method to call the static method <code>methodName</code> on the
+ * class <code>clazzName</code> with the given <code>args</code>. This
+ * method operates exclusively using reflection to prevent any issues if
the
+ * class cannot be loaded.
+ * <p>
+ * The goal is to enable running the bundle resource provider without a
hard
+ * dependency on the Felix Web Console.
+ *
+ * @param clazzName The fully qualified name of the class whose static
+ * method is to be called.
+ * @param methodName The name of the method to call. This method must be
+ * declared in the given class.
+ * @param argTypes The types of arguments of the methods to be able to find
+ * the method. This may be <code>null</code> if the method has
+ * no arguments.
+ * @param args The actual arguments to the method. This may be
+ * <code>null</code> if the method has no arguments.
+ */
+ private void callMethod(String clazzName, String methodName,
+ Class<?>[] argTypes, Object[] args) {
+ try {
+ Class<?> clazz = getClass().getClassLoader().loadClass(clazzName);
+ Method method = clazz.getDeclaredMethod(methodName, argTypes);
+ if (!method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ method.invoke(null, args);
+ } catch (Throwable t) {
+ // ignore anything
+ }
+ }
}
Added:
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java?rev=691895&view=auto
==============================================================================
---
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
(added)
+++
incubator/sling/trunk/extensions/bundleresource/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
Thu Sep 4 00:40:03 2008
@@ -0,0 +1,222 @@
+/*
+ * 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.sling.bundleresource.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+
+class BundleResourceWebConsolePlugin extends AbstractWebConsolePlugin {
+
+ private static final String LABEL = "bundleresources";
+
+ private ServiceRegistration serviceRegistration;
+
+ private ServiceTracker providerTracker;
+
+ private List<BundleResourceProvider> provider = new
ArrayList<BundleResourceProvider>();
+
+ //--------- setup and shutdown
+
+ private static BundleResourceWebConsolePlugin INSTANCE;
+
+ static void initPlugin(BundleContext context) {
+ if (INSTANCE == null) {
+ BundleResourceWebConsolePlugin tmp = new
BundleResourceWebConsolePlugin();
+ tmp.activate(context);
+ INSTANCE = tmp;
+ }
+ }
+
+ static void destroyPlugin() {
+ if (INSTANCE != null) {
+ try {
+ INSTANCE.deactivate();
+ } finally {
+ INSTANCE = null;
+ }
+ }
+ }
+
+ // private constructor to force using static setup and shutdown
+ private BundleResourceWebConsolePlugin() {
+ }
+
+ //---------- AbstractWebConsolePlugin implementation
+
+ @Override
+ public String getLabel() {
+ return LABEL;
+ }
+
+ @Override
+ public String getTitle() {
+ return "Bundle Resource Provider";
+ }
+
+ @Override
+ protected void renderContent(HttpServletRequest req, HttpServletResponse
res)
+ throws IOException {
+
+ PrintWriter pw = res.getWriter();
+
+ pw.println("<table class='content' cellpadding='0' cellspacing='0'
width='100%'>");
+
+ pw.println("<tr class='content'>");
+ pw.println("<th colspan='2' class='content container'>Bundle Resource
Provider</th>");
+ pw.println("</tr>");
+
+ BundleResourceProvider[] brp = provider.toArray(new
BundleResourceProvider[provider.size()]);
+ for (BundleResourceProvider bundleResourceProvider : brp) {
+
+ BundleResourceCache cache =
bundleResourceProvider.getBundleResourceCache();
+ MappedPath[] paths = bundleResourceProvider.getMappedPaths();
+
+ pw.println("<tr class='content'>");
+
+ pw.println("<td class='content'>");
+ pw.println(cache.getBundle().getBundleId());
+ pw.println("</td>");
+
+ pw.println("<td class='content'>");
+ pw.println(getName(cache.getBundle()));
+ pw.println("</td>");
+
+ pw.println("</tr>");
+
+ pw.println("<tr class='content'>");
+ pw.println("<td class='content'> </td>");
+
+ pw.println("<td class='content'>");
+
+ pw.println("<table>");
+
+ pw.println("<tr>");
+ pw.println("<td>Mappings</td>");
+ pw.println("<td>");
+ for (MappedPath mappedPath : paths) {
+ pw.print(mappedPath.getResourceRoot());
+ if (mappedPath.getEntryRoot() != null) {
+ pw.print(" ==> ");
+ pw.print(mappedPath.getEntryRoot());
+ }
+ pw.print("<br>");
+ }
+ pw.println("</td>");
+ pw.println("</tr>");
+
+ pw.println("<tr>");
+ pw.println("<td>Entry Cache</td>");
+ pw.printf("<td>Size: %d, Limit: %d</td>%n",
+ cache.getEntryCacheSize(), cache.getEntryCacheMaxSize());
+ pw.println("</tr>");
+
+ pw.println("<tr>");
+ pw.println("<td>List Cache</td>");
+ pw.printf("<td>Size: %d, Limit: %d</td>%n",
+ cache.getListCacheSize(), cache.getListCacheMaxSize());
+ pw.println("</tr>");
+
+ pw.println("</table>");
+
+ pw.println("</td>");
+ pw.println("</tr>");
+ }
+
+ pw.println("</table>");
+
+ }
+
+ public void activate(BundleContext context) {
+ super.activate(context);
+
+ providerTracker = new ServiceTracker(context,
+ ResourceProvider.SERVICE_NAME, null) {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ Object service = super.addingService(reference);
+ if (service instanceof BundleResourceProvider) {
+ provider.add((BundleResourceProvider) service);
+ }
+ return service;
+ }
+
+ @Override
+ public void removedService(ServiceReference reference,
+ Object service) {
+ if (service instanceof BundleResourceProvider) {
+ provider.remove(service);
+ }
+ super.removedService(reference, service);
+ }
+ };
+ providerTracker.open();
+
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_DESCRIPTION,
+ "Web Console Plugin for Bundle Resource Providers");
+ props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+ props.put(Constants.SERVICE_PID, getClass().getName());
+ props.put(WebConsoleConstants.PLUGIN_LABEL, LABEL);
+
+ serviceRegistration = context.registerService(
+ WebConsoleConstants.SERVICE_NAME, this, props);
+ }
+
+ public void deactivate() {
+ if (serviceRegistration != null) {
+ serviceRegistration.unregister();
+ serviceRegistration = null;
+ }
+
+ if (providerTracker != null) {
+ providerTracker.close();
+ providerTracker = null;
+ }
+
+ super.deactivate();
+ }
+
+ private String getName(Bundle bundle) {
+ String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
+ if (name == null) {
+ name = bundle.getSymbolicName();
+ if (name == null) {
+ name = bundle.getLocation();
+ }
+ }
+ return name;
+ }
+}