/* * 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.gogo.command; import java.util.ArrayList; import java.util.List; import org.apache.felix.service.command.Descriptor; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.ExportedPackage; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.service.packageadmin.RequiredBundle; @SuppressWarnings("deprecation") public class Inspect42 { public static final String LEGACY_PACKAGE_NAMESPACE = "package"; public static final String LEGACY_BUNDLE_NAMESPACE = "bundle"; public static final String LEGACY_HOST_NAMESPACE = "host"; public static final String NONSTANDARD_SERVICE_NAMESPACE = "service"; public static final String CAPABILITY = "capability"; public static final String REQUIREMENT = "requirement"; private static final String EMPTY_MESSAGE = "[EMPTY]"; private static final String UNUSED_MESSAGE = "[UNUSED]"; private static final String UNRESOLVED_MESSAGE = "[UNRESOLVED]"; private final BundleContext m_bc; public Inspect42(BundleContext bc) { m_bc = bc; } @Descriptor("inspects bundle capabilities and requirements") public void inspect( @Descriptor("('capability' | 'requirement')") String direction, @Descriptor("('package' | 'bundle' | 'host' | 'service')") String namespace, @Descriptor("target bundles") Bundle[] bundles) { inspect(m_bc, direction, namespace, bundles); } private static void inspect( BundleContext bc, String direction, String namespace, Bundle[] bundles) { // Verify arguments. if (isValidDirection(direction)) { bundles = ((bundles == null) || (bundles.length == 0)) ? bc.getBundles() : bundles; if (CAPABILITY.startsWith(direction)) { printNonstandardCapabilities(bc, Util.parseSubstring(namespace), bundles); } else { printNonstandardRequirements(bc, Util.parseSubstring(namespace), bundles); } } else { if (!isValidDirection(direction)) { System.out.println("Invalid argument: " + direction); } } } private static void printNonstandardCapabilities( BundleContext bc, List<String> namespace, Bundle[] bundles) { boolean separatorNeeded = false; for (Bundle b : bundles) { if (separatorNeeded) { System.out.println(""); } String title = b + " provides:"; System.out.println(title); System.out.println(Util.getUnderlineString(title.length())); boolean matches = false; if (matchNamespace(namespace, LEGACY_BUNDLE_NAMESPACE)) { matches |= printRequiringBundles(bc, b); } if (matchNamespace(namespace, LEGACY_HOST_NAMESPACE)) { matches |= printHostedFragments(bc, b); } if (matchNamespace(namespace, LEGACY_PACKAGE_NAMESPACE)) { matches |= printExportedPackages(bc, b); } if (matchNamespace(namespace, NONSTANDARD_SERVICE_NAMESPACE)) { matches |= Inspect.printServiceCapabilities(b); } // If there were no capabilities for the specified namespace, // then say so. if (!matches) { System.out.println(Util.unparseSubstring(namespace) + " " + EMPTY_MESSAGE); } separatorNeeded = true; } } private static void printNonstandardRequirements( BundleContext bc, List<String> namespace, Bundle[] bundles) { boolean separatorNeeded = false; for (Bundle b : bundles) { if (separatorNeeded) { System.out.println(""); } String title = b + " requires:"; System.out.println(title); System.out.println(Util.getUnderlineString(title.length())); boolean matches = false; if (matchNamespace(namespace, LEGACY_BUNDLE_NAMESPACE)) { matches |= printRequiredBundles(bc, b); } if (matchNamespace(namespace, LEGACY_HOST_NAMESPACE)) { matches |= printFragmentHosts(bc, b); } if (matchNamespace(namespace, LEGACY_PACKAGE_NAMESPACE)) { matches |= printImportedPackages(bc, b); } if (matchNamespace(namespace, NONSTANDARD_SERVICE_NAMESPACE)) { matches |= Inspect.printServiceRequirements(b); } // If there were no capabilities for the specified namespace, // then say so. if (!matches) { System.out.println(Util.unparseSubstring(namespace) + " " + EMPTY_MESSAGE); } separatorNeeded = true; } } public static boolean printExportedPackages(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Fragments cannot export packages. if (!isFragment(b)) { // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { try { ExportedPackage[] exports = pa.getExportedPackages(b); if (exports != null) { for (ExportedPackage ep : exports) { matches = true; Bundle[] importers = ep.getImportingBundles(); if ((importers != null) && (importers.length > 0)) { String msg = LEGACY_PACKAGE_NAMESPACE + "; " + ep.getName() + "; " + ep.getVersion().toString() + " required by:"; System.out.println(msg); for (Bundle importer : importers) { System.out.println(" " + importer); } } else { System.out.println( LEGACY_PACKAGE_NAMESPACE + "; " + ep.getName() + "; " + ep.getVersion().toString() + " " + UNUSED_MESSAGE); } } } } catch (Exception ex) { System.err.println(ex.toString()); } } } Util.ungetServices(bc, refs); return matches; } private static boolean printImportedPackages(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Fragments cannot import packages. if (!isFragment(b)) { // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { ExportedPackage[] exports = pa.getExportedPackages((Bundle) null); if (exports != null) { for (ExportedPackage ep : exports) { Bundle[] importers = ep.getImportingBundles(); if (importers != null) { for (Bundle importer : importers) { if (importer == b) { matches = true; System.out.println( LEGACY_PACKAGE_NAMESPACE + "; " + ep.getName() + " resolved by:"); System.out.println( " " + ep.getName() + "; " + ep.getVersion().toString() + " from " + ep.getExportingBundle()); } } } } } } } Util.ungetServices(bc, refs); return matches; } public static boolean printRequiringBundles(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Fragments cannot be required. if (!isFragment(b)) { // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { try { RequiredBundle[] rbs = pa.getRequiredBundles(b.getSymbolicName()); if (rbs != null) { for (RequiredBundle rb : rbs) { if (rb.getBundle() == b) { Bundle[] requires = rb.getRequiringBundles(); if ((requires != null) && (requires.length > 0)) { matches = true; System.out.println( LEGACY_BUNDLE_NAMESPACE + "; " + b.getSymbolicName() + "; " + b.getVersion().toString() + " required by:"); for (Bundle requirer : requires) { System.out.println(" " + requirer); } } } } } if (!matches) { matches = true; System.out.println( LEGACY_BUNDLE_NAMESPACE + "; " + b.getSymbolicName() + "; " + b.getVersion().toString() + " " + UNUSED_MESSAGE); } } catch (Exception ex) { System.err.println(ex.toString()); } } } Util.ungetServices(bc, refs); return matches; } private static boolean printRequiredBundles(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Fragments cannot require bundles. if (!isFragment(b)) { // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { RequiredBundle[] rbs = pa.getRequiredBundles(null); if (rbs != null) { for (RequiredBundle rb : rbs) { Bundle[] requirers = rb.getRequiringBundles(); if (requirers != null) { for (Bundle requirer : requirers) { if (requirer == b) { matches = true; System.out.println( LEGACY_BUNDLE_NAMESPACE + "; " + rb.getSymbolicName() + " resolved by:"); System.out.println(" " + rb.getBundle()); } } } } } } } Util.ungetServices(bc, refs); return matches; } public static boolean printHostedFragments(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { try { if (!isFragment(b)) { matches = true; Bundle[] fragments = pa.getFragments(b); if ((fragments != null) && (fragments.length > 0)) { System.out.println( LEGACY_HOST_NAMESPACE + "; " + b.getSymbolicName() + "; " + b.getVersion().toString() + " required by:"); for (Bundle fragment : fragments) { System.out.println(" " + fragment); } } else { System.out.println( LEGACY_HOST_NAMESPACE + "; " + b.getSymbolicName() + "; " + b.getVersion().toString() + " " + UNUSED_MESSAGE); } } } catch (Exception ex) { System.err.println(ex.toString()); } Util.ungetServices(bc, refs); } return matches; } public static boolean printFragmentHosts(BundleContext bc, Bundle b) { boolean matches = false; // Keep track of service references. List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>(); // Get package admin service. PackageAdmin pa = Util.getService(bc, PackageAdmin.class, refs); if (pa == null) { System.out.println("PackageAdmin service is unavailable."); } else { try { if (isFragment(b)) { matches = true; Bundle[] hosts = pa.getHosts(b); if ((hosts != null) && (hosts.length > 0)) { System.out.println( LEGACY_HOST_NAMESPACE + "; " + b.getHeaders().get(Constants.FRAGMENT_HOST) + " resolved by:"); for (Bundle host : hosts) { System.out.println(" " + host); } } else { System.out.println( LEGACY_HOST_NAMESPACE + "; " + b.getHeaders().get(Constants.FRAGMENT_HOST) + " " + UNRESOLVED_MESSAGE); } } } catch (Exception ex) { System.err.println(ex.toString()); } Util.ungetServices(bc, refs); } return matches; } private static boolean matchNamespace(List<String> namespace, String actual) { return Util.compareSubstring(namespace, actual); } private static boolean isValidDirection(String direction) { return (CAPABILITY.startsWith(direction) || REQUIREMENT.startsWith(direction)); } private static boolean isFragment(Bundle bundle) { return bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null; } }