Added class load error diagnostic checking with improved error messages.
Also commented out the default boot delegation configuration property.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@394078 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
index 344e266..0209373 100755
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
@@ -259,13 +259,13 @@
R4Package pkg = Util.getExportPackage(module, pkgName);
if (pkg != null)
{
- return new Object[] {
+ return new Object[] {
pkgName, // Spec title.
pkg.getVersion().toString(), // Spec version.
"", // Spec vendor.
"", // Impl title.
"", // Impl version.
- "" // Impl vendor.
+ "" // Impl vendor.
};
}
return null;
@@ -313,27 +313,35 @@
}
}
- // Look in the module's imports.
- Class clazz = findImportedClass(module, name, pkgName);
-
- // If not found, try the module's own class path.
- if (clazz == null)
+ try
{
- clazz = module.getContentLoader().getClass(name);
-
- // If still not found, then try the module's dynamic imports.
+ // Look in the module's imports.
+ Class clazz = findImportedClass(module, name, pkgName);
+
+ // If not found, try the module's own class path.
if (clazz == null)
{
- clazz = findDynamicallyImportedClass(module, name, pkgName);
+ clazz = module.getContentLoader().getClass(name);
+
+ // If still not found, then try the module's dynamic imports.
+ if (clazz == null)
+ {
+ clazz = findDynamicallyImportedClass(module, name, pkgName);
+ }
}
- }
- if (clazz == null)
+ if (clazz == null)
+ {
+ throw new ClassNotFoundException(name);
+ }
+
+ return clazz;
+ }
+ catch (ClassNotFoundException ex)
{
- throw new ClassNotFoundException(name);
+ diagnoseClassLoadError(module, name, pkgName);
+ throw ex;
}
-
- return clazz;
}
private Class findImportedClass(IModule module, String name, String pkgName)
@@ -370,18 +378,8 @@
// normal static imports.
if (wire != null)
{
- // If we find the class, then return it. Otherwise,
- // throw an exception since the provider of the
- // package did not have the class.
- Class clazz = wire.getClass(name);
- if (clazz != null)
- {
- return clazz;
- }
- else
- {
- throw new ClassNotFoundException(name);
- }
+ // Return the class.
+ return wire.getClass(name);
}
// At this point, the class could not be found by the bundle's static
@@ -411,14 +409,14 @@
// of the R4 search policy classes, nor a class loader or
// class itself, because we want to ignore the calls to
// ClassLoader.loadClass() and Class.forName().
- if (!R4SearchPolicyCore.class.equals(classes[i]) &&
- !R4SearchPolicy.class.equals(classes[i]) &&
- !ClassLoader.class.isAssignableFrom(classes[i]) &&
- !Class.class.isAssignableFrom(classes[i]))
+ if (!R4SearchPolicyCore.class.equals(classes[i])
+ && !R4SearchPolicy.class.equals(classes[i])
+ && !ClassLoader.class.isAssignableFrom(classes[i])
+ && !Class.class.isAssignableFrom(classes[i]))
{
// If the instigating class was not from a bundle, then
// delegate to the parent class loader. Otherwise, break
- // out of loop and throw an exception.
+ // out of loop and return null.
if (!ContentClassLoader.class.isInstance(classes[i].getClassLoader()))
{
return this.getClass().getClassLoader().loadClass(name);
@@ -427,7 +425,7 @@
}
}
- throw new ClassNotFoundException(name);
+ return null;
}
public URL findResource(IModule module, String name)
@@ -479,27 +477,34 @@
}
}
- // Look in the module's imports.
- URL url = findImportedResource(module, name);
-
- // If not found, try the module's own class path.
- if (url == null)
+ try
{
- url = module.getContentLoader().getResource(name);
+ // Look in the module's imports.
+ URL url = findImportedResource(module, name);
- // If still not found, then try the module's dynamic imports.
+ // If not found, try the module's own class path.
if (url == null)
{
- url = findDynamicallyImportedResource(module, name, pkgName);
+ url = module.getContentLoader().getResource(name);
+
+ // If still not found, then try the module's dynamic imports.
+ if (url == null)
+ {
+ url = findDynamicallyImportedResource(module, name, pkgName);
+ }
}
+
+ if (url == null)
+ {
+ throw new ResourceNotFoundException(name);
+ }
+
+ return url;
}
-
- if (url == null)
+ catch (ResourceNotFoundException ex)
{
- throw new ResourceNotFoundException(name);
+ throw ex;
}
-
- return url;
}
private URL findImportedResource(IModule module, String name)
@@ -516,7 +521,7 @@
return url;
}
}
-
+
return null;
}
@@ -528,7 +533,7 @@
// the module's content. Now we make an attempt to load the
// class via a dynamic import, if possible.
R4Wire wire = attemptDynamicImport(module, pkgName);
-
+
// If the dynamic import was successful, then this initial
// time we must directly return the result from dynamically
// created wire, but subsequent requests for resources in
@@ -536,20 +541,10 @@
// normal static imports.
if (wire != null)
{
- // If we find the class, then return it. Otherwise,
- // throw an exception since the provider of the
- // package did not have the class.
- URL url = wire.getResource(name);
- if (url != null)
- {
- return url;
- }
- else
- {
- throw new ResourceNotFoundException(name);
- }
+ // Return the resource.
+ return wire.getResource(name);
}
-
+
// At this point, the resource could not be found by the bundle's static
// or dynamic imports, nor its own resources. Before we throw
// an exception, we will try to determine if the instigator of the
@@ -567,7 +562,7 @@
// parent class loader and we will delegate to it. If the class was
// from a bundle, then we will enforce strict class loading rules
// for the bundle and throw a resource not found exception.
-
+
// Get the class context to see the classes on the stack.
Class[] classes = m_sm.getClassContext();
// Start from 1 to skip security manager class.
@@ -577,14 +572,14 @@
// of the R4 search policy classes, nor a class loader or
// class itself, because we want to ignore the calls to
// ClassLoader.loadClass() and Class.forName().
- if (!R4SearchPolicyCore.class.equals(classes[i]) &&
- !R4SearchPolicy.class.equals(classes[i]) &&
- !ClassLoader.class.isAssignableFrom(classes[i]) &&
- !Class.class.isAssignableFrom(classes[i]))
+ if (!R4SearchPolicyCore.class.equals(classes[i])
+ && !R4SearchPolicy.class.equals(classes[i])
+ && !ClassLoader.class.isAssignableFrom(classes[i])
+ && !Class.class.isAssignableFrom(classes[i]))
{
// If the instigating class was not from a bundle, then
// delegate to the parent class loader. Otherwise, break
- // out of loop and throw an exception.
+ // out of loop and return null.
if (!ContentClassLoader.class.isInstance(classes[i].getClassLoader()))
{
return this.getClass().getClassLoader().getResource(name);
@@ -592,8 +587,8 @@
break;
}
}
-
- throw new ResourceNotFoundException(name);
+
+ return null;
}
private R4Wire attemptDynamicImport(IModule module, String pkgName)
@@ -607,45 +602,8 @@
try
{
- // Check the dynamic import specs for a match of
- // the target package.
- R4Import[] dynamics = getDynamicImports(module);
- R4Import impMatch = null;
- for (int i = 0;
- (impMatch == null) && (dynamics != null) && (i < dynamics.length);
- i++)
- {
- // Star matches everything.
- if (dynamics[i].getName().equals("*"))
- {
- // Create a package instance without wildcard.
- impMatch = new R4Import(
- pkgName,
- dynamics[i].getDirectives(),
- dynamics[i].getAttributes());
- }
- // Packages ending in ".*" must match starting strings.
- else if (dynamics[i].getName().endsWith(".*"))
- {
- if (pkgName.regionMatches(
- 0, dynamics[i].getName(), 0, dynamics[i].getName().length() - 2))
- {
- // Create a package instance without wildcard.
- impMatch = new R4Import(
- pkgName,
- dynamics[i].getDirectives(),
- dynamics[i].getAttributes());
- }
- }
- // Or we can have a precise match.
- else
- {
- if (pkgName.equals(dynamics[i].getName()))
- {
- impMatch = dynamics[i];
- }
- }
- }
+ // Get the matching dynamic import, if any.
+ R4Import impMatch = createDynamicImportTarget(module, pkgName);
// If the target package does not match any dynamically imported
// packages or if the module is already wired for the target package,
@@ -732,6 +690,46 @@
return wire;
}
+ private R4Import createDynamicImportTarget(IModule module, String pkgName)
+ {
+ // Check the dynamic import specs for a match of
+ // the target package.
+ R4Import[] dynamics = getDynamicImports(module);
+ R4Import impMatch = null;
+ for (int i = 0; (impMatch == null) && (dynamics != null)
+ && (i < dynamics.length); i++)
+ {
+ // Star matches everything.
+ if (dynamics[i].getName().equals("*"))
+ {
+ // Create a package instance without wildcard.
+ impMatch = new R4Import(pkgName, dynamics[i]
+ .getDirectives(), dynamics[i].getAttributes());
+ }
+ // Packages ending in ".*" must match starting strings.
+ else if (dynamics[i].getName().endsWith(".*"))
+ {
+ if (pkgName.regionMatches(0, dynamics[i].getName(), 0,
+ dynamics[i].getName().length() - 2))
+ {
+ // Create a package instance without wildcard.
+ impMatch = new R4Import(pkgName, dynamics[i]
+ .getDirectives(), dynamics[i].getAttributes());
+ }
+ }
+ // Or we can have a precise match.
+ else
+ {
+ if (pkgName.equals(dynamics[i].getName()))
+ {
+ impMatch = dynamics[i];
+ }
+ }
+ }
+
+ return impMatch;
+ }
+
public String findLibrary(IModule module, String name)
{
// Remove leading slash, if present.
@@ -761,7 +759,8 @@
// modules are added, removed, or resolved.
synchronized (m_factory)
{
- return getCompatibleExporters((IModule[]) m_availPkgMap.get(pkg.getName()), pkg);
+ return getCompatibleExporters(
+ (IModule[]) m_availPkgMap.get(pkg.getName()), pkg);
}
}
@@ -771,7 +770,8 @@
// modules are added, removed, or resolved.
synchronized (m_factory)
{
- return getCompatibleExporters((IModule[]) m_inUsePkgMap.get(pkg.getName()), pkg);
+ return getCompatibleExporters(
+ (IModule[]) m_inUsePkgMap.get(pkg.getName()), pkg);
}
}
@@ -790,12 +790,12 @@
// candidates to resolve the import and the current selected
// candidate index.
Map resolverMap = new HashMap();
-
+
// This map will be used to hold the final wires for all
// resolved modules, which can then be used to fire resolved
// events outside of the synchronized block.
Map resolvedModuleWireMap = null;
-
+
// Synchronize on the module manager, because we don't want
// any modules being added or removed while we are in the
// middle of this operation.
@@ -826,7 +826,7 @@
// it exhausts all possible combinations and could not find a
// consistent class space.
findConsistentClassSpace(resolverMap, rootModule);
-
+
// The final step is to create the wires for the root module and
// transitively all modules that are to be resolved from the
// selected candidates for resolving the root module's imports.
@@ -836,10 +836,9 @@
// The resolved module wire map maps a module to its array of
// wires.
resolvedModuleWireMap = createWires(resolverMap, rootModule);
-
+
//dumpAvailablePackages();
//dumpUsedPackages();
-
} // End of synchronized block on module manager.
// Fire resolved events for all resolved modules;
@@ -951,8 +950,7 @@
}
}
-
-// TODO: REMOVE THESE DEBUG METHODS.
+// TODO: REMOVE THESE DEBUG METHODS.
private void dumpAvailablePackages()
{
synchronized (this)
@@ -1014,7 +1012,7 @@
throws ResolveException
{
List resolverList = null;
-
+
// Test the current set of candidates to determine if they
// are consistent. Keep looping until we find a consistent
// set or an exception is thrown.
@@ -1037,10 +1035,10 @@
resolverList.add((List) ((Map.Entry) iter.next()).getValue());
}
}
-
+
// Increment the candidate configuration so we can test again.
incrementCandidateConfiguration(resolverList);
-
+
// Clear the cycle map.
cycleMap.clear();
}
@@ -1057,10 +1055,10 @@
{
return true;
}
-
+
// Add to cycle map for future reference.
cycleMap.put(rootModule, rootModule);
-
+
// Create an implicit "uses" constraint for every exported package
// of the root module that is not also imported; uses constraints
// for exported packages that are also imported will be taken
@@ -1076,7 +1074,7 @@
usesMap.put(exports[i].getName(), rootModule);
}
}
-
+
// Loop through the current candidates for the module's imports
// (available in the resolver node list of the resolver map) and
// calculate the uses constraints for each of the currently
@@ -1091,10 +1089,10 @@
// calculating the candidate's transitive "uses" constraints
// for the provided package and testing whether they
// overlap with existing constraints.
-
+
// First, get the resolver node.
ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
-
+
// Verify that the current candidate itself has a consistent
// class space.
if (!isClassSpaceConsistent(
@@ -1102,12 +1100,12 @@
{
return false;
}
-
+
// Get the exported package from the current candidate that
// will be used to resolve the root module's import.
R4Export candidatePkg = Util.getExportPackage(
node.m_candidates[node.m_idx], node.m_import.getName());
-
+
// Calculate the "uses" dependencies implied by the candidate's
// exported package with respect to the currently selected
// candidates in the resolver map.
@@ -1134,14 +1132,14 @@
return false;
}
}
-
+
// Since the current candidate's uses constraints did not
// conflict with existing constraints, merge all constraints
// and keep testing the remaining candidates for the other
// imports of the root module.
usesMap.putAll(candUsesMap);
}
-
+
return true;
}
@@ -1219,7 +1217,7 @@
node = null;
}
}
-
+
// If there is a resolver node for the "used" package,
// then this means that the module imports the package
// and we need to recursively add the constraints of
@@ -1289,7 +1287,7 @@
Map.Entry entry = (Map.Entry) iter.next();
IModule module = (IModule) entry.getKey();
R4Wire[] wires = (R4Wire[]) entry.getValue();
-
+
// Set the module's resolved and wiring attribute.
setResolved(module, true);
// Only add wires attribute if some exist; export
@@ -1298,7 +1296,7 @@
{
setWires(module, wires);
}
-
+
// Remove the wire's exporting module from the "available"
// package map and put it into the "in use" package map;
// these steps may be a no-op.
@@ -1311,7 +1309,7 @@
IModule[] modules = (IModule[]) m_availPkgMap.get(wires[wireIdx].getExport().getName());
modules = removeModuleFromArray(modules, wires[wireIdx].getExportingModule());
m_availPkgMap.put(wires[wireIdx].getExport().getName(), modules);
-
+
// Also remove any exported packages from the "available"
// package map that are from the module associated with
// the current wires where the exported packages were not
@@ -1326,7 +1324,7 @@
modules = removeModuleFromArray(modules, module);
m_availPkgMap.put(wires[wireIdx].getExport().getName(), modules);
}
-
+
// Add the module of the wire to the "in use" package map.
modules = (IModule[]) m_inUsePkgMap.get(wires[wireIdx].getExport().getName());
modules = addModuleToArray(modules, wires[wireIdx].getExportingModule());
@@ -1344,30 +1342,30 @@
{
return wireMap;
}
-
+
List nodeList = (List) resolverMap.get(module);
R4Wire[] wires = new R4Wire[nodeList.size()];
-
+
// Put the module in the wireMap with an empty wire array;
// we do this early so we can use it to detect cycles.
wireMap.put(module, wires);
-
+
// Loop through each resolver node and create a wire
// for the selected candidate for the associated import.
for (int nodeIdx = 0; nodeIdx < nodeList.size(); nodeIdx++)
{
// Get the import's associated resolver node.
ResolverNode node = (ResolverNode) nodeList.get(nodeIdx);
-
+
// Add the candidate to the list of wires.
R4Export export =
Util.getExportPackage(node.m_candidates[node.m_idx], node.m_import.getName());
wires[nodeIdx] = new R4Wire(module, node.m_candidates[node.m_idx], export);
-
+
// Create the wires for the selected candidate module.
wireMap = populateWireMap(resolverMap, node.m_candidates[node.m_idx], wireMap);
}
-
+
return wireMap;
}
@@ -1617,7 +1615,7 @@
// Otherwise, we need to do some array copying.
else
{
- IModule[] newModules= new IModule[modules.length - 1];
+ IModule[] newModules = new IModule[modules.length - 1];
System.arraycopy(modules, 0, newModules, 0, idx);
if (idx < newModules.length)
{
@@ -1700,4 +1698,247 @@
}
}
}
+
+ private void diagnoseClassLoadError(IModule module, String name, String pkgName)
+ {
+ // We will try to do some diagnostics here to help the developer
+ // deal with this exception.
+
+ boolean imported = false;
+ boolean exported = false;
+
+ // First, get the bundle ID of the module doing the class loader.
+ long impId = Util.getBundleIdFromModuleId(module.getId());
+
+ // Next, check to see if the module imports the package.
+ R4Wire[] wires = getWires(module);
+ for (int i = 0; (wires != null) && (i < wires.length); i++)
+ {
+ if (wires[i].getExport().getName().equals(pkgName))
+ {
+ imported = true;
+
+ long expId = Util.getBundleIdFromModuleId(
+ wires[i].getExportingModule().getId());
+
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("Package '");
+ sb.append(pkgName);
+ sb.append("' is imported by bundle ");
+ sb.append(impId);
+ sb.append(" from bundle ");
+ sb.append(expId);
+ sb.append(", but the exported package from bundle ");
+ sb.append(expId);
+ 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(impId);
+ sb.append(" and/or that the exported package is correctly bundled in ");
+ sb.append(expId);
+ sb.append(".");
+ sb.append("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, sb.toString());
+ }
+ }
+
+ // Next, check to see if the package was optionally imported and
+ // whether or not there is an exporter available.
+ if (!imported)
+ {
+ R4Import[] imports = getImports(module);
+ for (int i = 0; (imports != null) && (i < imports.length); i++)
+ {
+ if (imports[i].getName().equals(pkgName) && imports[i].isOptional())
+ {
+ imported = true;
+
+ // Try to see if there is an exporter available. It may be
+ // the case that the package is exported, but the attributes
+ // do not match, so check that case too.
+ IModule[] exporters = getInUseExporters(imports[i]);
+ exporters = (exporters.length == 0)
+ ? getAvailableExporters(imports[i]) : exporters;
+ exporters = (exporters.length == 0)
+ ? getInUseExporters(new R4Import(pkgName, null, null)) : exporters;
+ exporters = (exporters.length == 0)
+ ? getAvailableExporters(new R4Import(pkgName, null, null)) : exporters;
+ long expId = (exporters.length == 0)
+ ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
+
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("Class '");
+ sb.append(name);
+ sb.append("' was not found, but this is likely normal since package '");
+ sb.append(pkgName);
+ sb.append("' is optionally imported by bundle ");
+ sb.append(impId);
+ sb.append(".");
+ if (exporters.length > 0)
+ {
+ sb.append(" However, bundle ");
+ sb.append(expId);
+ if (imports[i].isSatisfied(
+ Util.getExportPackage(exporters[0], imports[i].getName())))
+ {
+ sb.append(" does export this package. Bundle ");
+ sb.append(expId);
+ sb.append(" must be installed before bundle ");
+ sb.append(impId);
+ sb.append(" is resolved or else the optional import will be ignored.");
+ }
+ else
+ {
+ sb.append(" does export this package with attributes that do not match.");
+ }
+ }
+ sb.append("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, sb.toString());
+ }
+ }
+ }
+
+ // Next, check to see if the package is dynamically imported
+ // by the module.
+ if (!imported)
+ {
+ R4Import imp = createDynamicImportTarget(module, pkgName);
+ if (imp != null)
+ {
+ imported = true;
+
+ // Try to see if there is an exporter available. It may be
+ // the case that the package is exported, but the attributes
+ // do not match, so check that case too.
+ IModule[] exporters = getInUseExporters(imp);
+ exporters = (exporters.length == 0)
+ ? getAvailableExporters(imp) : exporters;
+ exporters = (exporters.length == 0)
+ ? getInUseExporters(new R4Import(pkgName, null, null)) : exporters;
+ exporters = (exporters.length == 0)
+ ? getAvailableExporters(new R4Import(pkgName, null, null)) : exporters;
+ long expId = (exporters.length == 0)
+ ? -1 : Util.getBundleIdFromModuleId(exporters[0].getId());
+
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("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(impId);
+ sb.append(".");
+ if (exporters.length > 0)
+ {
+ if (!imp.isSatisfied(
+ Util.getExportPackage(exporters[0], imp.getName())))
+ {
+ sb.append(" However, bundle ");
+ sb.append(expId);
+ sb.append(" does export this package with attributes that do not match.");
+ }
+ }
+ sb.append("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, sb.toString());
+ }
+ }
+
+ // Next, if the package is not imported by the module, check to
+ // see if there is an exporter for the package.
+ if (!imported)
+ {
+ IModule[] exporters = getInUseExporters(new R4Import(pkgName, null, null));
+ exporters = (exporters.length == 0)
+ ? getAvailableExporters(new R4Import(pkgName, null, null)) : exporters;
+ if (exporters.length > 0)
+ {
+ exported = true;
+
+ long expId = Util.getBundleIdFromModuleId(exporters[0].getId());
+
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("Class '");
+ sb.append(name);
+ sb.append("' was not found because bundle ");
+ sb.append(impId);
+ sb.append(" does not import '");
+ sb.append(pkgName);
+ sb.append("' even though bundle ");
+ sb.append(expId);
+ sb.append(" does export it. There are two fixes: 1) Add an import for '");
+ sb.append(pkgName);
+ sb.append("' to bundle ");
+ sb.append(impId);
+ 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.");
+ sb.append("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, sb.toString());
+ }
+ }
+
+ // Next, try to see if the class is available from the system
+ // class loader.
+ if (!imported && !exported)
+ {
+ try
+ {
+ ClassLoader.getSystemClassLoader().loadClass(name);
+
+ exported = true;
+
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("Package '");
+ sb.append(pkgName);
+ sb.append("' is not imported by bundle ");
+ sb.append(impId);
+ 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);
+ sb.append("' property and modify bundle ");
+ sb.append(impId);
+ 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("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, 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.
+ if (!imported && !exported)
+ {
+ StringBuffer sb = new StringBuffer("****\n****\n");
+ sb.append("Class '");
+ sb.append(name);
+ sb.append("' was not found. Bundle ");
+ sb.append(impId);
+ 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("\n****\n****");
+
+ m_logger.log(Logger.LOG_ERROR, sb.toString());
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/org.apache.felix.main/src/main/resources/config.properties b/org.apache.felix.main/src/main/resources/config.properties
index 15382a1..a0ff83b 100644
--- a/org.apache.felix.main/src/main/resources/config.properties
+++ b/org.apache.felix.main/src/main/resources/config.properties
@@ -17,7 +17,7 @@
org.xml.sax, \
javax.xml.parsers, \
javax.imageio
-org.osgi.framework.bootdelegation=sun.*,com.sun.*
+#org.osgi.framework.bootdelegation=sun.*,com.sun.*
#felix.cache.profile=foo
felix.auto.start.1= \
file:bundle/org.apache.felix.shell-${pom.version}.jar \