Fixed FELIX-2282 /Optimize Services Printer/
https://issues.apache.org/jira/browse/FELIX-2282
Also added some javadoc in OsgiManager and fixed spelling mistakes in the comments.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@934299 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesConfigurationPrinter.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesConfigurationPrinter.java
new file mode 100644
index 0000000..60f43c7
--- /dev/null
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesConfigurationPrinter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.core;
+
+import java.io.PrintWriter;
+import java.text.MessageFormat;
+import java.util.Locale;
+
+import org.apache.felix.webconsole.internal.AbstractConfigurationPrinter;
+import org.apache.felix.webconsole.internal.Util;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * ServicesConfigurationPrinter provides a configuration printer for inspecting the
+ * registered services.
+ */
+public class ServicesConfigurationPrinter extends AbstractConfigurationPrinter implements Constants
+{
+ private static final String TITLE = "Services";
+
+ private static final MessageFormat INFO = new MessageFormat(
+ "Service {0} - {1} (pid: {2})");
+ private static final MessageFormat FROM = new MessageFormat(
+ " from Bundle {0} - {1} ({2}), version {3}");
+ private static final MessageFormat USING = new MessageFormat(
+ " Using Bundle {0} - {1} ({2}), version {3}");
+
+ // don't create empty reference array all the time, create it only once - it is immutable
+ private static final ServiceReference[] NO_REFS = new ServiceReference[0];
+
+ /**
+ * @see org.apache.felix.webconsole.ConfigurationPrinter#getTitle()
+ */
+ public final String getTitle()
+ {
+ return TITLE;
+ }
+
+ /**
+ * @see org.apache.felix.webconsole.ConfigurationPrinter#printConfiguration(java.io.PrintWriter)
+ */
+ public final void printConfiguration(PrintWriter pw)
+ {
+ final Object[] data = new Object[4]; // used as message formatter parameters
+ final ServiceReference refs[] = getServices();
+ pw.print("Status: ");
+ pw.println(ServicesServlet.getStatusLine(refs));
+
+ for (int i = 0; refs != null && i < refs.length; i++)
+ {
+ try
+ {
+ final Bundle bundle = refs[i].getBundle();
+ final Bundle[] usingBundles = refs[i].getUsingBundles();
+
+ pw.println();
+ pw.println(INFO.format(params(refs[i], data)));
+ pw.println(FROM.format(params(bundle, data)));
+
+ // print registration properties
+ String[] keys = refs[i].getPropertyKeys();
+ for (int j = 0; keys != null && j < keys.length; j++)
+ {
+ final String key = keys[j];
+ // skip common keys - already added above
+ if (SERVICE_ID.equals(key) || OBJECTCLASS.equals(key)
+ || SERVICE_PID.equals(key))
+ continue;
+
+ pw.print(" ");
+ pw.print(key);
+ pw.print(": ");
+ pw.println(ServicesServlet.propertyAsString(refs[i], key));
+ }
+
+ // using bundles
+ for (int j = 0; usingBundles != null && j < usingBundles.length; j++)
+ {
+ pw.println(USING.format(params(usingBundles[j], data)));
+ }
+ }
+ catch (Throwable t)
+ {
+ // a problem handling a service - ignore and continue with the next
+ }
+ }
+ }
+
+ private static final Object[] params(Bundle bundle, Object[] data)
+ {
+ data[0] = String.valueOf(bundle.getBundleId());
+ data[1] = Util.getName(bundle, Locale.ENGLISH);
+ data[2] = bundle.getSymbolicName();
+ data[3] = Util.getHeaderValue(bundle, Constants.BUNDLE_VERSION);
+ return data;
+ }
+
+ private static final Object[] params(ServiceReference ref, Object[] data)
+ {
+ data[0] = ServicesServlet.propertyAsString(ref, SERVICE_ID);
+ data[1] = ServicesServlet.propertyAsString(ref, OBJECTCLASS);
+ data[2] = ServicesServlet.propertyAsString(ref, SERVICE_PID);
+ data[3] = "";
+ return data;
+ }
+
+ private final ServiceReference[] getServices()
+ {
+ ServiceReference[] refs = null;
+ try
+ {
+ refs = getBundleContext().getAllServiceReferences(null, null);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ // ignore
+ }
+
+ // no services or invalid filter syntax (unlikely)
+ return refs != null ? refs : NO_REFS;
+ }
+
+}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesServlet.java
index f8528da..9a56bb6 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/ServicesServlet.java
@@ -23,36 +23,30 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
-import java.text.MessageFormat;
import java.util.Locale;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.felix.webconsole.ConfigurationPrinter;
import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
import org.apache.felix.webconsole.internal.Util;
-import org.json.JSONArray;
import org.json.JSONException;
-import org.json.JSONObject;
import org.json.JSONWriter;
import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
/**
* ServicesServlet provides a plugin for inspecting the registered services.
*/
-public class ServicesServlet extends SimpleWebConsolePlugin implements ConfigurationPrinter, OsgiManagerPlugin
+public class ServicesServlet extends SimpleWebConsolePlugin implements OsgiManagerPlugin
{
// don't create empty reference array all the time, create it only once - it is immutable
private static final ServiceReference[] NO_REFS = new ServiceReference[0];
@@ -109,8 +103,6 @@
return ( RequestInfo ) request.getAttribute( ServicesServlet.class.getName() );
}
- private ServiceRegistration configurationPrinter;
-
/** the label for the services plugin */
public static final String LABEL = "services";
private static final String TITLE = "%services.pluginTitle";
@@ -127,122 +119,6 @@
}
- /**
- * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#activate(org.osgi.framework.BundleContext)
- */
- public void activate( BundleContext bundleContext )
- {
- super.activate( bundleContext );
- configurationPrinter = bundleContext.registerService( ConfigurationPrinter.SERVICE, this, null );
- }
-
-
- /**
- * @see org.apache.felix.webconsole.SimpleWebConsolePlugin#deactivate()
- */
- public void deactivate()
- {
- if ( configurationPrinter != null )
- {
- configurationPrinter.unregister();
- configurationPrinter = null;
- }
-
- super.deactivate();
- }
-
-
- /**
- * @see org.apache.felix.webconsole.ConfigurationPrinter#printConfiguration(java.io.PrintWriter)
- */
- public void printConfiguration( PrintWriter pw )
- {
- try
- {
- StringWriter w = new StringWriter();
- writeJSON( w, null, true, Locale.ENGLISH );
- String jsonString = w.toString();
- JSONObject json = new JSONObject( jsonString );
-
- pw.println( "Status: " + json.get( "status" ) );
- pw.println();
-
- JSONArray data = json.getJSONArray( "data" );
- for ( int i = 0; i < data.length(); i++ )
- {
- if ( !data.isNull( i ) )
- {
- JSONObject service = data.getJSONObject( i );
-
- pw.println( MessageFormat.format( "Service {0} - {1} (pid: {2})", new Object[]
- { service.get( "id" ), service.get( "types" ), service.get( "pid" ) } ) );
- pw.println( MessageFormat.format( " from Bundle {0} - {1} ({2}), version {3}", new Object[]
- { service.get( "bundleId" ), service.get( "bundleName" ), service.get( "bundleSymbolicName" ),
- service.get( "bundleVersion" ) } ) );
-
- JSONArray props = service.getJSONArray( "props" );
- for ( int pi = 0; pi < props.length(); pi++ )
- {
- if ( !props.isNull( pi ) )
- {
- JSONObject entry = props.getJSONObject( pi );
-
- pw.print( " " + entry.get( "key" ) + ": " );
-
- Object entryValue = entry.get( "value" );
- if ( entryValue instanceof JSONArray )
- {
- pw.println();
- JSONArray entryArray = ( JSONArray ) entryValue;
- for ( int ei = 0; ei < entryArray.length(); ei++ )
- {
- if ( !entryArray.isNull( ei ) )
- {
- pw.println( " " + entryArray.get( ei ) );
- }
- }
- }
- else
- {
- pw.println( entryValue );
- }
- }
- }
-
- JSONArray usingBundles = service.getJSONArray( "usingBundles" );
- for ( int ui = 0; ui < usingBundles.length(); ui++ )
- {
- if ( !usingBundles.isNull( ui ) )
- {
- JSONObject bundle = usingBundles.getJSONObject( ui );
- pw.println( MessageFormat.format( " Using Bundle {0} - {1} ({2}), version {3}", new Object[]
- { bundle.get( "bundleId" ), bundle.get( "bundleName" ),
- bundle.get( "bundleSymbolicName" ), bundle.get( "bundleVersion" ) } ) );
- }
- }
-
- pw.println();
- }
- }
- }
- catch ( Exception e )
- {
- log( "Problem rendering Bundle details for configuration status", e );
- }
- }
-
-
- private static final void appendServiceInfoCount( final StringBuffer buf, String msg, int count )
- {
- buf.append( count );
- buf.append( " service" );
- if ( count != 1 )
- buf.append( 's' );
- buf.append( ' ' );
- buf.append( msg );
- }
-
-
final ServiceReference getServiceById( String pathInfo )
{
// only use last part of the pathInfo
@@ -290,16 +166,21 @@
}
- private static final String getStatusLine( final ServiceReference[] services )
+ static final String getStatusLine( final ServiceReference[] services )
{
+ final int count = services.length;
final StringBuffer buffer = new StringBuffer();
buffer.append( "Services information: " );
- appendServiceInfoCount( buffer, "in total", services.length );
+ buffer.append( count );
+ buffer.append( " service" );
+ if ( count != 1 )
+ buffer.append( 's' );
+ buffer.append( " in total" );
return buffer.toString();
}
- private String propertyAsString( ServiceReference ref, String name )
+ static final String propertyAsString( ServiceReference ref, String name )
{
Object value = ref.getProperty( name );
if ( value instanceof Object[] )
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 0daf99d..9d2d45e 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
@@ -70,7 +70,7 @@
private static final long serialVersionUID = 1L;
/**
- * Old name of the request attribute provding the root to the web console.
+ * Old name of the request attribute providing the root to the web console.
* This attribute is no deprecated and replaced by
* {@link WebConsoleConstants#ATTR_APP_ROOT}.
*
@@ -79,7 +79,7 @@
private static final String ATTR_APP_ROOT_OLD = OsgiManager.class.getName() + ".appRoot";
/**
- * Old name of the request attribute provding the mappings from label to
+ * Old name of the request attribute providing the mappings from label to
* page title. This attribute is no deprecated and replaced by
* {@link WebConsoleConstants#ATTR_LABEL_MAP}.
*
@@ -141,6 +141,7 @@
"org.apache.felix.webconsole.internal.compendium.LogServlet",
"org.apache.felix.webconsole.internal.compendium.PreferencesConfigurationPrinter",
"org.apache.felix.webconsole.internal.core.BundlesServlet",
+ "org.apache.felix.webconsole.internal.core.ServicesConfigurationPrinter",
"org.apache.felix.webconsole.internal.core.ServicesServlet",
"org.apache.felix.webconsole.internal.deppack.DepPackServlet",
"org.apache.felix.webconsole.internal.misc.LicenseServlet",
@@ -240,6 +241,9 @@
//---------- Servlet API
+ /**
+ * @see javax.servlet.GenericServlet#init()
+ */
public void init()
{
// base class initialization not needed, since the GenericServlet.init
@@ -318,6 +322,9 @@
}
+ /**
+ * @see javax.servlet.GenericServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+ */
public void service( final ServletRequest req, final ServletResponse res ) throws ServletException, IOException
{
// don't really expect to be called within a non-HTTP environment
@@ -423,6 +430,9 @@
return locale;
}
+ /**
+ * @see javax.servlet.GenericServlet#destroy()
+ */
public void destroy()
{
// base class destroy not needed, since the GenericServlet.destroy
@@ -479,7 +489,7 @@
* Calls the <code>GenericServlet.log(String)</code> method if the
* configured log level is less than or equal to the given <code>level</code>.
* <p>
- * Note, that the <code>level</code> paramter is only used to decide whether
+ * Note, that the <code>level</code> parameter is only used to decide whether
* the <code>GenericServlet.log(String)</code> method is called or not. The
* actual implementation of the <code>GenericServlet.log</code> method is
* outside of the control of this method.
@@ -501,7 +511,7 @@
* the configured log level is less than or equal to the given
* <code>level</code>.
* <p>
- * Note, that the <code>level</code> paramter is only used to decide whether
+ * Note, that the <code>level</code> parameter is only used to decide whether
* the <code>GenericServlet.log(String, Throwable)</code> method is called
* or not. The actual implementation of the <code>GenericServlet.log</code>
* method is outside of the control of this method.