diff options
author | Thomas Watson | 2016-06-02 21:19:23 +0000 |
---|---|---|
committer | Thomas Watson | 2016-06-03 13:36:12 +0000 |
commit | 9a6165fbb48f1c583c967e6debb1d23250b4fd29 (patch) | |
tree | ba760cc2558fda92b017d0137a6b1c173185d230 | |
parent | f355e41034d9d0a2969dc9331f910da7a7e8d565 (diff) | |
download | rt.equinox.framework-9a6165fbb48f1c583c967e6debb1d23250b4fd29.tar.gz rt.equinox.framework-9a6165fbb48f1c583c967e6debb1d23250b4fd29.tar.xz rt.equinox.framework-9a6165fbb48f1c583c967e6debb1d23250b4fd29.zip |
Bug 495333 - ContextFinder returns null from getResourcesR4_6I20160606-1100I20160603-1000
If there are no classes loaded from bundle class loaders on the
stack then ContextFinder.getResources can return null.
This fix ensures an empty enumeration is returned instead.
Change-Id: I07fe25eeaf8d02ea92cbe130794cdd2a011ae481
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
3 files changed, 110 insertions, 5 deletions
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 b4d6729ee..8f4d2b15b 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 @@ -14,7 +14,11 @@ import java.io.*; import java.lang.reflect.Method; import java.net.*; import java.util.*; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.*; +import javax.jws.WebService; +import javax.xml.namespace.QName; +import javax.xml.ws.Endpoint; +import javax.xml.ws.Service; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.osgi.tests.OSGiTestsActivator; @@ -1672,7 +1676,7 @@ public class ClassLoadingBundleTests extends AbstractBundleTests { ClassLoader contextFinder = getContext().getService(getContext().getServiceReferences(ClassLoader.class, "(equinox.classloader.type=contextClassLoader)").iterator().next()); // Using a resource we know is in java 8. String resource = "META-INF/services/javax.print.PrintServiceLookup"; - URL systemURL = ClassLoader.getSystemClassLoader().getResource("META-INF/services/javax.print.PrintServiceLookup"); + URL systemURL = ClassLoader.getSystemClassLoader().getResource(resource); assertNotNull("Did not find a parent resource: " + resource, systemURL); //should return the file defined in test bundle. URL url = contextFinder.getResource(resource); @@ -1684,6 +1688,80 @@ public class ClassLoadingBundleTests extends AbstractBundleTests { assertEquals(url.toExternalForm(), urls.get(0).toExternalForm()); } + @WebService(endpointInterface = "org.eclipse.osgi.tests.bundles.TestService") + public static class TestServiceImpl implements TestService { + + @Override + public String hello(final String name) { + return "Hello " + name; + } + + } + + /* + * This test depends on the behavior of the JVM Endpoint implementation to use + * the context class loader to try and find resources using an executor. + * This is important because it causes the thread stack to have NO classes + * loaded by a bundle class loader. This causes a condition that would + * make ContextFinder.getResources to return null + */ + public void testContextFinderEmptyGetResources() throws Exception { + // get the context finder explicitly to test incase the thread context class loader has changed + ClassLoader contextFinder = getContext().getService(getContext().getServiceReferences(ClassLoader.class, "(equinox.classloader.type=contextClassLoader)").iterator().next()); + ClassLoader previousTCCL = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(contextFinder); + ExecutorService pool = null; + try { + pool = Executors.newFixedThreadPool(3); + + final String address = "http://localhost:8888/service"; + + final WebService annotation = TestService.class.getAnnotation(WebService.class); + final String namespaceURI = annotation.serviceName(); + final String localPart = annotation.targetNamespace(); + final QName serviceName = new QName(namespaceURI, localPart); + + final TestServiceImpl tsi = new TestServiceImpl(); + final Endpoint endpoint = Endpoint.create(tsi); + final HashMap<String, Object> props = new HashMap<String, Object>(); + props.put(Endpoint.WSDL_SERVICE, serviceName); + + endpoint.setProperties(props); + endpoint.setExecutor(pool); + endpoint.publish(address); + final URL wsdlURL = new URL(address + "?wsdl"); + final Service s = Service.create(wsdlURL, serviceName); + assertNotNull("Service is null.", s); + final TestService port = s.getPort(TestService.class); + + assertEquals("Wrong result.", "Hello World", port.hello("World")); + } finally { + Thread.currentThread().setContextClassLoader(previousTCCL); + if (pool != null) { + pool.shutdown(); + } + } + } + + public void testBundleClassLoaderEmptyGetResources() throws Exception { + final ClassLoader bundleClassLoader = getClass().getClassLoader(); + // Using a resource we know does not exist + final String resource = "META-INF/services/test.does.note.ExistService"; + doTestEmptyGetResources(bundleClassLoader, resource); + } + + private void doTestEmptyGetResources(ClassLoader testClassLoader, String resource) throws Exception { + URL systemURL = ClassLoader.getSystemClassLoader().getResource(resource); + assertNull("Found a parent resource: " + resource, systemURL); + // Should return null resource + URL testurl = testClassLoader.getResource(resource); + assertNull("Found a resource: " + resource, testurl); + + Enumeration<URL> testResources = testClassLoader.getResources(resource); + assertNotNull("null resources from testClassLoader: " + resource, testResources); + assertFalse("Resources has elements.", testResources.hasMoreElements()); + } + public void testBundleReference01() throws Exception { Bundle test = installer.installBundle("test"); //$NON-NLS-1$ Class clazz = test.loadClass("test1.Activator"); //$NON-NLS-1$ diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/TestService.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/TestService.java new file mode 100644 index 000000000..c3d2ea34f --- /dev/null +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/TestService.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.osgi.tests.bundles; + +import javax.jws.WebService; + +@WebService(serviceName = "Foo", targetNamespace = "http://bar") +public interface TestService { + String hello(String name); +} diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java index 5fcfed8d1..2e7f0e319 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java @@ -64,6 +64,10 @@ public class BundleLoader extends ModuleLoader { private static final Pattern PACKAGENAME_FILTER = Pattern.compile("\\(osgi.wiring.package\\s*=\\s*([^)]+)\\)"); //$NON-NLS-1$ + // TODO needed instead of using Collections.emptyEnumertion until we no longer support Java 6 + @SuppressWarnings("rawtypes") + private final static Enumeration EMPTY_ENUMERATION = Collections.enumeration(Collections.emptyList()); + private final ModuleWiring wiring; private final EquinoxContainer container; private final Debug debug; @@ -627,7 +631,7 @@ public class BundleLoader extends ModuleLoader { if ((name.length() > 1) && (name.charAt(0) == '/')) /* if name has a leading slash */ name = name.substring(1); /* remove leading slash before search */ String pkgName = getResourcePackageName(name); - Enumeration<URL> result = Collections.enumeration(Collections.<URL> emptyList()); + Enumeration<URL> result = emptyEnumeration(); boolean bootDelegation = false; // follow the OSGi delegation model // First check the parent classloader for system resources, if it is a java resource. @@ -781,9 +785,9 @@ public class BundleLoader extends ModuleLoader { public static <E> Enumeration<E> compoundEnumerations(Enumeration<E> list1, Enumeration<E> list2) { if (list2 == null || !list2.hasMoreElements()) - return list1; + return list1 == null ? BundleLoader.<E> emptyEnumeration() : list1; if (list1 == null || !list1.hasMoreElements()) - return list2; + return list2 == null ? BundleLoader.<E> emptyEnumeration() : list2; List<E> compoundResults = new ArrayList<E>(); while (list1.hasMoreElements()) compoundResults.add(list1.nextElement()); @@ -795,6 +799,11 @@ public class BundleLoader extends ModuleLoader { return Collections.enumeration(compoundResults); } + @SuppressWarnings("unchecked") + private static <E> Enumeration<E> emptyEnumeration() { + return EMPTY_ENUMERATION; + } + /** * Finds a resource local to this bundle. Only the classloader for this bundle is searched. * @param name The name of the resource to find. |