From a5d5f6ca0e4bb79c866db88242a900eb7086161e Mon Sep 17 00:00:00 2001 From: Vasili Gulevich Date: Wed, 26 Nov 2025 20:35:56 +0400 Subject: [PATCH 1/2] Do not throw RuntimeException from IFile.getContents(false) #2290 --- .../localstore/FileSystemResourceManager.java | 4 + .../tests/resources/regression/IFileTest.java | 85 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java index f1b404cf443..2a83f0d2071 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java @@ -935,6 +935,10 @@ private IFileStore getFileStore(IFile target, boolean force) throws ResourceExce final IFileInfo fileInfo = store.fetchInfo(); Resource resource = (Resource) target; ResourceInfo info = resource.getResourceInfo(true, false); + if (info == null) { + String message = NLS.bind(Messages.resources_mustExist, target.getFullPath()); + throw new ResourceException(IResourceStatus.RESOURCE_NOT_FOUND, target.getFullPath(), message, null); + } if (fileInfo.getLastModified() != info.getLocalSyncInfo()) { asyncRefresh(target); String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, target.getFullPath()); diff --git a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/IFileTest.java b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/IFileTest.java index 0c333a57054..97420c3dbee 100644 --- a/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/IFileTest.java +++ b/resources/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/IFileTest.java @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.core.tests.resources.regression; +import static java.lang.System.currentTimeMillis; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.core.resources.ResourcesPlugin.getWorkspace; import static org.eclipse.core.tests.resources.ResourceTestUtil.createInWorkspace; @@ -24,6 +25,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -31,7 +35,10 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform.OS; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.tests.resources.util.WorkspaceResetExtension; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -125,4 +132,82 @@ public void testBug43936() throws CoreException { project.setDescription(desc, createTestMonitor()); } + /** + * Do not throw RuntimeException when accessing a deleted file + */ + @Test + public void testIssue2290() throws CoreException, InterruptedException { + IProject project = getWorkspace().getRoot().getProject("MyProject"); + IFile subject = project.getFile("subject.txt"); + Job noise = Job.create("Create/delete", monitor -> { + try { + while (!monitor.isCanceled()) { + createInWorkspace(subject); + while (!monitor.isCanceled()) { + try { + subject.delete(true, monitor); + break; + } catch (CoreException e) { + // On Windows, files opened for reading can't be deleted, try again + if (e.getStatus().getCode() != IResourceStatus.FAILED_DELETE_LOCAL) { + throw e; + } + } + } + } + } catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + }); + noise.setPriority(Job.INTERACTIVE); + + long stop = currentTimeMillis() + 1000; + try { + noise.schedule(); + while (currentTimeMillis() < stop) { + assertContentAccessibleOrNotFound(subject); // should not throw + } + } finally { + noise.cancel(); + noise.join(); + IStatus result = noise.getResult(); + if (!result.isOK()) { + throw new CoreException(result); + } + } + } + + private void assertContentAccessibleOrNotFound(IFile file) { + try (InputStream contents = file.getContents(false)) { + contents.transferTo(OutputStream.nullOutputStream()); + } catch (IOException e) { + throw new AssertionError(e); + } catch (CoreException e) { + switch (e.getStatus().getCode()) { + case IResourceStatus.RESOURCE_NOT_LOCAL: + case IResourceStatus.RESOURCE_NOT_FOUND: + case IResourceStatus.FAILED_READ_LOCAL: + case IResourceStatus.OUT_OF_SYNC_LOCAL: + break; + default: + throw new AssertionError(e); + } + } + try (InputStream contents = file.getContents(true)) { + contents.transferTo(OutputStream.nullOutputStream()); + } catch (IOException e) { + throw new AssertionError(e); + } catch (CoreException e) { + switch (e.getStatus().getCode()) { + case IResourceStatus.RESOURCE_NOT_LOCAL: + case IResourceStatus.RESOURCE_NOT_FOUND: + case IResourceStatus.FAILED_READ_LOCAL: + break; + default: + throw new AssertionError(e); + } + } + } + } From 5e2a75588f930d1eba7ce3a043aaa3b875ed3c88 Mon Sep 17 00:00:00 2001 From: Eclipse Platform Bot Date: Mon, 1 Dec 2025 14:19:58 +0000 Subject: [PATCH 2/2] Version bump(s) for 4.39 stream --- .../bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF | 2 +- .../tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF | 2 +- resources/tests/org.eclipse.core.tests.resources/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF b/resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF index 82730f06304..f089e0fbcc0 100644 --- a/resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF +++ b/resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.core.resources; singleton:=true -Bundle-Version: 3.23.100.qualifier +Bundle-Version: 3.23.200.qualifier Bundle-Activator: org.eclipse.core.resources.ResourcesPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF b/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF index 0af9e7d8aa7..ca13fe16300 100644 --- a/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF +++ b/resources/tests/org.eclipse.core.tests.resources/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Core Tests Resources Bundle-SymbolicName: org.eclipse.core.tests.resources; singleton:=true -Bundle-Version: 3.11.1100.qualifier +Bundle-Version: 3.11.1200.qualifier Bundle-Vendor: Eclipse.org Export-Package: org.eclipse.core.tests.filesystem, org.eclipse.core.tests.internal.alias, diff --git a/resources/tests/org.eclipse.core.tests.resources/pom.xml b/resources/tests/org.eclipse.core.tests.resources/pom.xml index 8ae4d950aee..8e86a6785a7 100644 --- a/resources/tests/org.eclipse.core.tests.resources/pom.xml +++ b/resources/tests/org.eclipse.core.tests.resources/pom.xml @@ -18,7 +18,7 @@ 4.39.0-SNAPSHOT org.eclipse.core.tests.resources - 3.11.1100-SNAPSHOT + 3.11.1200-SNAPSHOT eclipse-test-plugin