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 2020/09/07 08:31:05 UTC

[felix-dev] branch connect updated: FELIX-6326: encode and decode resource path correctly.

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

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


The following commit(s) were added to refs/heads/connect by this push:
     new 1333dbf  FELIX-6326: encode and decode resource path correctly.
1333dbf is described below

commit 1333dbf5780d28fc2f7c565ed82d4aa4d9da7082
Author: Karl Pauls <kp...@adobe.com>
AuthorDate: Mon Sep 7 10:30:51 2020 +0200

    FELIX-6326: encode and decode resource path correctly.
---
 .../apache/felix/framework/BundleRevisionImpl.java |  13 ++-
 .../apache/felix/framework/BundleWiringImpl.java   |  34 ------
 .../framework/URLHandlersBundleURLConnection.java  |  27 +++--
 .../felix/framework/ResourceLoadingTest.java       | 124 +++++++++++++++++++++
 4 files changed, 153 insertions(+), 45 deletions(-)

diff --git a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
index c6fcaa4..358faad 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
@@ -29,7 +29,6 @@ import org.apache.felix.framework.util.manifestparser.NativeLibrary;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
-import org.osgi.framework.connect.ConnectModule;
 import org.osgi.framework.wiring.BundleCapability;
 import org.osgi.framework.wiring.BundleRequirement;
 import org.osgi.framework.wiring.BundleRevision;
@@ -40,7 +39,7 @@ import org.osgi.resource.Resource;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
@@ -676,12 +675,20 @@ public class BundleRevisionImpl implements BundleRevision, Resource
 
         try
         {
+            path = new URI(FelixConstants.BUNDLE_URL_PROTOCOL,
+                null,
+                m_bundle.getFramework()._getProperty(Constants.FRAMEWORK_UUID),
+                port,
+                path,
+                null,
+                null).getRawPath();
+
             return m_secureAction.createURL(null,
                 FelixConstants.BUNDLE_URL_PROTOCOL + "://" +
                 m_bundle.getFramework()._getProperty(Constants.FRAMEWORK_UUID) + "_" + m_id + ":" + port + path,
                 getBundle().getFramework().getBundleStreamHandler());
         }
-        catch (MalformedURLException ex)
+        catch (Exception ex)
         {
             m_bundle.getFramework().getLogger().log(
                 m_bundle,
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index 6d22ec7..ecd2e50 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -38,8 +38,6 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkEvent;
 import org.osgi.framework.PackagePermission;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.connect.ConnectContent;
-import org.osgi.framework.connect.ConnectModule;
 import org.osgi.framework.hooks.weaving.WeavingException;
 import org.osgi.framework.hooks.weaving.WeavingHook;
 import org.osgi.framework.hooks.weaving.WovenClass;
@@ -57,7 +55,6 @@ import org.osgi.service.resolver.ResolutionException;
 
 import java.io.IOException;
 import java.lang.reflect.Constructor;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -1092,37 +1089,6 @@ public class BundleWiringImpl implements BundleWiring
         return m_revision.getBundle();
     }
 
-    //
-    // Class loader implementation methods.
-    //
-
-    private URL createURL(int port, String path)
-    {
-        // Add a slash if there is one already, otherwise
-        // the is no slash separating the host from the file
-        // in the resulting URL.
-        if (!path.startsWith("/"))
-        {
-            path = "/" + path;
-        }
-
-        try
-        {
-            return BundleRevisionImpl.getSecureAction().createURL(null,
-                    FelixConstants.BUNDLE_URL_PROTOCOL + "://" +
-                    getBundle().getFramework()._getProperty(Constants.FRAMEWORK_UUID) + "_" + m_revision.getId() + ":" + port + path,
-                    getBundle().getFramework().getBundleStreamHandler());
-        }
-        catch (MalformedURLException ex)
-        {
-            m_logger.log(m_revision.getBundle(),
-                    Logger.LOG_ERROR,
-                    "Unable to create resource URL.",
-                    ex);
-        }
-        return null;
-    }
-
     public Enumeration getResourcesByDelegation(String name)
     {
         Set requestSet = (Set) m_cycleCheck.get();
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 5a06e1b..8538f3d 100644
--- a/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
+++ b/framework/src/main/java/org/apache/felix/framework/URLHandlersBundleURLConnection.java
@@ -20,6 +20,8 @@ package org.apache.felix.framework;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.security.Permission;
@@ -39,6 +41,7 @@ class URLHandlersBundleURLConnection extends URLConnection
     private long m_contentTime;
     private String m_contentType;
     private InputStream m_is;
+    private final String m_path;
 
     public URLHandlersBundleURLConnection(URL url, Felix framework)
         throws IOException
@@ -49,8 +52,16 @@ class URLHandlersBundleURLConnection extends URLConnection
         // 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.
-        String path = url.getPath();
-        if ((path == null) || (path.length() == 0) || path.equals("/"))
+        try
+        {
+            m_path = new URI(url.getProtocol() + "://felix" + url.getPath()).getPath();
+        }
+        catch (URISyntaxException e)
+        {
+            throw new IOException(e);
+        }
+
+        if ((m_path == null) || (m_path.length() == 0) || m_path.equals("/"))
         {
             throw new IOException("Resource does not exist: " + url);
         }
@@ -120,11 +131,11 @@ class URLHandlersBundleURLConnection extends URLConnection
             m_classPathIdx = 0;
         }
         if (!((BundleRevisionImpl) m_targetRevision)
-            .hasInputStream(m_classPathIdx, url.getPath()))
+            .hasInputStream(m_classPathIdx, m_path))
         {
             BundleWiring wiring = m_targetRevision.getWiring();
             ClassLoader cl = (wiring != null) ? wiring.getClassLoader() : null;
-            URL newurl = (cl != null) ? cl.getResource(url.getPath()) : null;
+            URL newurl = (cl != null) ? cl.getResource(m_path) : null;
             if (newurl == null)
             {
                 throw new IOException("Resource does not exist: " + url);
@@ -142,10 +153,10 @@ class URLHandlersBundleURLConnection extends URLConnection
                 throw new IOException("Resource does not exist: " + url);
             }
             m_is = ((BundleRevisionImpl)
-                m_targetRevision).getInputStream(m_classPathIdx, url.getPath());
+                m_targetRevision).getInputStream(m_classPathIdx, m_path);
             m_contentLength = (m_is == null) ? 0 : m_is.available();
