/* | |
* 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.Arrays; | |
import java.util.Comparator; | |
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 = BundleContextUtil.getWorkingBundleContext(getBundleContext()).getAllServiceReferences(null, null); | |
} | |
catch (InvalidSyntaxException e) | |
{ | |
// ignore | |
} | |
// no services or invalid filter syntax (unlikely) | |
if (refs != null) | |
{ | |
Arrays.sort(refs, new ServiceReferenceComparator()); | |
} | |
else | |
{ | |
refs = NO_REFS; | |
} | |
return refs; | |
} | |
} | |
class ServiceReferenceComparator implements Comparator | |
{ | |
private static final Long ZERO = new Long(0); | |
public int compare(ServiceReference p1, ServiceReference p2) | |
{ | |
Long id1 = null; | |
if (p1 != null) | |
{ | |
id1 = (Long) p1.getProperty(Constants.SERVICE_ID); | |
} | |
if (id1 == null) | |
{ | |
id1 = ZERO; | |
} | |
Long id2 = null; | |
if (p2 != null) | |
{ | |
id2 = (Long) p2.getProperty(Constants.SERVICE_ID); | |
} | |
if (id2 == null) | |
{ | |
id2 = ZERO; | |
} | |
return id1.compareTo(id2); | |
} | |
public int compare(Object o1, Object o2) | |
{ | |
return compare((ServiceReference) o1, (ServiceReference) o2); | |
} | |
} |