/* * 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); } }