Search in sources :

Example 6 with ClassLoaderHook

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;
}
Also used : Generation(org.eclipse.osgi.storage.BundleInfo.Generation) ClassLoaderHook(org.eclipse.osgi.internal.hookregistry.ClassLoaderHook) PrivilegedAction(java.security.PrivilegedAction)

Example 7 with ClassLoaderHook

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);
        }
    }
}
Also used : ClassLoaderHook(org.eclipse.osgi.internal.hookregistry.ClassLoaderHook) URL(java.net.URL)

Example 8 with ClassLoaderHook

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;
}
Also used : ClassLoaderHook(org.eclipse.osgi.internal.hookregistry.ClassLoaderHook) DefineClassResult(org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult)

Example 9 with ClassLoaderHook

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);
        }
    }
}
Also used : ClassLoaderHook(org.eclipse.osgi.internal.hookregistry.ClassLoaderHook)

Aggregations

ClassLoaderHook (org.eclipse.osgi.internal.hookregistry.ClassLoaderHook)9 FileNotFoundException (java.io.FileNotFoundException)1 URL (java.net.URL)1 PrivilegedAction (java.security.PrivilegedAction)1 DefineClassResult (org.eclipse.osgi.internal.loader.ModuleClassLoader.DefineClassResult)1 Generation (org.eclipse.osgi.storage.BundleInfo.Generation)1 ManifestElement (org.eclipse.osgi.util.ManifestElement)1 BundleException (org.osgi.framework.BundleException)1