private Object findClassOrResourceByDelegation(String name, boolean isClass)
throws ClassNotFoundException, ResourceNotFoundException
{
Object result = null;
Set requestSet = (Set) 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);
// 如果该类在父容器类加载器委托清单中(即osgi容器启动参数org.osgi.framework.bootdelegation的值中)
if (shouldBootDelegate(pkgName))
{
try
{
// 根据osgi容器启动参数org.osgi.framework.bundle.parent的值来获得适当的父类加载器
// 默认是bootstrap classloader
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))
{
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;
}
}
}
// 在Import-Package和Require-Bundle中查找是否有该类,有则委托给相应的加载器加载,详见下面searchImports方法的代码
result = searchImports(pkgName, name, isClass);
// 如果还没找到,就在当前bundle的classpath下查找是否有该类,有则加载.
if (result == null)
{
if (isClass)
{
ClassLoader cl = getClassLoaderInternal();
if (cl == null)
{
throw new ClassNotFoundException(
"Unable to load class '"
+ name
+ "' because the bundle wiring for "
+ m_revision.getSymbolicName()
+ " is no longer valid.");
}
result = (Object) ((BundleClassLoader) cl).findClass(name);
}
else
{
result = (Object) m_revision.getResourceLocal(name);
}
// 如果还是没找到,则在DynamicImport-Package中查找和加载
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;
}
// 在Import-Package和Require-Bundle中查找是否有该类,有则委托给相应的加载器加载
private Object searchImports(String pkgName, String name, boolean isClass)
throws ClassNotFoundException, ResourceNotFoundException
{
// 从Import-Package中查找和加载.
BundleRevision provider = m_importedPkgs.get(pkgName);
if (provider != null)
{
// 如果pkgName配置在启动参数org.osgi.framework.system.packages.extra 的值中,
// 则由启动osgi容器的类加载器来加载这个类或者资源,(一般情况是系统类加载器加载)。
// 其classloader来自ExtensionManagerWiring的getClassByDelegation 方法,
// 其实质是ExtensionManagerWiring的getClass().getClassLoader().loadClass(name) 来加载的,
// 而ExtensionManagerWiring类是由启动osgi容器的类加载器加载;
// 如果pkgName未配置在启动参数org.osgi.framework.system.packages.extra的清单中,
// 则用相应的bundle的classloader来加载
Object result = (isClass)
? (Object) ((BundleWiringImpl) provider.getWiring()).getClassByDelegation(name)
: (Object) ((BundleWiringImpl) provider.getWiring()).getResourceByDelegation(name);
if (result != null)
{
return result;
}
// If no class or resource was found, then we must throw an exception
// since the provider of this package did not contain the
// requested class and imported packages are atomic.
if (isClass)
{
throw new ClassNotFoundException(name);
}
throw new ResourceNotFoundException(name);
}
// 从Require-Bundle中查找和加载.
List providers = m_requiredPkgs.get(pkgName);
if (providers != null)
{
for (BundleRevision p : providers)
{
// If we find the class or resource, then return it.
try
{
Object result = (isClass)
? (Object) ((BundleWiringImpl) p.getWiring()).getClassByDelegation(name)
: (Object) ((BundleWiringImpl) p.getWiring()).getResourceByDelegation(name);
if (result != null)
{
return result;
}
}
catch (ClassNotFoundException ex)
{
// Since required packages can be split, don't throw an
// exception here if it is not found. Instead, we'll just
// continue searching other required bundles and the
// revision's local content.
}
}
}
return null;
}