You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2021/05/16 22:56:26 UTC

[felix-dev] 01/01: FELIX-6416: special case runtime ref in bundle urls

This is an automated email from the ASF dual-hosted git repository.

pauls pushed a commit to branch issues/FELIX-6416
in repository https://gitbox.apache.org/repos/asf/felix-dev.git

commit 616c772199d5398942273c5c2783fea4467bdcd4
Author: Karl Pauls <ka...@gmail.com>
AuthorDate: Mon May 17 00:56:11 2021 +0200

    FELIX-6416: special case runtime ref in bundle urls
---
 .../framework/URLHandlersBundleURLConnection.java  | 35 ++++++++++---
 .../felix/framework/ResourceLoadingTest.java       | 58 ++++++++++++++++++++++
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
index bbde321..164d4d2 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
@@ -48,13 +48,13 @@ class URLHandlersBundleURLConnection extends URLConnection
 
         String urlString = url.toExternalForm();
 
-        m_path = urlString.substring(urlString.indexOf(url.getPath()));
+        String path = urlString.substring(urlString.indexOf(url.getPath()));
 
         // If this is an attempt to create a connection to the root of
         // the bundle, then throw an exception since this isn't possible.
         // We only allow "/" as a valid URL so it can be used as context
         // for creating other URLs.
-        if ((m_path == null) || (m_path.length() == 0) || m_path.equals("/"))
+        if ((path == null) || (path.length() == 0) || path.equals("/"))
         {
             throw new IOException("Resource does not exist: " + url);
         }
@@ -124,17 +124,40 @@ class URLHandlersBundleURLConnection extends URLConnection
             m_classPathIdx = 0;
         }
         if (!((BundleRevisionImpl) m_targetRevision)
-            .hasInputStream(m_classPathIdx, m_path))
+            .hasInputStream(m_classPathIdx, path))
         {
             BundleWiring wiring = m_targetRevision.getWiring();
             ClassLoader cl = (wiring != null) ? wiring.getClassLoader() : null;
-            URL newurl = (cl != null) ? cl.getResource(m_path) : null;
+            URL newurl = (cl != null) ? cl.getResource(path) : null;
             if (newurl == null)
             {
-                throw new IOException("Resource does not exist: " + url);
+                // FELIX-6416 - handle the special case of java adding a runtime ref
+                if (!"runtime".equals(url.getRef()))
+                {
+                    throw new IOException("Resource does not exist: " + url);
+                }
+                path = url.getPath();
+                if ((path == null) || (path.length() == 0) || path.equals("/"))
+                {
+                    throw new IOException("Resource does not exist: " + url);
+                }
+                if (!((BundleRevisionImpl) m_targetRevision)
+                        .hasInputStream(m_classPathIdx, path))
+                {
+                    newurl = (cl != null) ? cl.getResource(path) : null;
+                    if (newurl == null)
+                    {
+                        throw new IOException("Resource does not exist: " + url);
+                    }
+                    m_classPathIdx = newurl.getPort();
+                }
+            }
+            else
+            {
+                m_classPathIdx = newurl.getPort();
             }
-            m_classPathIdx = newurl.getPort();
         }
+        m_path = path;
     }
 
     public synchronized void connect() throws IOException
diff --git a/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java b/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java
index 19d6d07..bcd5de7 100644
--- a/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java
@@ -20,12 +20,17 @@ package org.apache.felix.framework;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
@@ -174,6 +179,59 @@ public class ResourceLoadingTest extends TestCase
         assertTrue(testBundle.adapt(BundleWiring.class).getClassLoader().getResource("bla/bli/blub").toExternalForm().endsWith("/blub"));
     }
 
+    public void testResourceLoadingUsingURLClassLoaderJDK9() throws Exception {
+        String bmf = "Bundle-SymbolicName: cap.bundle\n"
+            + "Bundle-Version: 1.2.3.Blah\n"
+            + "Bundle-ManifestVersion: 2\n"
+            + "Import-Package: org.osgi.framework\n";
+        File bundleFile = File.createTempFile("felix-bundle", ".jar", tempDir);
+        ByteArrayOutputStream embeddedJar1 = new ByteArrayOutputStream();
+        ByteArrayOutputStream embeddedJar2 = new ByteArrayOutputStream();
+
+        Manifest mf = new Manifest(new ByteArrayInputStream(bmf.getBytes("utf-8")));
+        mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+        JarOutputStream bundle1 = new JarOutputStream(new FileOutputStream(bundleFile), mf);
+        JarOutputStream ej1 = new JarOutputStream(embeddedJar1, mf);
+        JarOutputStream ej2 = new JarOutputStream(embeddedJar2, mf);
+
+        String ej1Entry = "ej1.txt";
+        ej1.putNextEntry(new ZipEntry(ej1Entry));
+        ej1.write("This is a Test".getBytes());
+        ej1.close();
+
+        String ej2Entry = "ej2.txt";
+        ej2.putNextEntry(new ZipEntry(ej2Entry));
+        ej2.write("This is a Test".getBytes());
+        ej2.close();
+
+        String bundleResource = "b1.txt";
+        bundle1.putNextEntry(new ZipEntry(bundleResource));
+        bundle1.write("This is a Test".getBytes());
+        bundle1.putNextEntry(new ZipEntry("ej1.jar"));
+        bundle1.write(embeddedJar1.toByteArray());
+        bundle1.putNextEntry(new ZipEntry("ej2.jar"));
+        bundle1.write(embeddedJar2.toByteArray());
+        bundle1.close();
+
+        Bundle testBundle = felix.getBundleContext().installBundle(bundleFile.toURI().toASCIIString());
+
+        testBundle.start();
+
+        ClassLoader urlClassLoader = createClassLoader(testBundle);
+
+        assertNotNull(urlClassLoader.getResource("ej2.txt"));
+    }
+
+    ClassLoader createClassLoader(Bundle bundle) {
+        List<URL> urls = new ArrayList<URL>();
+        Collection<String> resources = bundle.adapt(BundleWiring.class).listResources("/", "*.jar", BundleWiring.LISTRESOURCES_LOCAL);
+        for (String resource : resources) {
+            urls.add(bundle.getResource(resource));
+        }
+        // Create the classloader
+        return new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
+    }
+
     private static void deleteDir(File root) throws IOException
     {
         if (root.isDirectory())