blob: 5e28e98c660981d6b6e08cf91d8985eb9cb85455 [file] [log] [blame]
/*
* 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;
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();
// 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();
// 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();
// 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();
// 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();
// 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();
// 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;
}
}