Search in sources :

Example 11 with BundleRequirementImpl

use of org.apache.felix.framework.wiring.BundleRequirementImpl in project felix by apache.

the class BundleWiringImpl method diagnoseClassLoadError.

private static String diagnoseClassLoadError(StatefulResolver resolver, BundleRevision revision, String name) {
    // We will try to do some diagnostics here to help the developer
    // deal with this exception.
    // Get package name.
    String pkgName = Util.getClassPackage(name);
    if (pkgName.length() == 0) {
        return null;
    }
    // First, get the bundle string of the revision doing the class loader.
    String importer = revision.getBundle().toString();
    // Next, check to see if the revision imports the package.
    List<BundleWire> wires = (revision.getWiring() == null) ? null : revision.getWiring().getProvidedWires(null);
    for (int i = 0; (wires != null) && (i < wires.size()); i++) {
        if (wires.get(i).getCapability().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) && wires.get(i).getCapability().getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(pkgName)) {
            String exporter = wires.get(i).getProviderWiring().getBundle().toString();
            StringBuffer sb = new StringBuffer("*** Package '");
            sb.append(pkgName);
            sb.append("' is imported by bundle ");
            sb.append(importer);
            sb.append(" from bundle ");
            sb.append(exporter);
            sb.append(", but the exported package from bundle ");
            sb.append(exporter);
            sb.append(" does not contain the requested class '");
            sb.append(name);
            sb.append("'. Please verify that the class name is correct in the importing bundle ");
            sb.append(importer);
            sb.append(" and/or that the exported package is correctly bundled in ");
            sb.append(exporter);
            sb.append(". ***");
            return sb.toString();
        }
    }
    // Next, check to see if the package was optionally imported and
    // whether or not there is an exporter available.
    List<BundleRequirement> reqs = revision.getWiring().getRequirements(null);
    // Next, check to see if the package is dynamically imported by the revision.
    if (resolver.isAllowedDynamicImport(revision, pkgName)) {
        // Try to see if there is an exporter available.
        Map<String, String> dirs = Collections.EMPTY_MAP;
        Map<String, Object> attrs = Collections.singletonMap(BundleRevision.PACKAGE_NAMESPACE, (Object) pkgName);
        BundleRequirementImpl req = new BundleRequirementImpl(revision, BundleRevision.PACKAGE_NAMESPACE, dirs, attrs);
        List<BundleCapability> exporters = resolver.findProviders(req, false);
        BundleRevision provider = null;
        try {
            provider = resolver.resolve(revision, pkgName);
        } catch (Exception ex) {
            provider = null;
        }
        String exporter = (exporters.isEmpty()) ? null : exporters.iterator().next().toString();
        StringBuffer sb = new StringBuffer("*** Class '");
        sb.append(name);
        sb.append("' was not found, but this is likely normal since package '");
        sb.append(pkgName);
        sb.append("' is dynamically imported by bundle ");
        sb.append(importer);
        sb.append(".");
        if ((exporters.size() > 0) && (provider == null)) {
            sb.append(" However, bundle ");
            sb.append(exporter);
            sb.append(" does export this package with attributes that do not match.");
        }
        sb.append(" ***");
        return sb.toString();
    }
    // Next, check to see if there are any exporters for the package at all.
    Map<String, String> dirs = Collections.EMPTY_MAP;
    Map<String, Object> attrs = Collections.singletonMap(BundleRevision.PACKAGE_NAMESPACE, (Object) pkgName);
    BundleRequirementImpl req = new BundleRequirementImpl(revision, BundleRevision.PACKAGE_NAMESPACE, dirs, attrs);
    List<BundleCapability> exports = resolver.findProviders(req, false);
    if (exports.size() > 0) {
        boolean classpath = false;
        try {
            BundleRevisionImpl.getSecureAction().getClassLoader(BundleClassLoader.class).loadClass(name);
            classpath = true;
        } catch (NoClassDefFoundError err) {
        // Ignore
        } catch (Exception ex) {
        // Ignore
        }
        String exporter = exports.iterator().next().toString();
        StringBuffer sb = new StringBuffer("*** Class '");
        sb.append(name);
        sb.append("' was not found because bundle ");
        sb.append(importer);
        sb.append(" does not import '");
        sb.append(pkgName);
        sb.append("' even though bundle ");
        sb.append(exporter);
        sb.append(" does export it.");
        if (classpath) {
            sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
            sb.append(pkgName);
            sb.append("' to bundle ");
            sb.append(importer);
            sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
            sb.append("2) Add package '");
            sb.append(pkgName);
            sb.append("' to the '");
            sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
            sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
        } else {
            sb.append(" To resolve this issue, add an import for '");
            sb.append(pkgName);
            sb.append("' to bundle ");
            sb.append(importer);
            sb.append(".");
        }
        sb.append(" ***");
        return sb.toString();
    }
    // class loader.
    try {
        BundleRevisionImpl.getSecureAction().getClassLoader(BundleClassLoader.class).loadClass(name);
        StringBuffer sb = new StringBuffer("*** Package '");
        sb.append(pkgName);
        sb.append("' is not imported by bundle ");
        sb.append(importer);
        sb.append(", nor is there any bundle that exports package '");
        sb.append(pkgName);
        sb.append("'. However, the class '");
        sb.append(name);
        sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
        sb.append(pkgName);
        sb.append("' to the '");
        sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
        sb.append("' property and modify bundle ");
        sb.append(importer);
        sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
        sb.append(pkgName);
        sb.append("' to the '");
        sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
        sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
        sb.append(" ***");
        return sb.toString();
    } catch (Exception ex2) {
    }
    // Finally, if there are no imports or exports for the package
    // and it is not available on the system class path, simply
    // log a message saying so.
    StringBuffer sb = new StringBuffer("*** Class '");
    sb.append(name);
    sb.append("' was not found. Bundle ");
    sb.append(importer);
    sb.append(" does not import package '");
    sb.append(pkgName);
    sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
    sb.append(" ***");
    return sb.toString();
}
Also used : BundleWire(org.osgi.framework.wiring.BundleWire) BundleRequirement(org.osgi.framework.wiring.BundleRequirement) BundleRequirementImpl(org.apache.felix.framework.wiring.BundleRequirementImpl) BundleException(org.osgi.framework.BundleException) ResolutionException(org.osgi.service.resolver.ResolutionException) ResourceNotFoundException(org.apache.felix.framework.resolver.ResourceNotFoundException) WeavingException(org.osgi.framework.hooks.weaving.WeavingException) PrivilegedActionException(java.security.PrivilegedActionException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) BundleRevision(org.osgi.framework.wiring.BundleRevision) BundleCapability(org.osgi.framework.wiring.BundleCapability)

