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();
}
Aggregations