in framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java [1414:1599]
private Object findClassOrResourceByDelegation(String name, boolean isClass)
throws ClassNotFoundException, ResourceNotFoundException
{
Object result = null;
Set<String> requestSet = m_cycleCheck.get();
if (requestSet == null)
{
requestSet = new HashSet<>();
m_cycleCheck.set(requestSet);
}
if (requestSet.add(name))
{
try
{
// Get the package of the target class/resource.
String pkgName = (isClass) ? Util.getClassPackage(name) : Util.getResourcePackage(name);
boolean accessor = name.startsWith("sun.reflect.Generated") || name.startsWith("jdk.internal.reflect.");
if (accessor)
{
if (m_accessorLookupCache == null)
{
m_accessorLookupCache = new ConcurrentHashMap<>();
}
ClassLoader loader = m_accessorLookupCache.get(name);
if (loader != null)
{
return loader.loadClass(name);
}
}
// Delegate any packages listed in the boot delegation
// property to the parent class loader.
if (shouldBootDelegate(pkgName))
{
try
{
// Get the appropriate class loader for delegation.
ClassLoader bdcl = getBootDelegationClassLoader();
result = (isClass) ? (Object) bdcl.loadClass(name) : (Object) bdcl.getResource(name);
// If this is a java.* package, then always terminate the
// search; otherwise, continue to look locally if not found.
if (pkgName.startsWith("java.") || (result != null))
{
if (accessor)
{
m_accessorLookupCache.put(name, bdcl);
}
return result;
}
}
catch (ClassNotFoundException ex)
{
// If this is a java.* package, then always terminate the
// search; otherwise, continue to look locally if not found.
if (pkgName.startsWith("java."))
{
throw ex;
}
}
}
if (accessor)
{
List<Collection<BundleRevision>> allRevisions = new ArrayList<>( 1 + m_requiredPkgs.size());
allRevisions.add(m_importedPkgs.values());
allRevisions.addAll(m_requiredPkgs.values());
for (Collection<BundleRevision> revisions : allRevisions)
{
for (BundleRevision revision : revisions)
{
ClassLoader loader = revision.getWiring().getClassLoader();
if (loader instanceof BundleClassLoader)
{
BundleClassLoader bundleClassLoader = (BundleClassLoader) loader;
result = bundleClassLoader.findLoadedClassInternal(name);
if (result != null)
{
m_accessorLookupCache.put(name, bundleClassLoader);
return result;
}
}
}
}
try
{
// Get the appropriate class loader for delegation.
ClassLoader bdcl = getBootDelegationClassLoader();
result = (isClass) ? (Object) bdcl.loadClass(name) : (Object) bdcl.getResource(name);
if (result != null)
{
m_accessorLookupCache.put(name, bdcl);
return result;
}
}
catch (ClassNotFoundException ex)
{
}
m_accessorLookupCache.put(name, CNFE_CLASS_LOADER);
CNFE_CLASS_LOADER.loadClass(name);
}
// Look in the revision's imports. Note that the search may
// be aborted if this method throws an exception, otherwise
// it continues if a null is returned.
result = searchImports(pkgName, name, isClass);
// If not found, try the revision's own class path.
if (result == null)
{
ClassLoader cl = getClassLoaderInternal();
if (cl == null)
{
if (isClass)
{
throw new ClassNotFoundException(
"Unable to load class '"
+ name
+ "' because the bundle wiring for "
+ m_revision.getSymbolicName()
+ " is no longer valid.");
}
else
{
throw new ResourceNotFoundException("Unable to load resource '"
+ name
+ "' because the bundle wiring for "
+ m_revision.getSymbolicName()
+ " is no longer valid.");
}
}
if (cl instanceof BundleClassLoader)
{
result = isClass ? ((BundleClassLoader) cl).findClass(name) :
((BundleClassLoader) cl).findResource(name);
}
else
{
result = isClass ? cl.loadClass(name) : !name.startsWith("/") ? cl.getResource(name) :
cl.getResource(name.substring(1));
}
// If still not found, then try the revision's dynamic imports.
if (result == null)
{
result = searchDynamicImports(pkgName, name, isClass);
}
}
}
finally
{
requestSet.remove(name);
}
}
else
{
// If a cycle is detected, we should return null to break the
// cycle. This should only ever be return to internal class
// loading code and not to the actual instigator of the class load.
return null;
}
if (result == null)
{
if (isClass)
{
throw new ClassNotFoundException(
name + " not found by " + this.getBundle());
}
else
{
throw new ResourceNotFoundException(
name + " not found by " + this.getBundle());
}
}
return result;
}