-            m_contentTime = ((BundleRevisionImpl) m_targetRevision).getContentTime(m_classPathIdx, url.getPath());
-            m_contentType = URLConnection.guessContentTypeFromName(url.getFile());
+            m_contentTime = ((BundleRevisionImpl) m_targetRevision).getContentTime(m_classPathIdx, m_path);
+            m_contentType = URLConnection.guessContentTypeFromName(m_path);
             connected = true;
         }
     }
@@ -234,6 +245,6 @@ class URLHandlersBundleURLConnection extends URLConnection
             return url;
         }
         return ((BundleRevisionImpl)
-            m_targetRevision).getLocalURL(m_classPathIdx, url.getPath());
+            m_targetRevision).getLocalURL(m_classPathIdx, m_path);
     }
 }
\ No newline at end of file
diff --git a/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java b/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java
new file mode 100644
index 0000000..ddec326
--- /dev/null
+++ b/framework/src/test/java/org/apache/felix/framework/ResourceLoadingTest.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import junit.framework.TestCase;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+
+public class ResourceLoadingTest extends TestCase
+{
+    private File tempDir;
+    private Framework felix;
+    private File cacheDir;
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        tempDir = File.createTempFile("felix-temp", ".dir");
+        assertTrue("precondition", tempDir.delete());
+        assertTrue("precondition", tempDir.mkdirs());
+
+        cacheDir = new File(tempDir, "felix-cache");
+        assertTrue("precondition", cacheDir.mkdir());
+
+        String cache = cacheDir.getPath();
+
+        Map<String,String> params = new HashMap<String, String>();
+        params.put("felix.cache.profiledir", cache);
+        params.put("felix.cache.dir", cache);
+        params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+        felix = new Felix(params);
+        felix.init();
+        felix.start();
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+
+        felix.stop(); // Note that this method is async
+        felix = null;
+
+        deleteDir(tempDir);
+        tempDir = null;
+        cacheDir = null;
+    }
+
+    public void testResourceLoadingWithHash() 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);
+
+        Manifest mf = new Manifest(new ByteArrayInputStream(bmf.getBytes("utf-8")));
+        mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+        JarOutputStream os = new JarOutputStream(new FileOutputStream(bundleFile), mf);
+
+        String name = "bla/ bli/@@€ ß&&????ßß &&$$\" \'##&&/ äöüß/ @@ foo#bar#baz ?a=a.txt?d=ä#dlksl";
+        os.putNextEntry(new ZipEntry(name));
+        os.write("This is a Test".getBytes());
+        os.close();
+
+        Bundle testBundle = felix.getBundleContext().installBundle(bundleFile.toURI().toASCIIString());
+
+        testBundle.start();
+
+        assertEquals(Bundle.ACTIVE, testBundle.getState());
+        assertNotNull(testBundle.getResource(name));
+        assertNotNull(testBundle.getEntry(name));
+
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(testBundle.getResource(name).openStream()))) {
+            assertEquals("This is a Test", reader.readLine());
+        }
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(testBundle.getEntry(name).openStream()))) {
+            assertEquals("This is a Test", reader.readLine());
+        }
+
+    }
+
+    private static void deleteDir(File root) throws IOException
+    {
+        if (root.isDirectory())
+        {
+            for (File file : root.listFiles())
+            {
+                deleteDir(file);
+            }
+        }
+        assertTrue(root.delete());
+    }
+}