Bug 440110 - FileSystemResourceManager#refreshResource uses potentially expensive IFileSystem#fetchFileTree for depth equal to DEPTH_ZERO

Change-Id: Ib34f16d4480b74239f38b50c8614da5ead3e4407
Signed-off-by: Szymon Ptaszkiewicz <szymon.ptaszkiewicz@pl.ibm.com>
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java
index a7011f6..5680763 100644
--- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java
+++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java
@@ -965,9 +965,12 @@
 	protected boolean refreshResource(IResource target, int depth, boolean updateAliases, IProgressMonitor monitor) throws CoreException {
 		String title = NLS.bind(Messages.localstore_refreshing, target.getFullPath());
 		SubMonitor subMonitor = SubMonitor.convert(monitor, title, 100);
-		IFileStore fileStore = ((Resource) target).getStore();
-		// Try to get all info in one shot, if the file system supports it.
-		IFileTree fileTree = fileStore.getFileSystem().fetchFileTree(fileStore, subMonitor.newChild(2));
+		IFileTree fileTree = null;
+		// If there can be more than one resource to refresh, try to get the whole tree in one shot, if the file system supports it.
+		if (depth != IResource.DEPTH_ZERO) {
+			IFileStore fileStore = ((Resource) target).getStore();
+			fileTree = fileStore.getFileSystem().fetchFileTree(fileStore, subMonitor.newChild(2));
+		}
 		UnifiedTree tree = fileTree == null ? new UnifiedTree(target) : new UnifiedTree(target, fileTree);
 		SubMonitor refreshMonitor = subMonitor.newChild(98);
 		RefreshLocalVisitor visitor = updateAliases ? new RefreshLocalAliasVisitor(refreshMonitor) : new RefreshLocalVisitor(refreshMonitor);
diff --git a/tests/org.eclipse.core.tests.resources/plugin.xml b/tests/org.eclipse.core.tests.resources/plugin.xml
index f27c228..63c0a16 100644
--- a/tests/org.eclipse.core.tests.resources/plugin.xml
+++ b/tests/org.eclipse.core.tests.resources/plugin.xml
@@ -564,6 +564,12 @@
 </extension>
 <extension
       point="org.eclipse.core.filesystem.filesystems">
+   <filesystem scheme="bug440110">
+      <run class="org.eclipse.core.tests.internal.filesystem.bug440110.Bug440110FileSystem"/>
+   </filesystem>
+</extension>
+<extension
+      point="org.eclipse.core.filesystem.filesystems">
    <filesystem scheme="remote">
       <run class="org.eclipse.core.tests.internal.filesystem.remote.RemoteFileSystem"/>
    </filesystem>
diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileStore.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileStore.java
new file mode 100644
index 0000000..4f183d3
--- /dev/null
+++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileStore.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.tests.internal.filesystem.bug440110;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.filesystem.IFileSystem;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.tests.internal.filesystem.ram.MemoryFileStore;
+
+public class Bug440110FileStore extends MemoryFileStore {
+	public Bug440110FileStore(IPath path) {
+		super(path);
+	}
+
+	@Override
+	public IFileStore getChild(String name) {
+		return new Bug440110FileStore(path.append(name));
+	}
+
+	@Override
+	public IFileSystem getFileSystem() {
+		return Bug440110FileSystem.getInstance();
+	}
+
+	@Override
+	public IFileStore getParent() {
+		if (path.segmentCount() == 0)
+			return null;
+		return new Bug440110FileStore(path.removeLastSegments(1));
+	}
+
+	@Override
+	public URI toURI() {
+		try {
+			return new URI(Bug440110FileSystem.SCHEME, path.setDevice(null).toPortableString(), null);
+		} catch (URISyntaxException e) {
+			throw new Error(e);
+		}
+	}
+}
diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileSystem.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileSystem.java
new file mode 100644
index 0000000..d13c44f
--- /dev/null
+++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileSystem.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.tests.internal.filesystem.bug440110;
+
+import java.net.URI;
+import org.eclipse.core.filesystem.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.tests.internal.filesystem.ram.MemoryFileSystem;
+
+public class Bug440110FileSystem extends MemoryFileSystem {
+	public static final String SCHEME = "bug440110";
+	private static IFileSystem instance;
+	private static boolean fetchedFileTree = false;
+
+	public static void clearFetchedFileTree() {
+		fetchedFileTree = false;
+	}
+
+	public static IFileSystem getInstance() {
+		return instance;
+	}
+
+	public static boolean hasFetchedFileTree() {
+		return fetchedFileTree;
+	}
+
+	public Bug440110FileSystem() {
+		super();
+		instance = this;
+	}
+
+	@Override
+	public IFileTree fetchFileTree(IFileStore root, IProgressMonitor monitor) throws CoreException {
+		fetchedFileTree = true;
+		return new Bug440110FileTree(root);
+	}
+
+	@Override
+	public IFileStore getStore(URI uri) {
+		return new Bug440110FileStore(Path.fromPortableString(uri.getSchemeSpecificPart()));
+	}
+}
diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileTree.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileTree.java
new file mode 100644
index 0000000..202c3ad
--- /dev/null
+++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/filesystem/bug440110/Bug440110FileTree.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.tests.internal.filesystem.bug440110;
+
+import org.eclipse.core.filesystem.*;
+import org.eclipse.core.filesystem.provider.FileTree;
+import org.eclipse.core.runtime.CoreException;
+
+public class Bug440110FileTree extends FileTree {
+	public Bug440110FileTree(IFileStore treeRoot) {
+		super(treeRoot);
+	}
+
+	@Override
+	public IFileInfo[] getChildInfos(IFileStore store) {
+		try {
+			return store.childInfos(EFS.NONE, null);
+		} catch (CoreException e) {
+			return new IFileInfo[0];
+		}
+	}
+
+	@Override
+	public IFileStore[] getChildStores(IFileStore store) {
+		try {
+			return store.childStores(EFS.NONE, null);
+		} catch (CoreException e) {
+			return new IFileStore[0];
+		}
+	}
+
+	@Override
+	public IFileInfo getFileInfo(IFileStore store) {
+		return store.fetchInfo();
+	}
+}
diff --git a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/FileSystemResourceManagerTest.java b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/FileSystemResourceManagerTest.java
index b75c1d3..5feb05c 100644
--- a/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/FileSystemResourceManagerTest.java
+++ b/tests/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/localstore/FileSystemResourceManagerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,8 @@
 package org.eclipse.core.tests.internal.localstore;
 
 import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import org.eclipse.core.filesystem.IFileInfo;
@@ -18,6 +20,7 @@
 import org.eclipse.core.internal.resources.*;
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
+import org.eclipse.core.tests.internal.filesystem.bug440110.Bug440110FileSystem;
 
 //
 public class FileSystemResourceManagerTest extends LocalStoreTest implements ICoreConstants {
@@ -38,6 +41,33 @@
 		return new TestSuite(FileSystemResourceManagerTest.class);
 	}
 
+	public void testBug440110() throws URISyntaxException, CoreException {
+		String projectName = getUniqueString();
+		IWorkspace workspace = getWorkspace();
+		IProject project = workspace.getRoot().getProject(projectName);
+		IProjectDescription projectDescription = workspace.newProjectDescription(projectName);
+		projectDescription.setLocationURI(new URI(Bug440110FileSystem.SCHEME + "://" + projectName));
+		project.create(projectDescription, null);
+		project.open(null);
+		assertEquals("0.1", Bug440110FileSystem.SCHEME, project.getLocationURI().getScheme());
+
+		IFolder folder = project.getFolder("folder");
+		folder.create(true, true, null);
+		assertEquals("0.2", Bug440110FileSystem.SCHEME, folder.getLocationURI().getScheme());
+
+		Bug440110FileSystem.clearFetchedFileTree();
+		folder.refreshLocal(IResource.DEPTH_ZERO, null);
+		assertFalse("1.0", Bug440110FileSystem.hasFetchedFileTree());
+
+		Bug440110FileSystem.clearFetchedFileTree();
+		folder.refreshLocal(IResource.DEPTH_ONE, null);
+		assertTrue("2.0", Bug440110FileSystem.hasFetchedFileTree());
+
+		Bug440110FileSystem.clearFetchedFileTree();
+		folder.refreshLocal(IResource.DEPTH_INFINITE, null);
+		assertTrue("3.0", Bug440110FileSystem.hasFetchedFileTree());
+	}
+
 	/**
 	 */
 	public void testContainerFor() throws Throwable {