use of org.eclipse.osgi.internal.hookregistry.ClassLoaderHook in project rt.equinox.framework by eclipse.
the class BundleLoader method getModuleClassLoader.
public ModuleClassLoader getModuleClassLoader() {
ModuleClassLoader result = classloader;
if (result != null) {
return result;
}
// doing optimistic class loader creating here to avoid holding any locks,
// this may result in multiple classloaders being constructed but only one will be used.
final List<ClassLoaderHook> hooks = container.getConfiguration().getHookRegistry().getClassLoaderHooks();
final Generation generation = (Generation) wiring.getRevision().getRevisionInfo();
if (System.getSecurityManager() == null) {
result = createClassLoaderPrivledged(parent, generation.getBundleInfo().getStorage().getConfiguration(), this, generation, hooks);
} else {
final ClassLoader cl = parent;
result = AccessController.doPrivileged(new PrivilegedAction<ModuleClassLoader>() {
@Override
public ModuleClassLoader run() {
return createClassLoaderPrivledged(cl, generation.getBundleInfo().getStorage().getConfiguration(), BundleLoader.this, generation, hooks);
}
});
}
// Not ideal, but hooks really should do little work from classLoaderCreated method.
synchronized (classLoaderCreatedMonitor) {
if (classLoaderCreated == null) {
// must set createdClassloader before calling hooks; otherwise we could enter
// and endless loop if the hook causes re-entry (that would be a bad hook impl)
classLoaderCreated = result;
// only send to hooks if this thread wins in creating the class loader.
final ModuleClassLoader cl = result;
// protect with doPriv to avoid bubbling up permission checks that hooks may require
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
for (ClassLoaderHook hook : hooks) {
hook.classLoaderCreated(cl);
}
return null;
}
});
// finally set the class loader for use after calling hooks
classloader = classLoaderCreated;
} else {
// return the classLoaderCreated here; not the final classloader
// this is necessary in case re-entry by a hook.classLoaderCreated method
result = classLoaderCreated;
if (debug.DEBUG_LOADER) {
// $NON-NLS-1$ //$NON-NLS-2$
Debug.println("BundleLoader[" + this + "].getModuleClassLoader() - created duplicate classloader");
}
}
}
return result;
}
use of org.eclipse.osgi.internal.hookregistry.ClassLoaderHook in project rt.equinox.framework by eclipse.
the class ClasspathManager method findLocalResource.
/**
* Finds a local resource by searching the ClasspathEntry objects of the classpath manager.
* This method will first call all the configured class loading hooks
* {@link ClassLoaderHook#preFindLocalResource(String, ClasspathManager)} methods. Then it
* will search for the resource. Finally it will call all the configured class loading hooks
* {@link ClassLoaderHook#postFindLocalResource(String, URL, ClasspathManager)} methods.
* @param resource the requested resource name.
* @return the requested resource URL or null if the resource does not exist
*/
public URL findLocalResource(String resource) {
List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
for (ClassLoaderHook hook : hooks) {
hook.preFindLocalResource(resource, this);
}
URL result = null;
try {
result = findLocalResourceImpl(resource, -1);
return result;
} finally {
for (ClassLoaderHook hook : hooks) {
hook.postFindLocalResource(resource, result, this);
}
}
}
use of org.eclipse.osgi.internal.hookregistry.ClassLoaderHook in project rt.equinox.framework by eclipse.
the class ClasspathManager method defineClass.
/**
* Defines the specified class. This method will first call all the configured class loader hooks
* {@link ClassLoadingHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods. If any hook modifies the bytes the all configured hook
* {@link ClassLoaderHook#rejectTransformation(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods are called. Then it will call the {@link ModuleClassLoader#defineClass(String, byte[], ClasspathEntry, BundleEntry)}
* method to define the class. After that, the class loader hooks are called to announce the class
* definition by calling {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}.
* @param name the name of the class to define
* @param classbytes the class bytes
* @param classpathEntry the classpath entry used to load the class bytes
* @param entry the BundleEntry used to load the class bytes
* @param hooks the class loader hooks
* @return the defined class
*/
private Class<?> defineClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, List<ClassLoaderHook> hooks) {
DefineClassResult result = null;
boolean recursionDetected = false;
try {
definePackage(name, classpathEntry);
DefineContext context = currentDefineContext.get();
if (context == null) {
context = new DefineContext();
currentDefineContext.set(context);
}
// First call the hooks that do not handle recursion themselves
if (!hookRegistry.getContainer().isProcessClassRecursionSupportedByAll()) {
// We need to detect recursions for this set of hooks.
if (context.currentlyProcessing.contains(name)) {
// Avoid recursion for the same class name for these hooks
recursionDetected = true;
// TODO consider thrown a ClassCircularityError here
return null;
}
context.currentlyProcessing.add(name);
try {
for (ClassLoaderHook hook : hooks) {
if (!hook.isProcessClassRecursionSupported()) {
classbytes = processClass(hook, name, classbytes, classpathEntry, entry, this, hooks);
}
}
} finally {
context.currentlyProcessing.remove(name);
}
}
// Now call the hooks that do support recursion without the check.
for (ClassLoaderHook hook : hooks) {
if (hook.isProcessClassRecursionSupported()) {
// Note if the hooks don't take protective measures for a recursive class load here
// it will result in a stack overflow.
classbytes = processClass(hook, name, classbytes, classpathEntry, entry, this, hooks);
}
}
if (context.currentlyDefining.contains(name)) {
// avoid recursive defines (bug 345500)
return null;
}
context.currentlyDefining.add(name);
try {
result = classloader.defineClass(name, classbytes, classpathEntry);
} finally {
context.currentlyDefining.remove(name);
}
} finally {
// only call hooks if we properly called processClass above
if (!recursionDetected) {
// only pass the newly defined class to the hook
Class<?> defined = result != null && result.defined ? result.clazz : null;
for (ClassLoaderHook hook : hooks) {
hook.recordClassDefine(name, defined, classbytes, classpathEntry, entry, this);
}
}
}
// return either the pre-loaded class or the newly defined class
return result == null ? null : result.clazz;
}
use of org.eclipse.osgi.internal.hookregistry.ClassLoaderHook in project rt.equinox.framework by eclipse.
the class ClasspathManager method findLocalClass.
/**
* Finds a local class by searching the ClasspathEntry objects of the classpath manager.
* This method will first call all the configured class loader hooks
* {@link ClassLoaderHook#preFindLocalClass(String, ClasspathManager)} methods. Then it
* will search for the class. If a class is found then
* <ol>
* <li>All configured class loader hooks
* {@link ClassLoaderHook#processClass(String, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods will be called.</li>
* <li>The class is then defined.</li>
* <li>Finally, all configured class loading
* stats hooks {@link ClassLoaderHook#recordClassDefine(String, Class, byte[], ClasspathEntry, BundleEntry, ClasspathManager)}
* methods are called.</li>
* </ol>
* Finally all the configured class loading hooks
* {@link ClassLoaderHook#postFindLocalClass(String, Class, ClasspathManager)} methods are called.
* @param classname the requested class name.
* @return the requested class
* @throws ClassNotFoundException if the class does not exist
*/
public Class<?> findLocalClass(String classname) throws ClassNotFoundException {
Class<?> result = null;
List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks();
try {
for (ClassLoaderHook hook : hooks) {
hook.preFindLocalClass(classname, this);
}
result = classloader.publicFindLoaded(classname);
if (result != null)
return result;
result = findLocalClassImpl(classname, hooks);
return result;
} finally {
for (ClassLoaderHook hook : hooks) {
hook.postFindLocalClass(classname, result, this);
}
}
}
Aggregations