diff options
author | Thomas Watson | 2017-02-28 15:03:45 +0000 |
---|---|---|
committer | Thomas Watson | 2017-03-02 20:50:36 +0000 |
commit | 64c504c7f56e523b3a70c065bf793acc7c397487 (patch) | |
tree | ab116274d3bfc00d447054f407a49652f7f72327 /bundles/org.eclipse.osgi.tests | |
parent | 6e3d3967c4052a93abc26281fe7809f4abbc5e69 (diff) | |
download | rt.equinox.framework-64c504c7f56e523b3a70c065bf793acc7c397487.tar.gz rt.equinox.framework-64c504c7f56e523b3a70c065bf793acc7c397487.tar.xz rt.equinox.framework-64c504c7f56e523b3a70c065bf793acc7c397487.zip |
Bug 512707 - Add support for recursive class processingY20170321-2315Y20170321-0120Y20170316-0500Y20170309-1000S4_7_0_M6I20170327-2000I20170326-2000I20170325-2000I20170324-2000I20170323-2000I20170322-2000I20170321-2000I20170320-2000I20170319-2000I20170318-2000I20170317-2000I20170316-2000I20170315-2000I20170315-0500I20170314-2000I20170313-2000I20170312-2000I20170311-2000I20170310-2000I20170308-2000I20170308-0800I20170307-2000I20170307-0800I20170307-0610I20170307-0450I20170307-0420I20170307-0410I20170307-0150I20170306-2000I20170306-0800I20170305-2000I20170304-2000I20170303-2000I20170302-2000
Change-Id: I3223216586d1cb5bf399132b26293cf0e787377f
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
Diffstat (limited to 'bundles/org.eclipse.osgi.tests')
3 files changed, 146 insertions, 3 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 0259d4fd2..db458e144 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2016 IBM Corporation and others. + * Copyright (c) 2013, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.osgi.tests.classloader.hooks.a; +import org.eclipse.osgi.container.Module; import org.eclipse.osgi.internal.hookregistry.*; import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry; import org.eclipse.osgi.internal.loader.classpath.ClasspathManager; @@ -18,6 +19,13 @@ import org.eclipse.osgi.storage.bundlefile.BundleEntry; public class TestHookConfigurator implements HookConfigurator { private static final String REJECT_PROP = "classloader.hooks.a.reject"; private static final String BAD_TRANSFORM_PROP = "classloader.hooks.a.bad.transform"; + private static final String RECURSION_LOAD = "classloader.hooks.a.recursion.load"; + private static final String RECURSION_LOAD_SUPPORTED = "classloader.hooks.a.recursion.load.supported"; + final ThreadLocal<Boolean> doingRecursionLoad = new ThreadLocal<Boolean>() { + protected Boolean initialValue() { + return false; + }; + }; public void addHooks(HookRegistry hookRegistry) { hookRegistry.addClassLoaderHook(new ClassLoaderHook() { @@ -32,9 +40,34 @@ public class TestHookConfigurator implements HookConfigurator { if (Boolean.getBoolean(BAD_TRANSFORM_PROP)) { return new byte[] {'b', 'a', 'd', 'b', 'y', 't', 'e', 's'}; } + if (Boolean.getBoolean(RECURSION_LOAD)) { + if (isProcessClassRecursionSupported() && doingRecursionLoad.get()) { + return null; + } + Module m = manager.getGeneration().getBundleInfo().getStorage().getModuleContainer().getModule(1); + doingRecursionLoad.set(true); + try { + m.getCurrentRevision().getWiring().getClassLoader().loadClass("substitutes.x.Ax"); + if (!isProcessClassRecursionSupported()) { + throw new LinkageError("Recursion is no supported."); + } + } catch (ClassNotFoundException e) { + if (isProcessClassRecursionSupported()) { + throw new LinkageError("Recursion should be supported."); + } + // expected + } finally { + doingRecursionLoad.set(false); + } + } return null; } + @Override + public boolean isProcessClassRecursionSupported() { + return Boolean.getBoolean(RECURSION_LOAD_SUPPORTED); + } + }); } } diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java index 20fbe4366..1acbfb4a1 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/ClassLoadingBundleTests.java @@ -15,6 +15,7 @@ import java.lang.reflect.Method; import java.net.*; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; import javax.jws.WebService; import javax.xml.namespace.QName; import javax.xml.ws.Endpoint; @@ -25,6 +26,8 @@ import org.eclipse.osgi.tests.OSGiTestsActivator; import org.osgi.framework.*; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.hooks.resolver.ResolverHookFactory; +import org.osgi.framework.hooks.weaving.WeavingHook; +import org.osgi.framework.hooks.weaving.WovenClass; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.framework.wiring.*; import org.osgi.service.packageadmin.ExportedPackage; @@ -2221,6 +2224,84 @@ public class ClassLoadingBundleTests extends AbstractBundleTests { } } + public void testRecursiveWeavingHookFactory() { + final ThreadLocal<Boolean> testThread = new ThreadLocal<Boolean>() { + @Override + protected Boolean initialValue() { + return Boolean.FALSE; + } + }; + + testThread.set(Boolean.TRUE); + final Set<String> weavingHookClasses = new HashSet<String>(); + final List<WovenClass> called = new ArrayList<WovenClass>(); + final AtomicBoolean loadNewClassInWeave = new AtomicBoolean(false); + + ServiceFactory<WeavingHook> topFactory = new ServiceFactory<WeavingHook>() { + @Override + public WeavingHook getService(Bundle bundle, ServiceRegistration<WeavingHook> registration) { + if (!testThread.get()) { + return null; + } + WeavingHook hook = new WeavingHook() { + + @Override + public void weave(WovenClass wovenClass) { + if (loadNewClassInWeave.get()) { + // Force a load of inner class + Runnable run = new Runnable() { + @Override + public void run() { + // nothing + } + }; + run.run(); + weavingHookClasses.add(run.getClass().getName()); + } + called.add(wovenClass); + } + }; + weavingHookClasses.add(hook.getClass().getName()); + return hook; + } + + @Override + public void ungetService(Bundle bundle, ServiceRegistration<WeavingHook> registration, WeavingHook service) { + // nothing + } + }; + ServiceRegistration<WeavingHook> reg = getContext().registerService(WeavingHook.class, topFactory, null); + + Runnable run = null; + try { + // force call to factory without protection of the framework recursion checks + topFactory.getService(null, null); + + // set flag to load inner class while weaving + loadNewClassInWeave.set(true); + + // Force a load of inner class + run = new Runnable() { + @Override + public void run() { + // nothing + } + }; + run.run(); + } finally { + reg.unregister(); + } + + assertEquals("Unexpected number of woven classes.", 3, called.size()); + for (WovenClass wovenClass : called) { + if (weavingHookClasses.contains(wovenClass.getClassName())) { + assertNull("Did not expect to find class: " + wovenClass.getDefinedClass(), wovenClass.getDefinedClass()); + } else { + assertEquals("Expected the inner runnable class.", run.getClass(), wovenClass.getDefinedClass()); + } + } + } + public void testLoaderUninstalledBundle() throws BundleException, IOException { String testResourcePath = "testResource"; File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$ 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 56d2b76e1..d342e8ecd 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2016 IBM Corporation and others. + * Copyright (c) 2013, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -32,6 +32,8 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { 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"; private static final String BAD_TRANSFORM_PROP = "classloader.hooks.a.bad.transform"; + 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 Map<String, String> configuration; private Framework framework; @@ -41,6 +43,8 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { super.setUp(); setRejectTransformation(false); setBadTransform(false); + setRecursionLoad(false); + setRecursionLoadSupported(false); String loc = bundleInstaller.getBundleLocation(HOOK_CONFIGURATOR_BUNDLE); loc = loc.substring(loc.indexOf("file:")); classLoader.addURL(new URL(loc)); @@ -65,7 +69,7 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { return framework.getBundleContext().installBundle(location); } - private void setRejectTransformation(boolean value) throws Exception { + private void setRejectTransformation(boolean value) { System.setProperty(REJECT_PROP, Boolean.toString(value)); } @@ -73,6 +77,14 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { System.setProperty(BAD_TRANSFORM_PROP, Boolean.toString(value)); } + private void setRecursionLoad(boolean value) { + System.setProperty(RECURSION_LOAD, Boolean.toString(value)); + } + + private void setRecursionLoadSupported(boolean value) { + System.setProperty(RECURSION_LOAD_SUPPORTED, Boolean.toString(value)); + } + public void testRejectTransformationFromWeavingHook() throws Exception { setRejectTransformation(true); initAndStartFramework(); @@ -95,6 +107,7 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { refreshBundles(Collections.singleton(b)); try { b.loadClass(TEST_CLASSNAME); + fail("Expected a ClassFormatError."); } catch (ClassFormatError e) { // expected } @@ -115,11 +128,27 @@ public class ClassLoaderHookTests extends AbstractFrameworkHookTests { refreshBundles(Collections.singleton(b)); try { b.loadClass(TEST_CLASSNAME); + fail("Expected a ClassFormatError."); } catch (ClassFormatError e) { // expected } } + public void testRecursionFromClassLoadingHookNotSupported() throws Exception { + setRecursionLoad(true); + initAndStartFramework(); + Bundle b = installBundle(); + b.loadClass(TEST_CLASSNAME); + } + + public void testRecursionFromClassLoadingHookIsSupported() throws Exception { + setRecursionLoad(true); + setRecursionLoadSupported(true); + initAndStartFramework(); + Bundle b = installBundle(); + b.loadClass(TEST_CLASSNAME); + } + private void refreshBundles(Collection<Bundle> bundles) throws InterruptedException { final CountDownLatch refreshSignal = new CountDownLatch(1); framework.adapt(FrameworkWiring.class).refreshBundles(bundles, new FrameworkListener() { |