diff options
author | Thomas Watson | 2020-07-27 15:26:23 +0000 |
---|---|---|
committer | Thomas Watson | 2020-07-27 15:29:12 +0000 |
commit | 16056e80642d4dc9708672243c05b3917b764ecd (patch) | |
tree | c81caaa5ffe2156a70cbb099df14c6f0c0583d50 | |
parent | b09ea5dba4030ea2685ba3e72f05a6c9361839ff (diff) | |
download | rt.equinox.framework-I20200801-0010.tar.gz rt.equinox.framework-I20200801-0010.tar.xz rt.equinox.framework-I20200801-0010.zip |
Bug 565522 - EquinoxClassLoader returns wrong resource contentY20200801-1200Y20200729-1200Y20200729-0630Y20200728-0600I20200803-0210I20200801-1800I20200801-0010I20200731-2040I20200731-1800I20200731-0520I20200730-1800I20200729-1800I20200729-0120I20200728-1800I20200728-1120I20200727-1800
When searching for a resource that is indexed by a bundle URL the search
must not return an entry unless the index properly matches the class
path index.
This issue is surfaced when taking the external String from a bundle
resource URL and creating a new URL from it. Here the index is stored
in the port of the URL and it must be validated when searching for the
entry when opening the connection to the new URL
Change-Id: I74685811c39ba10af2c92851759cd1eb6ffcf339
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
3 files changed, 110 insertions, 6 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 f279c8c3c..516f80c41 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,6 +14,7 @@ package org.eclipse.osgi.tests.bundles; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -39,6 +40,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; import junit.framework.AssertionFailedError; import junit.framework.Test; import junit.framework.TestSuite; @@ -2454,6 +2457,80 @@ public class ClassLoadingBundleTests extends AbstractBundleTests { assertNull("Found more events.", events.poll(1, TimeUnit.SECONDS)); } + public void testBug565522FragmentClasspath() throws IOException, BundleException { + ByteArrayOutputStream libResourceJarBytes1 = new ByteArrayOutputStream(); + try (JarOutputStream libResourceJar = new JarOutputStream(libResourceJarBytes1)) { + libResourceJar.putNextEntry(new JarEntry("META-INF/")); + libResourceJar.closeEntry(); + libResourceJar.putNextEntry(new JarEntry("META-INF/services/")); + libResourceJar.closeEntry(); + libResourceJar.putNextEntry(new JarEntry("META-INF/services/some.bundle.Factory")); + libResourceJar.write("testFactory1".getBytes()); + libResourceJar.closeEntry(); + } + ByteArrayOutputStream libResourceJarBytes2 = new ByteArrayOutputStream(); + try (JarOutputStream libResourceJar = new JarOutputStream(libResourceJarBytes2)) { + libResourceJar.putNextEntry(new JarEntry("META-INF/")); + libResourceJar.closeEntry(); + libResourceJar.putNextEntry(new JarEntry("META-INF/services/")); + libResourceJar.closeEntry(); + libResourceJar.putNextEntry(new JarEntry("META-INF/services/some.bundle.Factory")); + libResourceJar.write("testFactory2".getBytes()); + libResourceJar.closeEntry(); + } + + File outputDir = OSGiTestsActivator.getContext().getDataFile(getName()); // $NON-NLS-1$ + outputDir.mkdirs(); + + Map<String, String> hostHeaders = new HashMap<>(); + hostHeaders.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + hostHeaders.put(Constants.BUNDLE_SYMBOLICNAME, "host"); + hostHeaders.put(Constants.BUNDLE_CLASSPATH, "., lib/resource.jar"); + Map<String, byte[]> hostEntries = new HashMap<>(); + hostEntries.put("lib/", null); + hostEntries.put("lib/resource.jar", libResourceJarBytes1.toByteArray()); + File hostFile = SystemBundleTests.createBundleWithBytes(outputDir, "host", hostHeaders, hostEntries); + + Map<String, String> fragHeaders = new HashMap<>(); + fragHeaders.put(Constants.BUNDLE_MANIFESTVERSION, "2"); + fragHeaders.put(Constants.BUNDLE_SYMBOLICNAME, "fragment"); + fragHeaders.put(Constants.BUNDLE_CLASSPATH, "., lib/resource.jar"); + fragHeaders.put(Constants.FRAGMENT_HOST, "host"); + Map<String, byte[]> fragEntries = new HashMap<>(); + fragEntries.put("lib/", null); + fragEntries.put("lib/resource.jar", libResourceJarBytes2.toByteArray()); + File fragFile = SystemBundleTests.createBundleWithBytes(outputDir, "frag", fragHeaders, fragEntries); + + Bundle host = null, frag = null; + try { + host = getContext().installBundle(hostFile.toURI().toASCIIString()); + frag = getContext().installBundle(fragFile.toURI().toASCIIString()); + host.start(); + Enumeration<URL> eResources = host.getResources("META-INF/services/some.bundle.Factory"); + assertNotNull("No resources found.", eResources); + List<URL> resources = new ArrayList<>(); + while (eResources.hasMoreElements()) { + resources.add(eResources.nextElement()); + } + assertEquals("Wrong number of resources.", 2, resources.size()); + assertEquals("Wrong content for resource 1", "testFactory1", readURL(resources.get(0))); + assertEquals("Wrong content for resource 2", "testFactory2", readURL(resources.get(1))); + + // round trip the URLs + URL copyURL1 = new URL(resources.get(0).toExternalForm()); + URL copyURL2 = new URL(resources.get(1).toExternalForm()); + assertEquals("Wrong content for url copy 1", "testFactory1", readURL(copyURL1)); + assertEquals("Wrong content for url copy 2", "testFactory2", readURL(copyURL2)); + } finally { + if (host != null) { + host.uninstall(); + } + if (frag != null) { + frag.uninstall(); + } + } + } + void refreshBundles(Collection<Bundle> bundles) throws InterruptedException { final CountDownLatch refreshSignal = new CountDownLatch(1); getContext().getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class).refreshBundles(bundles, new FrameworkListener() { diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java index 018a04095..b0e9ab909 100755 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java @@ -2442,6 +2442,32 @@ public class SystemBundleTests extends AbstractBundleTests { return file; } + public static File createBundleWithBytes(File outputDir, String bundleName, Map<String, String> headers, + Map<String, byte[]>... entries) throws IOException { + Manifest m = new Manifest(); + Attributes attributes = m.getMainAttributes(); + attributes.putValue("Manifest-Version", "1.0"); + for (Map.Entry<String, String> entry : headers.entrySet()) { + attributes.putValue(entry.getKey(), entry.getValue()); + } + File file = new File(outputDir, "bundle" + bundleName + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$ + JarOutputStream jos = new JarOutputStream(new FileOutputStream(file), m); + if (entries != null) { + for (Map<String, byte[]> entryMap : entries) { + for (Map.Entry<String, byte[]> entry : entryMap.entrySet()) { + jos.putNextEntry(new JarEntry(entry.getKey())); + if (entry.getValue() != null) { + jos.write(entry.getValue()); + } + jos.closeEntry(); + } + } + } + jos.flush(); + jos.close(); + return file; + } + public void testBug405919() throws Exception { File config = OSGiTestsActivator.getContext().getDataFile(getName()); config.mkdirs(); 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 fa24f45f3..ec13c9096 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2017 IBM Corporation and others. + * Copyright (c) 2005, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -521,17 +521,18 @@ public class ClasspathManager { } private BundleEntry findLocalEntry(String path, ClasspathEntry[] cpEntries, int classPathIndex, int[] curIndex) { - BundleEntry result = null; for (ClasspathEntry cpEntry : cpEntries) { if (cpEntry != null) { - result = cpEntry.findEntry(path); - if (result != null && (classPathIndex == -1 || classPathIndex == curIndex[0])) { - return result; + if (classPathIndex == -1 || classPathIndex == curIndex[0]) { + BundleEntry result = cpEntry.findEntry(path); + if (result != null) { + return result; + } } } curIndex[0]++; } - return result; + return null; } /** |