From cff785d2b2b9d514a25901f105a5a125c2c644aa Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Sat, 30 Mar 2024 13:19:15 +0100 Subject: [PATCH] Add existence check (file protocol) in URLImageDescriptor.getFilePath() The URLImageDescriptor.getFilePath() method currently returns a path for a given URL using the file protocol even if the file does not exist. This conflicts with the method's contract and breaks consumers (such as the scaled image data retrieval in SWT's DPIUtil). With this change, the method properly checks for the existence of a file at the given location and returns null in case it does not exist, according to the method's contract. A test case is added to demonstrate the bug and detect regressions. --- .../jface/resource/URLImageDescriptor.java | 10 ++++++-- .../tests/images/UrlImageDescriptorTest.java | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java index 24ff2ab58ae..e00a363bfe0 100644 --- a/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java +++ b/bundles/org.eclipse.jface/src/org/eclipse/jface/resource/URLImageDescriptor.java @@ -22,6 +22,8 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IAdaptable; @@ -267,8 +269,12 @@ private static String getFilePath(URL url, boolean logIOException) { url = platformURL; } URL locatedURL = FileLocator.toFileURL(url); - if (FILE_PROTOCOL.equalsIgnoreCase(locatedURL.getProtocol())) - return IPath.fromOSString(locatedURL.getPath()).toOSString(); + if (FILE_PROTOCOL.equalsIgnoreCase(locatedURL.getProtocol())) { + String filePath = IPath.fromOSString(locatedURL.getPath()).toOSString(); + if (Files.exists(Path.of(filePath))) { + return filePath; + } + } return null; } catch (IOException e) { if (logIOException) { diff --git a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java index fa620a0b46b..c86db5d3a34 100644 --- a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java +++ b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/images/UrlImageDescriptorTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; +import java.io.IOException; import java.net.URL; import org.eclipse.core.runtime.Adapters; @@ -29,10 +30,15 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageFileNameProvider; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; public class UrlImageDescriptorTest { + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + /** * Test that individually created images of a given descriptor are not equal * (See issue #682). @@ -114,6 +120,24 @@ public void testImageFileNameProviderGetxName() { assertNull("URLImageDescriptor's ImageFileNameProvider does return a @1.5x path", imagePath150); } + @Test + public void testImageFileNameProviderGetxName_forFileURL() throws IOException { + URL imageFileURL = tempFolder.newFile("image.png").toURI().toURL(); + tempFolder.newFile("image@2x.png"); + ImageDescriptor descriptor = ImageDescriptor.createFromURL(imageFileURL); + + ImageFileNameProvider fileNameProvider = Adapters.adapt(descriptor, ImageFileNameProvider.class); + assertNotNull("URLImageDescriptor does not adapt to ImageFileNameProvider", fileNameProvider); + String imagePath100 = fileNameProvider.getImagePath(100); + assertNotNull("URLImageDescriptor ImageFileNameProvider does not return the 100% path", imagePath100); + assertEquals(IPath.fromOSString(imagePath100).lastSegment(), "image.png"); + String imagePath200 = fileNameProvider.getImagePath(200); + assertNotNull("URLImageDescriptor ImageFileNameProvider does not return the @2x path", imagePath200); + assertEquals(IPath.fromOSString(imagePath200).lastSegment(), "image@2x.png"); + String imagePath150 = fileNameProvider.getImagePath(150); + assertNull("URLImageDescriptor's ImageFileNameProvider does return a @1.5x path", imagePath150); + } + @Test public void testAdaptToURL() { ImageDescriptor descriptor = ImageDescriptor