Bug 507084 - Leftover resources pointing to deleted folders after
refresh

Change-Id: I06dfbc1ec38f22adb1a214c493e8a4e6c4144c91
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileStoreRoot.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileStoreRoot.java
index cfaab43..13d9bb8 100644
--- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileStoreRoot.java
+++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileStoreRoot.java
@@ -111,14 +111,16 @@
 	 */
 	IFileStore createStore(IPath workspacePath, IResource resource) throws CoreException {
 		IPath childPath = workspacePath.removeFirstSegments(chop);
-		IFileStore rootStore;
-		final URI uri = resource.getPathVariableManager().resolveURI(getCanonicalRoot());
+		// For a linked resource itself we have to use its root, but for its children we prefer
+		// to use the canonical root since it provides for faster file system access.
+		// See http://bugs.eclipse.org/507084
+		final URI uri = resource.getPathVariableManager().resolveURI(resource.isLinked() ? root : getCanonicalRoot());
 		if (!uri.isAbsolute()) {
-			//handles case where resource location cannot be resolved
-			//such as unresolved path variable or invalid file system scheme
+			// Handles case where resource location cannot be resolved such as
+			// unresolved path variable or invalid file system scheme.
 			return EFS.getNullFileSystem().getStore(workspacePath);
 		}
-		rootStore = EFS.getStore(uri);
+		IFileStore rootStore = EFS.getStore(uri);
 		if (childPath.segmentCount() == 0)
 			return rootStore;
 		return rootStore.getFileStore(childPath);
diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/LinkedResourceTest.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/LinkedResourceTest.java
index 08178c4..be0b029 100644
--- a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/LinkedResourceTest.java
+++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/LinkedResourceTest.java
@@ -845,7 +845,6 @@
 			childStore = EFS.getStore(linkChild.getLocationURI());
 		} catch (CoreException e) {
 			fail("0.99", e);
-			return;
 		}
 
 		//everything should exist at this point
@@ -1930,7 +1929,7 @@
 		assertTrue("2.1", linkChild.exists());
 	}
 
-	public void testBug293935_linkedFolderWithOverlappingLocation() {
+	public void testLinkedFolderWithOverlappingLocation_Bug293935_() {
 		IWorkspace workspace = getWorkspace();
 
 		IPath projectLocation = existingProject.getLocation();
@@ -1976,7 +1975,7 @@
 		}
 	}
 
-	public void testBug338010_linkedFolderWithSymlink() {
+	public void testLinkedFolderWithSymlink_Bug338010() {
 		// Only activate this test if testing of symbolic links is possible.
 		if (!canCreateSymLinks())
 			return;
@@ -2001,4 +2000,40 @@
 		// Check that the symlink is preserved.
 		assertEquals("1.2", resolvedLinkChildLocation, folder.getLocation());
 	}
+
+	/**
+	 * Tests deleting of the target of a linked folder that itself is a symbolic link.
+	 */
+	public void testDeleteLinkTarget_Bug507084() throws Exception {
+		// Only activate this test if testing of symbolic links is possible.
+		if (!canCreateSymLinks())
+			return;
+		IPath baseLocation = getRandomLocation();
+		IPath resolvedBaseLocation = resolve(baseLocation);
+		deleteOnTearDown(resolvedBaseLocation);
+		IPath symlinkTarget = resolvedBaseLocation.append("dir1/A");
+		symlinkTarget.append("B/C").toFile().mkdirs();
+		IPath linkParentDir = resolvedBaseLocation.append("dir2");
+		linkParentDir.toFile().mkdirs();
+		createSymLink(linkParentDir.toFile(), "symlink", symlinkTarget.toOSString(), true);
+
+		IFolder folder = nonExistingFolderInExistingProject;
+		IPath symLink = linkParentDir.append("symlink");
+		folder.createLink(symLink, IResource.NONE, getMonitor());
+		assertTrue("1.1", folder.exists());
+		assertTrue("1.2", folder.getFolder("B/C").exists());
+		assertEquals("1.3", symLink, folder.getLocation());
+		// Delete the symlink and the directory that contains it.
+		symLink.toFile().delete();
+		linkParentDir.toFile().delete();
+		// Check that the directory that contained the symlink has been deleted.
+		assertFalse("2.1", linkParentDir.toFile().exists());
+		// Refresh the project.
+		folder.getParent().refreshLocal(IResource.DEPTH_INFINITE, getMonitor());
+		// Check that the linked folder still exists.
+		assertTrue("3.1", folder.exists());
+		// Check that the contents of the linked folder no longer exist.
+		assertFalse("3.2", folder.getFolder("B").exists());
+		assertFalse("3.3", folder.getFolder("B/C").exists());
+	}
 }