eclipse-equinox / equinox

equinox
Eclipse Public License 2.0
28 stars 60 forks source link

URL protocol platform:/ is valid, but resolving it logs the error about unknown protocol #635

Closed al-popa closed 1 month ago

al-popa commented 1 month ago

The platform:/ URL protocol is defined in org.eclipse.core.internal.boot.PlatformURLHandler.PROTOCOL. However, in org.eclipse.core.internal.boot.PlatformURLConnection.getURLAsLocal() this protocol is not checked when performing sanity check. This leads to error log being logged about unknown protocol. This method is used in a public API method org.eclipse.core.runtime.FileLocator.toFileURL(URL). However, the menu icons using this protocol are successfully found, loaded and shown. The error log is misleading and probably wrong.

The exception stacktrace is:


eclipse.buildId=4.29.0.I20230903-1000
java.version=17.0.9
java.vendor=Eclipse Adoptium
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US
Command-line arguments:  -os win32 -ws win32 -arch x86_64

org.eclipse.jface
Error
Mon Jun 03 10:38:44 EEST 2024
Unhandled URL protocol "platform".

java.io.IOException: Unhandled URL protocol "platform".
    at org.eclipse.core.internal.boot.PlatformURLConnection.getURLAsLocal(PlatformURLConnection.java:221)
    at org.eclipse.core.internal.runtime.PlatformURLConverter.toFileURL(PlatformURLConverter.java:37)
    at org.eclipse.core.runtime.FileLocator.toFileURL(FileLocator.java:266)
    at org.eclipse.jface.resource.URLImageDescriptor.getFilePath(URLImageDescriptor.java:269)
    at org.eclipse.jface.resource.URLImageDescriptor$URLImageFileNameProvider.getImagePath(URLImageDescriptor.java:62)
    at org.eclipse.swt.internal.DPIUtil.validateAndGetImagePathAtZoom(DPIUtil.java:423)
    at org.eclipse.swt.graphics.Image.<init>(Image.java:672)
    at org.eclipse.jface.resource.URLImageDescriptor.createImage(URLImageDescriptor.java:300)
    at org.eclipse.jface.resource.ImageDescriptor.createResource(ImageDescriptor.java:230)
    at org.eclipse.jface.resource.DeviceResourceManager.allocate(DeviceResourceManager.java:56)
    at org.eclipse.jface.resource.AbstractResourceManager.create(AbstractResourceManager.java:92)
    at org.eclipse.jface.resource.LazyResourceManager.create(LazyResourceManager.java:96)
    at org.eclipse.jface.resource.LocalResourceManager.allocate(LocalResourceManager.java:71)
    at org.eclipse.jface.resource.AbstractResourceManager.create(AbstractResourceManager.java:92)
    at org.eclipse.e4.ui.workbench.renderers.swt.AbstractContributionItem.getImage(AbstractContributionItem.java:151)
    at org.eclipse.e4.ui.workbench.renderers.swt.AbstractContributionItem.updateIcons(AbstractContributionItem.java:177)
    at org.eclipse.e4.ui.workbench.renderers.swt.AbstractContributionItem.update(AbstractContributionItem.java:127)
    at org.eclipse.e4.ui.workbench.renderers.swt.AbstractContributionItem.fill(AbstractContributionItem.java:264)
    at org.eclipse.jface.action.MenuManager.doItemFill(MenuManager.java:729)
    at org.eclipse.jface.action.MenuManager.update(MenuManager.java:806)
    at org.eclipse.jface.action.MenuManager.handleAboutToShow(MenuManager.java:470)
    at org.eclipse.jface.action.MenuManager$2.menuShown(MenuManager.java:495)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:259)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4274)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1066)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1090)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1071)
    at org.eclipse.swt.widgets.Control.WM_INITMENUPOPUP(Control.java:5141)
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4773)
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:340)
    at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1478)
    at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2306)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5040)
    at org.eclipse.swt.internal.win32.OS.DefWindowProc(Native Method)
    at org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:508)
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4845)
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:340)
    at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1478)
    at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2306)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5040)
    at org.eclipse.swt.internal.win32.OS.DefWindowProc(Native Method)
    at org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:508)
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4845)
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:340)
    at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1478)
    at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2306)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5040)
    at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3658)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1155)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:342)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
    at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:645)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:342)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:552)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:171)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:402)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:651)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:588)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1459)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1432)
mickaelistria commented 1 month ago

Can you reproduce this issue with latest release or current 4.31 RC2 of the Eclipse SDK?

al-popa commented 1 month ago

Proposed change:

diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/boot/PlatformURLConnection.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/boot/PlatformURLConnection.java
index 9139125..1387dbf 100644
--- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/boot/PlatformURLConnection.java
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/boot/PlatformURLConnection.java
@@ -217,7 +217,8 @@
        connect(true); // connect and force caching if necessary
        URL u = connection.getURL();
        String up = u.getProtocol();
-       if (!up.equals(PlatformURLHandler.FILE) && !up.equals(PlatformURLHandler.JAR) && !up.startsWith(PlatformURLHandler.BUNDLE))
+       if (!up.equals(PlatformURLHandler.FILE) && !up.equals(PlatformURLHandler.JAR) //
+               && !up.startsWith(PlatformURLHandler.BUNDLE) && !up.startsWith(PlatformURLHandler.PROTOCOL))
            throw new IOException(NLS.bind(CommonMessages.url_noaccess, up));
        return u;
    }
mickaelistria commented 1 month ago

Proposed change:

Cool. Please make a pull request for it to facilitate review.

jukzi commented 1 month ago

I could not reproduce the error with a test like this:

diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/EquinoxBundleAdaptTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/EquinoxBundleAdaptTests.java
index 9aba6c3..0a76b6d 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/EquinoxBundleAdaptTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/EquinoxBundleAdaptTests.java
@@ -17,6 +17,7 @@
 import static org.junit.Assert.assertNotNull;

 import java.io.File;
+import java.net.URI;
 import java.net.URL;
 import java.security.Permission;
 import java.security.ProtectionDomain;
@@ -74,4 +75,12 @@
        assertEquals(new File(testBundleRoot, "bundle_tests"), file.getParentFile());
        assertEquals("test", file.getName().replace(".jar", ""));
    }
+
+   @Test
+   public void testGh635() throws Exception {
+       URL testBundleURL = URI
+               .create("platform:/plugin/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/debug.gif").toURL();
+       URL fileURL = FileLocator.toFileURL(testBundleURL);
+       org.junit.Assert.assertTrue(fileURL.toString(), new File(fileURL.toURI()).exists());
+   }
 }
al-popa commented 1 month ago

Affected version:

Eclipse SDK Version: 2023-09 (4.29) Build id: I20230903-1000 OS: Windows 10, v.10.0, x86_64 / win32 Java vendor: Eclipse Adoptium Java runtime version: 17.0.9+9 Java version: 17.0.9

al-popa commented 1 month ago

It turns out, the URL using platform:/ protocol was invalid. It resolved to the path containing 2 tokens of protocol, something like: platform:/<project>/platform:/<project>/<path>.

I am not sure how this path was resolved, but the issue cannot be reproduced in JUnit as @Jörg Kubitz shown. The path issue was solved downstream.

Close this issue.