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