diff options
author | Thomas Watson | 2019-02-15 15:41:54 +0000 |
---|---|---|
committer | Thomas Watson | 2019-02-15 16:43:17 +0000 |
commit | 9e200a3c15f8161fef93b241012ecb3d0f1f1b7d (patch) | |
tree | e0a86411948a370e61ce2f8f17203afc4807a417 | |
parent | 27e73a64c9a38f98b23838f2279c227238541f09 (diff) | |
download | rt.equinox.framework-9e200a3c15f8161fef93b241012ecb3d0f1f1b7d.tar.gz rt.equinox.framework-9e200a3c15f8161fef93b241012ecb3d0f1f1b7d.tar.xz rt.equinox.framework-9e200a3c15f8161fef93b241012ecb3d0f1f1b7d.zip |
Bug 544477 - allow hook to prevent resource load
Change-Id: I6286f7b427d54ad0f3961bd2b21658cb573552d7
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
4 files changed, 78 insertions, 12 deletions
diff --git a/bundles/org.eclipse.osgi.tests/bundles_src/classloader.hooks.a/org/eclipse/osgi/tests/classloader/hooks/a/TestHookConfigurator.java b/bundles/org.eclipse.osgi.tests/bundles_src/classloader.hooks.a/org/eclipse/osgi/tests/classloader/hooks/a/TestHookConfigurator.java index 61e86e9a0..0daec7d29 100644 --- a/bundles/org.eclipse.osgi.tests/bundles_src/classloader.hooks.a/org/eclipse/osgi/tests/classloader/hooks/a/TestHookConfigurator.java +++ b/bundles/org.eclipse.osgi.tests/bundles_src/classloader.hooks.a/org/eclipse/osgi/tests/classloader/hooks/a/TestHookConfigurator.java @@ -13,6 +13,8 @@ *******************************************************************************/ package org.eclipse.osgi.tests.classloader.hooks.a; +import java.net.URL; +import java.util.NoSuchElementException; import org.eclipse.osgi.container.Module; import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook; import org.eclipse.osgi.internal.hookregistry.HookConfigurator; @@ -27,6 +29,8 @@ public class TestHookConfigurator implements HookConfigurator { private static final String RECURSION_LOAD = "classloader.hooks.a.recursion.load"; private static final String RECURSION_LOAD_SUPPORTED = "classloader.hooks.a.recursion.load.supported"; private static final String FILTER_CLASS_PATHS = "classloader.hooks.a.filter.class.paths"; + private static final String PREVENT_RESOURCE_LOAD_PRE = "classloader.hooks.a.fail.resource.load.pre"; + private static final String PREVENT_RESOURCE_LOAD_POST = "classloader.hooks.a.fail.resource.load.post"; final ThreadLocal<Boolean> doingRecursionLoad = new ThreadLocal<Boolean>() { protected Boolean initialValue() { return false; @@ -81,6 +85,20 @@ public class TestHookConfigurator implements HookConfigurator { } return super.getClassPathEntries(name, manager); } + + @Override + public void preFindLocalResource(String name, ClasspathManager manager) { + if (Boolean.getBoolean(PREVENT_RESOURCE_LOAD_PRE)) { + throw new NoSuchElementException(); + } + } + + @Override + public void postFindLocalResource(String name, URL resource, ClasspathManager manager) { + if (Boolean.getBoolean(PREVENT_RESOURCE_LOAD_POST)) { + throw new NoSuchElementException(); + } + } }); } } diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ClassLoaderHookTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ClassLoaderHookTests.java index 131d77a03..3185a16c9 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ClassLoaderHookTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/hooks/framework/ClassLoaderHookTests.java @@ -37,6 +37,7 @@ import org.osgi.framework.wiring.FrameworkWiring; public class ClassLoaderHookTests extends AbstractFrameworkHookTests { private static final String TEST_BUNDLE = "substitutes.a"; private static final String TEST_CLASSNAME = "substitutes.x.Ax"; + private static final String TEST_CLASSNAME_RESOURCE = "substitutes/x/Ax.class"; private static final String HOOK_CONFIGURATOR_BUNDLE = "classloader.hooks.a"; private static final String HOOK_CONFIGURATOR_CLASS = "org.eclipse.osgi.tests.classloader.hooks.a.TestHookConfigurator"; private static final String REJECT_PROP = "classloader.hooks.a.reject"; @@ -44,6 +45,8 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { private static final String RECURSION_LOAD = "classloader.hooks.a.recursion.load"; private static final String RECURSION_LOAD_SUPPORTED = "classloader.hooks.a.recursion.load.supported"; private static final String FILTER_CLASS_PATHS = "classloader.hooks.a.filter.class.paths"; + private static final String PREVENT_RESOURCE_LOAD_PRE = "classloader.hooks.a.fail.resource.load.pre"; + private static final String PREVENT_RESOURCE_LOAD_POST = "classloader.hooks.a.fail.resource.load.post"; private Map<String, String> configuration; private Framework framework; @@ -56,6 +59,8 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { setRecursionLoad(false); setRecursionLoadSupported(false); setFilterClassPaths(false); + setPreventResourceLoadPre(false); + setPreventResourceLoadPost(false); String loc = bundleInstaller.getBundleLocation(HOOK_CONFIGURATOR_BUNDLE); loc = loc.substring(loc.indexOf("file:")); classLoader.addURL(new URL(loc)); @@ -100,6 +105,14 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { System.setProperty(FILTER_CLASS_PATHS, Boolean.toString(value)); } + private void setPreventResourceLoadPre(boolean value) { + System.setProperty(PREVENT_RESOURCE_LOAD_PRE, Boolean.toString(value)); + } + + private void setPreventResourceLoadPost(boolean value) { + System.setProperty(PREVENT_RESOURCE_LOAD_POST, Boolean.toString(value)); + } + public void testRejectTransformationFromWeavingHook() throws Exception { setRejectTransformation(true); initAndStartFramework(); @@ -193,4 +206,22 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { // expected } } + + public void testPreventResourceLoadFromClassLoadingHook() throws Exception { + setPreventResourceLoadPre(false); + setPreventResourceLoadPost(false); + initAndStartFramework(); + Bundle b = installBundle(); + URL resource = b.getResource(TEST_CLASSNAME_RESOURCE); + assertNotNull("Could not find resource.", resource); + + setPreventResourceLoadPre(true); + resource = b.getResource(TEST_CLASSNAME_RESOURCE); + assertNull("Could find resource.", resource); + + setPreventResourceLoadPre(false); + setPreventResourceLoadPost(true); + resource = b.getResource(TEST_CLASSNAME_RESOURCE); + assertNull("Could find resource.", resource); + } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java index 557544b60..8e0a52949 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java @@ -18,6 +18,7 @@ import java.io.FileNotFoundException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.NoSuchElementException; import org.eclipse.osgi.internal.framework.EquinoxConfiguration; import org.eclipse.osgi.internal.loader.BundleLoader; import org.eclipse.osgi.internal.loader.ModuleClassLoader; @@ -61,7 +62,7 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager when looking for ClasspathEntry objects. This method allows - * a classloading hook to add additional ClasspathEntry objects + * a class loading hook to add additional ClasspathEntry objects * @param cpEntries the list of ClasspathEntry objects currently available for the requested classpath * @param cp the name of the requested classpath * @param hostmanager the classpath manager the requested ClasspathEntry is for @@ -223,7 +224,7 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} before * searching the local classloader for a class. A classpath manager will call this method for - * each configured class loading stat hook. + * each configured class loading hook. * @param name the name of the requested class * @param manager the classpath manager used to find and load the requested class * @throws ClassNotFoundException to prevent the requested class from loading @@ -235,11 +236,12 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager during {@link ClasspathManager#findLocalClass(String)} after * searching the local classloader for a class. A classpath manager will call this method for - * each configured class loading stat hook. + * each configured class loading hook. * @param name the name of the requested class * @param clazz the loaded class or null if not found * @param manager the classpath manager used to find and load the requested class - * @throws ClassNotFoundException + * @throws ClassNotFoundException to prevent the requested class from loading. This is highly discouraged + * because if the class is non-null it is already too late to throw an exception. */ public void postFindLocalClass(String name, Class<?> clazz, ClasspathManager manager) throws ClassNotFoundException { // do nothing @@ -248,9 +250,10 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} before * searching the local classloader for a resource. A classpath manager will call this method for - * each configured class loading stat hook. + * each configured class loading hook. * @param name the name of the requested resource * @param manager the classpath manager used to find the requested resource + * @throws NoSuchElementException will prevent the local resource from loading */ public void preFindLocalResource(String name, ClasspathManager manager) { // do nothing @@ -259,10 +262,11 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager during {@link ClasspathManager#findLocalResource(String)} after * searching the local classloader for a resource. A classpath manager will call this method for - * each configured class loading stat hook. + * each configured class loading hook. * @param name the name of the requested resource * @param resource the URL to the requested resource or null if not found * @param manager the classpath manager used to find the requested resource + * @throws NoSuchElementException will prevent the local resource from loading */ public void postFindLocalResource(String name, URL resource, ClasspathManager manager) { // do nothing @@ -270,7 +274,7 @@ public abstract class ClassLoaderHook { /** * Gets called by a classpath manager after an attempt is made to define a class. This method allows - * a class loading stat hook to record data about a class definition. + * a class loading hook to record data about a class definition. * @param name the name of the class that got defined * @param clazz the class object that got defined or null if an error occurred while defining a class * @param classbytes the class bytes used to define the class diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java index af0115e47..dc6ea5bb1 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java @@ -25,6 +25,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.ListIterator; +import java.util.NoSuchElementException; import org.eclipse.osgi.container.Module; import org.eclipse.osgi.container.ModuleCapability; import org.eclipse.osgi.container.ModuleContainerAdaptor.ContainerEvent; @@ -357,18 +358,30 @@ public class ClasspathManager { */ public URL findLocalResource(String resource) { List<ClassLoaderHook> hooks = hookRegistry.getClassLoaderHooks(); + boolean hookFailed = false; for (ClassLoaderHook hook : hooks) { - hook.preFindLocalResource(resource, this); + try { + hook.preFindLocalResource(resource, this); + } catch (NoSuchElementException e) { + // mark the resource load as failed, but continue to all the hooks + hookFailed = true; + } } URL result = null; try { - result = findLocalResourceImpl(resource, -1); - return result; + if (!hookFailed) { + result = findLocalResourceImpl(resource, -1); + } } finally { for (ClassLoaderHook hook : hooks) { - hook.postFindLocalResource(resource, result, this); + try { + hook.postFindLocalResource(resource, result, this); + } catch (NoSuchElementException e) { + result = null; + } } } + return result; } private URL findLocalResourceImpl(String resource, int classPathIndex) { @@ -431,7 +444,7 @@ public class ClasspathManager { ClasspathEntry[] hookEntries = hook.getClassPathEntries(resource, this); if (hookEntries != null) { findLocalResources(resource, hookEntries, m, classPathIndex, resources); - return resources.size() > 0 ? Collections.enumeration(resources): EMPTY_ENUMERATION; + return resources.size() > 0 ? Collections.enumeration(resources) : EMPTY_ENUMERATION; } } |