Aggregations

BundleRequirementImpl (org.apache.felix.framework.wiring.BundleRequirementImpl)11 ArrayList (java.util.ArrayList)9 BundleRequirement (org.osgi.framework.wiring.BundleRequirement)8 SimpleFilter (org.apache.felix.framework.capabilityset.SimpleFilter)7 BundleCapability (org.osgi.framework.wiring.BundleCapability)5 HashMap (java.util.HashMap)4 LinkedHashMap (java.util.LinkedHashMap)4 BundleException (org.osgi.framework.BundleException)4 BundleRevision (org.osgi.framework.wiring.BundleRevision)3 BundleWire (org.osgi.framework.wiring.BundleWire)3 Capability (org.osgi.resource.Capability)3 List (java.util.List)2 ResolutionException (org.osgi.service.resolver.ResolutionException)2 IOException (java.io.IOException)1 MalformedURLException (java.net.MalformedURLException)1 PrivilegedActionException (java.security.PrivilegedActionException)1 CapabilitySet (org.apache.felix.framework.capabilityset.CapabilitySet)1 CandidateComparator (org.apache.felix.framework.resolver.CandidateComparator)1 ResolveException (org.apache.felix.framework.resolver.ResolveException)1 ResourceNotFoundException (org.apache.felix.framework.resolver.ResourceNotFoundException)1