### Eclipse Workspace Patch 1.0
#P org.eclipse.core.resources
Index: src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java,v
retrieving revision 1.130
diff -u -r1.130 FileSystemResourceManager.java
--- src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java 12 Jan 2011 09:38:29 -0000 1.130
+++ src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java 25 Mar 2011 12:36:10 -0000
@@ -18,18 +18,22 @@
import java.util.*;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.internal.refresh.RefreshManager;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.resources.File;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.core.runtime.preferences.*;
import org.eclipse.osgi.util.NLS;
import org.xml.sax.InputSource;
/**
* Manages the synchronization between the workspace's view and the file system.
*/
-public class FileSystemResourceManager implements ICoreConstants, IManager {
+public class FileSystemResourceManager implements ICoreConstants, IManager, IPreferenceChangeListener {
/**
* The history store is initialized lazily - always use the accessor method
@@ -37,6 +41,8 @@
protected IHistoryStore _historyStore;
protected Workspace workspace;
+ private volatile boolean lightweightAutoRefreshEnabled;
+
public FileSystemResourceManager(Workspace workspace) {
this.workspace = workspace;
}
@@ -124,6 +130,15 @@
return results;
}
+ /**
+ * Asynchronously auto-refresh the requested resource if Auto-Refresh is enabled
+ * @param target
+ */
+ private void asyncRefresh(IResource target) {
+ if (lightweightAutoRefreshEnabled)
+ workspace.getRefreshManager().refresh(target);
+ }
+
private void findLinkedResourcesPaths(URI inputLocation, final ArrayList results) throws CoreException {
IPath suffix = null;
IFileStore fileStore = EFS.getStore(inputLocation);
@@ -621,10 +636,12 @@
return projectInfo.getLocalSyncInfo() == getStore(descriptionFile).fetchInfo().getLastModified();
}
- /* (non-Javadoc)
+ /**
* Returns true if the given resource is synchronized with the file system
* to the given depth. Returns false otherwise.
*
+ * Any discovered out-of-sync resources are scheduled to be brought back in sync.
+ *
* @see IResource#isSynchronized(int)
*/
public boolean isSynchronized(IResource target, int depth) {
@@ -661,12 +678,25 @@
Policy.log(e);
return false;
} catch (IsSynchronizedVisitor.ResourceChangedException e) {
+ // Ask refresh manager to bring out-of-sync resource back into sync when convenient
+ asyncRefresh(e.target);
//visitor throws an exception if out of sync
return false;
}
return true;
}
+ /**
+ * Check whether the preference {@link RefreshManager#PREF_LIGHTWEIGHT_AUTO_REFRESH} is
+ * enabled. When this preference is true the Resources plugin automatically refreshes
+ * resources which are known to be out-of-sync, and may install lightweight filesystem
+ * notification hooks.
+ * @return whether this FSRM is automatically refreshing discovered out-of-sync resources
+ */
+ public boolean isLightweightAutoRefreshEnabled() {
+ return lightweightAutoRefreshEnabled;
+ }
+
public void link(Resource target, URI location, IFileInfo fileInfo) throws CoreException {
initializeStore(target, location);
ResourceInfo info = target.getResourceInfo(false, true);
@@ -716,18 +746,27 @@
return null;
}
+ public void preferenceChange(PreferenceChangeEvent event) {
+ if (RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH.equals(event.getKey()))
+ lightweightAutoRefreshEnabled = Boolean.valueOf((String)event.getNewValue());
+ }
+
public InputStream read(IFile target, boolean force, IProgressMonitor monitor) throws CoreException {
IFileStore store = getStore(target);
- if (!force) {
- final IFileInfo fileInfo = store.fetchInfo();
- if (!fileInfo.exists()) {
+ final IFileInfo fileInfo = store.fetchInfo();
+ if (!fileInfo.exists()) {
+ asyncRefresh(target);
+ if (!force) {
String message = NLS.bind(Messages.localstore_fileNotFound, store.toString());
throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, target.getFullPath(), message, null);
}
- ResourceInfo info = ((Resource) target).getResourceInfo(true, false);
- int flags = ((Resource) target).getFlags(info);
- ((Resource) target).checkExists(flags, true);
- if (fileInfo.getLastModified() != info.getLocalSyncInfo()) {
+ }
+ ResourceInfo info = ((Resource) target).getResourceInfo(true, false);
+ int flags = ((Resource) target).getFlags(info);
+ ((Resource) target).checkExists(flags, true);
+ if (fileInfo.getLastModified() != info.getLocalSyncInfo()) {
+ asyncRefresh(target);
+ if (!force) {
String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, target.getFullPath());
throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, target.getFullPath(), message, null);
}
@@ -962,10 +1001,13 @@
public void shutdown(IProgressMonitor monitor) throws CoreException {
if (_historyStore != null)
_historyStore.shutdown(monitor);
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).removePreferenceChangeListener(this);
}
public void startup(IProgressMonitor monitor) throws CoreException {
- //nothing to do
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).addPreferenceChangeListener(this);
+ lightweightAutoRefreshEnabled = Platform.getPreferencesService().getBoolean(
+ ResourcesPlugin.PI_RESOURCES, RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, PreferenceInitializer.PREF_LIGHTWEIGHT_AUTO_REFRESH, null);
}
/**
@@ -1006,10 +1048,12 @@
ResourceInfo info = ((Resource) target).getResourceInfo(true, false);
// test if timestamp is the same since last synchronization
if (lastModified != info.getLocalSyncInfo()) {
+ asyncRefresh(target);
String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, target.getFullPath());
throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, target.getFullPath(), message, null);
}
if (!fileInfo.exists()) {
+ asyncRefresh(target);
String message = NLS.bind(Messages.localstore_resourceDoesNotExist, target.getFullPath());
throw new ResourceException(IResourceStatus.NOT_FOUND_LOCAL, target.getFullPath(), message, null);
}
Index: src/org/eclipse/core/internal/localstore/IsSynchronizedVisitor.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/IsSynchronizedVisitor.java,v
retrieving revision 1.9
diff -u -r1.9 IsSynchronizedVisitor.java
--- src/org/eclipse/core/internal/localstore/IsSynchronizedVisitor.java 4 Apr 2006 20:53:47 -0000 1.9
+++ src/org/eclipse/core/internal/localstore/IsSynchronizedVisitor.java 25 Mar 2011 12:36:10 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 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
@@ -7,25 +7,30 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.internal.localstore;
import org.eclipse.core.internal.resources.Resource;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Visits a unified tree, and throws a ResourceChangedException on the first
* node that is discovered to be out of sync. The exception that is thrown
- * will not have any meaningful status, message, or stack trace. Nodes
- * discovered to be out of sync are not brought to be in sync with the workspace.
+ * will not have any meaningful status, message, or stack trace. However it
+ * does contain the target resource which can be used to bring the Resource
+ * back into sync.
*/
public class IsSynchronizedVisitor extends CollectSyncStatusVisitor {
static class ResourceChangedException extends RuntimeException {
private static final long serialVersionUID = 1L;
+ public final IResource target;
+ public ResourceChangedException(IResource target) {
+ this.target = target;
+ }
}
- protected static ResourceChangedException exception = new ResourceChangedException();
-
/**
* Creates a new IsSynchronizedVisitor.
*/
@@ -36,7 +41,19 @@
/**
* @see CollectSyncStatusVisitor#changed(Resource)
*/
+ @Override
protected void changed(Resource target) {
- throw exception;
+ throw new ResourceChangedException(target);
+ }
+
+ @Override
+ protected void fileToFolder(UnifiedTreeNode node, Resource target) {
+ changed((Resource)workspace.getRoot().getFolder(target.getFullPath()));
+ }
+
+ @Override
+ protected void folderToFile(UnifiedTreeNode node, Resource target) {
+ // Pass correct gender to changed for notification and async-refresh
+ changed((Resource)workspace.getRoot().getFile(target.getFullPath()));
}
}
Index: src/org/eclipse/core/internal/refresh/RefreshManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/refresh/RefreshManager.java,v
retrieving revision 1.19
diff -u -r1.19 RefreshManager.java
--- src/org/eclipse/core/internal/refresh/RefreshManager.java 21 Mar 2011 12:11:43 -0000 1.19
+++ src/org/eclipse/core/internal/refresh/RefreshManager.java 25 Mar 2011 12:36:10 -0000
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.core.internal.refresh;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+
import org.eclipse.core.internal.resources.IManager;
import org.eclipse.core.internal.utils.Policy;
import org.eclipse.core.resources.*;
@@ -27,6 +30,25 @@
* @since 3.0
*/
public class RefreshManager implements IRefreshResult, IManager, Preferences.IPropertyChangeListener {
+
+ /**
+ * Name of a preference for configuring whether out-of-sync resources are automatically
+ * asynchronously refreshed, when discovered to be out-of-sync by the workspace.
+ *
+ * This preference suppresses out-of-sync CoreException for some read methods, including:
+ * {@link IFile#getContents()} & {@link IFile#getContentDescription()}.
+ *
+ *
+ * In the future the workspace may enable other lightweight auto-refresh mechanisms when this
+ * preferece is true. (The existing {@link ResourcesPlugin#PREF_AUTO_REFRESH} will continue
+ * to enable filesystem hooks and the existing polling based monitor.)
+ *
+ * This is a is true by default. Integrators should take care when
+ * changing this from the default. See the discussion: https://bugs.eclipse.org/303517
+ * @since 3.7
+ */
+ public static final String PREF_LIGHTWEIGHT_AUTO_REFRESH = "refresh.lightweight.enabled"; //$NON-NLS-1$
+
public static boolean DEBUG = Policy.DEBUG_AUTO_REFRESH;
public static final String DEBUG_PREFIX = "Auto-refresh: "; //$NON-NLS-1$
MonitorManager monitors;
Index: src/org/eclipse/core/internal/resources/ContentDescriptionManager.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ContentDescriptionManager.java,v
retrieving revision 1.43
diff -u -r1.43 ContentDescriptionManager.java
--- src/org/eclipse/core/internal/resources/ContentDescriptionManager.java 21 Mar 2011 12:11:43 -0000 1.43
+++ src/org/eclipse/core/internal/resources/ContentDescriptionManager.java 25 Mar 2011 12:36:11 -0000
@@ -300,7 +300,15 @@
return projectContentTypes.getMatcherFor(project);
}
- public IContentDescription getDescriptionFor(File file, ResourceInfo info) throws CoreException {
+ /**
+ * Discovers, and caches, the content description of the requested File.
+ * @param file to discover the content description for; result cached
+ * @param info ResourceInfo for the passed in file
+ * @param in_sync boolean flag which indicates if cache can be trusted. If false false don't trust the cache
+ * @return IContentDescription for the file
+ * @throws CoreException
+ */
+ public IContentDescription getDescriptionFor(File file, ResourceInfo info, boolean in_sync) throws CoreException {
if (ProjectContentTypes.usesContentTypePreferences(file.getFullPath().segment(0)))
// caching for project containing project specific settings is not supported
return readDescription(file);
@@ -311,7 +319,7 @@
// the cache is not good, flush it
flushJob.schedule(1000);
}
- if (getCacheState() != ABOUT_TO_FLUSH) {
+ if (in_sync && getCacheState() != ABOUT_TO_FLUSH) {
// first look for the flags in the resource info to avoid looking in the cache
// don't need to copy the info because the modified bits are not in the deltas
if (info == null)
@@ -332,12 +340,14 @@
info.clear(ICoreConstants.M_CONTENT_CACHE);
}
}
- synchronized (this) {
+ if (in_sync) {
// tries to get a description from the cache
- Cache.Entry entry = cache.getEntry(file.getFullPath());
- if (entry != null && entry.getTimestamp() == getTimestamp(info))
- // there was a description in the cache, and it was up to date
- return (IContentDescription) entry.getCached();
+ synchronized (this) {
+ Cache.Entry entry = cache.getEntry(file.getFullPath());
+ if (entry != null && entry.getTimestamp() == getTimestamp(info))
+ // there was a description in the cache, and it was up to date
+ return (IContentDescription) entry.getCached();
+ }
}
// either we didn't find a description in the cache, or it was not up-to-date - has to be read again
@@ -347,7 +357,7 @@
synchronized (this) {
// tries to get a description from the cache
Cache.Entry entry = cache.getEntry(file.getFullPath());
- if (entry != null && entry.getTimestamp() == getTimestamp(info))
+ if (entry != null && in_sync && entry.getTimestamp() == getTimestamp(info))
// there was a description in the cache, and it was up to date
return (IContentDescription) entry.getCached();
@@ -375,7 +385,7 @@
entry = cache.addEntry(file.getFullPath(), newDescription, getTimestamp(info));
else {
// just update the existing entry
- entry.setTimestamp(info.getContentId());
+ entry.setTimestamp(getTimestamp(info));
entry.setCached(newDescription);
}
return newDescription;
Index: src/org/eclipse/core/internal/resources/File.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/File.java,v
retrieving revision 1.94
diff -u -r1.94 File.java
--- src/org/eclipse/core/internal/resources/File.java 13 May 2010 11:54:45 -0000 1.94
+++ src/org/eclipse/core/internal/resources/File.java 25 Mar 2011 12:36:11 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Serge Beauchamp (Freescale Semiconductor) - [229633] Group and Project Path Variable Support
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.internal.resources;
@@ -94,16 +95,6 @@
return result;
}
- /**
- * Checks that this resource is synchronized with the local file system.
- */
- private void checkSynchronized() throws CoreException {
- if (!isSynchronized(IResource.DEPTH_ZERO)) {
- String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, getFullPath());
- throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, getFullPath(), message, null);
- }
- }
-
/* (non-Javadoc)
* @see IFile#create(InputStream, int, IProgressMonitor)
*/
@@ -252,7 +243,7 @@
if (charset != null || !checkImplicit)
return charset;
// tries to obtain a description for the file contents
- IContentDescription description = workspace.getContentDescriptionManager().getDescriptionFor(this, info);
+ IContentDescription description = workspace.getContentDescriptionManager().getDescriptionFor(this, info, true);
if (description != null) {
String contentCharset = description.getCharset();
if (contentCharset != null)
@@ -270,16 +261,21 @@
ResourceInfo info = getResourceInfo(false, false);
int flags = getFlags(info);
checkAccessible(flags);
- checkSynchronized();
checkLocal(flags, DEPTH_ZERO);
- return workspace.getContentDescriptionManager().getDescriptionFor(this, info);
+ boolean isSynchronized = isSynchronized(IResource.DEPTH_ZERO);
+ // Throw an exception if out-of-sync and not auto-refresh enabled
+ if (!isSynchronized && !getLocalManager().isLightweightAutoRefreshEnabled()) {
+ String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, getFullPath());
+ throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, getFullPath(), message, null);
+ }
+ return workspace.getContentDescriptionManager().getDescriptionFor(this, info, isSynchronized);
}
/* (non-Javadoc)
* @see IFile#getContents()
*/
public InputStream getContents() throws CoreException {
- return getContents(false);
+ return getContents(getLocalManager().isLightweightAutoRefreshEnabled());
}
/* (non-Javadoc)
Index: src/org/eclipse/core/internal/resources/PreferenceInitializer.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/PreferenceInitializer.java,v
retrieving revision 1.12
diff -u -r1.12 PreferenceInitializer.java
--- src/org/eclipse/core/internal/resources/PreferenceInitializer.java 13 Oct 2009 09:28:08 -0000 1.12
+++ src/org/eclipse/core/internal/resources/PreferenceInitializer.java 25 Mar 2011 12:36:11 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * Copyright (c) 2004, 2011 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
@@ -7,9 +7,12 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.internal.resources;
+import org.eclipse.core.internal.refresh.RefreshManager;
+
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.preferences.*;
@@ -24,6 +27,7 @@
// DEFAULTS
public static final boolean PREF_AUTO_REFRESH_DEFAULT = false;
+ public static final boolean PREF_LIGHTWEIGHT_AUTO_REFRESH = false;
public static final boolean PREF_DISABLE_LINKING_DEFAULT = false;
public static final String PREF_ENCODING_DEFAULT = ""; //$NON-NLS-1$
public static final boolean PREF_AUTO_BUILDING_DEFAULT = true;
@@ -49,6 +53,7 @@
IEclipsePreferences node = new DefaultScope().getNode(ResourcesPlugin.PI_RESOURCES);
// auto-refresh default
node.putBoolean(ResourcesPlugin.PREF_AUTO_REFRESH, PREF_AUTO_REFRESH_DEFAULT);
+ node.putBoolean(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, PREF_LIGHTWEIGHT_AUTO_REFRESH);
// linked resources default
node.putBoolean(ResourcesPlugin.PREF_DISABLE_LINKING, PREF_DISABLE_LINKING_DEFAULT);
Index: src/org/eclipse/core/resources/IFile.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IFile.java,v
retrieving revision 1.63
diff -u -r1.63 IFile.java
--- src/org/eclipse/core/resources/IFile.java 22 Jan 2010 13:25:46 -0000 1.63
+++ src/org/eclipse/core/resources/IFile.java 25 Mar 2011 12:36:11 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 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
@@ -7,9 +7,12 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.resources;
+import org.eclipse.core.internal.refresh.RefreshManager;
+
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
@@ -669,7 +672,8 @@
* This resource could not be read.
* This resource is not local.
* The workspace is not in sync with the corresponding location
- * in the local file system.
+ * in the local file system and {@link RefreshManager#PREF_LIGHTWEIGHT_AUTO_REFRESH} is
+ * disabled.
* The corresponding location in the local file system
* is occupied by a directory.
*
@@ -681,8 +685,17 @@
/**
* Returns an open input stream on the contents of this file.
- * This refinement of the corresponding IStorage
method
- * returns an open input stream on the contents of this file.
+ *
+ * This refinement of the corresponding {@link IStorage} method
+ * is a convenience method returning an open input stream. It's equivalent to:
+ *
+ * getContents(RefreshManager#PREF_LIGHTWEIGHT_AUTO_REFRESH);
+ *
+ *
+ *
+ * If lightweight auto-refresh is not enabled this method will throw a CoreException
+ * when opening out-of-sync resources.
+ *
* The client is responsible for closing the stream when finished.
*
* @return an input stream containing the contents of the file
@@ -690,8 +703,10 @@
*
* - This resource does not exist.
* - This resource is not local.
+ * - The file-system resource is not a file.
* - The workspace is not in sync with the corresponding location
- * in the local file system.
+ * in the local file system (and {@link RefreshManager#PREF_LIGHTWEIGHT_AUTO_REFRESH}
+ * is disabled).
*
*/
public InputStream getContents() throws CoreException;
Index: src/org/eclipse/core/resources/ResourcesPlugin.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java,v
retrieving revision 1.58
diff -u -r1.58 ResourcesPlugin.java
--- src/org/eclipse/core/resources/ResourcesPlugin.java 20 Jan 2011 15:40:00 -0000 1.58
+++ src/org/eclipse/core/resources/ResourcesPlugin.java 25 Mar 2011 12:36:11 -0000
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Serge Beauchamp (Freescale Semiconductor) - [252996] add PT_FILTER_PROVIDERS
* Serge Beauchamp (Freescale Semiconductor) - [229633] add PT_VARIABLE_PROVIDERS
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.resources;
@@ -280,7 +281,9 @@
/**
* Name of a preference for configuring whether the workspace performs auto-
- * refresh.
+ * refresh. Auto-refresh installs a file-system listener, or performs
+ * periodic file-system polling to actively discover changes in the resource
+ * hierarchy.
* @since 3.0
*/
public static final String PREF_AUTO_REFRESH = "refresh.enabled"; //$NON-NLS-1$
#P org.eclipse.core.tests.resources
Index: src/org/eclipse/core/tests/resources/CharsetTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/CharsetTest.java,v
retrieving revision 1.37
diff -u -r1.37 CharsetTest.java
--- src/org/eclipse/core/tests/resources/CharsetTest.java 28 Dec 2010 14:22:46 -0000 1.37
+++ src/org/eclipse/core/tests/resources/CharsetTest.java 25 Mar 2011 12:36:14 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2010 IBM Corporation and others.
+ * Copyright (c) 2004, 2011 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.tests.resources;
@@ -14,9 +15,12 @@
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.internal.preferences.EclipsePreferences;
+import org.eclipse.core.internal.refresh.RefreshManager;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.*;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.InstanceScope;
import org.osgi.service.prefs.BackingStoreException;
public class CharsetTest extends ResourceTest {
@@ -359,11 +363,22 @@
}
}
- public void testBug186984() {
+ /**
+ * Test for getting charset on an IFile:
+ * #getContentDescription() checks file sync state(), always returning the
+ * correct content description, whereas getCharset() uses the cached charset if available.
+ * @throws Exception
+ */
+ public void testBug186984() throws Exception {
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).putBoolean(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, false);
IWorkspace workspace = getWorkspace();
IProject project = workspace.getRoot().getProject(getUniqueString());
IFile file = project.getFile("file.xml");
+ // Test changing content types externally as per bug 186984 Comment 8
+ String ascii = "";
+ String utf = "";
+
// test if we can get the charset, when the file doesn't exist in a file system
try {
file.getCharset(true);
@@ -389,21 +404,64 @@
} catch (CoreException ex) {
fail("3.0");
}
- //getContentDescription checks synchronization state, so it should fail
- try {
- file.getContentDescription();
- fail("3.1");
- } catch (CoreException ex) {
- assertEquals("3.2", IResourceStatus.OUT_OF_SYNC_LOCAL, ex.getStatus().getCode());
- }
- // test if we can get the charset, when the file is refreshed
- try {
- file.refreshLocal(IResource.DEPTH_ZERO, null);
- file.getCharset(true);
- } catch (CoreException ex) {
- fail("4.0");
- }
+ // set the content type within the XML file, ensure that #getContentDescription (which respects sync state)
+ // returns the correct value.
+
+ // 1) first set the content type to ascii
+ file.setContents(new ByteArrayInputStream(ascii.getBytes("ascii")), IResource.FORCE, getMonitor());
+ assertTrue("4.0", file.getCharset().equals("ascii"));
+ assertTrue("4.1", file.getContentDescription().getCharset().equals("ascii"));
+
+ // 2) Make out of sync - Methods should still work, giving the previous value
+ touchInFilesystem(file);
+ assertTrue("4.2", file.getCharset().equals("ascii"));
+ try {
+ file.getContentDescription().getCharset().equals("ascii");
+ assertTrue("4.3", false);
+ } catch (CoreException e) {
+ // expected
+ }
+
+ // As we now know that #getContentDescription correctly checks sync state, just enable LIGHTWEIGHT refresh
+ // for the rest of the test.
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).putBoolean(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, true);
+ assertTrue("4.4", file.getContentDescription().getCharset().equals("ascii"));
+
+ // getContentDescription will have noticed out-of-sync
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+ // Prime the cache...
+ assertTrue("4.5", file.getCharset().equals("ascii"));
+
+ // 3) Change the content type of the file under eclipse's feet
+ FileWriter writer = new FileWriter(file.getLocation().toFile());
+ writer.write(utf);
+ writer.close();
+ touchInFilesystem(file);
+ // #getCharset uses the cached value (bug 209167) - doesn't check sync state
+ assertTrue("5.4", file.getCharset().equals("ascii"));
+ // #getContentDescription checks sync and discovers the real content type
+ assertTrue("5.5", file.getContentDescription().getCharset().equals("UTF-8"));
+ // getContentDescription will have noticed out-of-sync
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+ // #getCharset will now have noticed that the file has changed.
+ assertTrue("5.6", file.getCharset().equals("UTF-8"));
+
+ // 4) Change the content type of the file under eclipse's feet once more (to non-default).
+ writer = new FileWriter(file.getLocation().toFile());
+ writer.write(ascii);
+ writer.close();
+ touchInFilesystem(file);
+ // #getCharset uses the cached value (bug 209167) - doesn't check sync state
+ assertTrue("6.7", file.getCharset().equals("UTF-8"));
+ // #getContentDescription checks sync and discovers the real content type
+ assertTrue("6.8", file.getContentDescription().getCharset().equals("ascii"));
+ // getContentDescription will have noticed out-of-sync
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+ assertTrue("6.9", file.getCharset().equals("ascii"));
+
+ // And disable lightweight refresh again before we leave
+ ResourcesPlugin.getPlugin().getPluginPreferences().setValue(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, false);
}
public void testBug207510() {
Index: src/org/eclipse/core/tests/resources/IResourceTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/IResourceTest.java,v
retrieving revision 1.49
diff -u -r1.49 IResourceTest.java
--- src/org/eclipse/core/tests/resources/IResourceTest.java 6 Oct 2010 19:35:14 -0000 1.49
+++ src/org/eclipse/core/tests/resources/IResourceTest.java 25 Mar 2011 12:36:15 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 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
@@ -18,6 +18,7 @@
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.tests.harness.CancelingProgressMonitor;
import org.eclipse.core.tests.harness.FussyProgressMonitor;
@@ -192,7 +193,7 @@
}
//out of sync
IResource[] unsynchronized = buildResources(root, new String[] {"1/2/3/3"});
- ensureOutOfSync(unsynchronized[0]);
+ ensureOutOfSync((IFile) unsynchronized[0]);
unsynchronizedResources.add(unsynchronized[0]);
//file system only
@@ -424,6 +425,13 @@
/**
* Sets up the workspace and file system for this test. */
protected void setupBeforeState(IResource receiver, IResource target, int state, int depth, boolean addVerifier) throws CoreException {
+ // Wait for any outstanding refresh to finish
+ try {
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+ } catch (InterruptedException e) {
+ fail("interrupted unexpectedly");
+ }
+
if (addVerifier) {
/* install the verifier */
if (verifier == null) {
@@ -466,7 +474,7 @@
break;
case S_CHANGED :
ensureExistsInWorkspace(target, true);
- ensureOutOfSync(target);
+ touchInFilesystem(target);
if (addVerifier) {
verifier.reset();
// we only get a delta if the receiver of refreshLocal
Index: src/org/eclipse/core/tests/resources/ResourceTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/ResourceTest.java,v
retrieving revision 1.29
diff -u -r1.29 ResourceTest.java
--- src/org/eclipse/core/tests/resources/ResourceTest.java 24 Mar 2011 15:33:11 -0000 1.29
+++ src/org/eclipse/core/tests/resources/ResourceTest.java 25 Mar 2011 12:36:15 -0000
@@ -71,7 +71,7 @@
* test is complete
* @see #getTempStore
*/
- private final Set storesToDelete = new HashSet();
+ private final Set storesToDelete = new HashSet();
/**
* Does some garbage collections to free unused resources
@@ -373,7 +373,7 @@
}
protected void cleanup() throws CoreException {
- final IFileStore[] toDelete = (IFileStore[]) storesToDelete.toArray(new IFileStore[0]);
+ final IFileStore[] toDelete = storesToDelete.toArray(new IFileStore[0]);
storesToDelete.clear();
getWorkspace().run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
@@ -658,22 +658,36 @@
}
/**
- * Modifies the resource in the file system so that it is out of sync
+ * Modifies the passed in IFile in the file system so that it is out of sync
* with the workspace.
*/
- public void ensureOutOfSync(final IResource resource) {
- if (resource.getType() != IResource.FILE)
- return;
- IFile file = (IFile) resource;
- ensureExistsInWorkspace(file, true);
- while (file.isSynchronized(IResource.DEPTH_ZERO)) {
- modifyInFileSystem(file);
+ public void ensureOutOfSync(final IFile file) {
+ touchInFilesystem(file);
+ modifyInFileSystem(file);
+ assertTrue("File not out of sync: " + file.getLocation().toOSString(), file.getLocation().toFile().lastModified() != file.getLocalTimeStamp());
+ }
+
+ /**
+ * Touch (but don't modify) the resource in the filesystem so that it's modification stamp is newer than
+ * the cached value in the Workspace.
+ */
+ public void touchInFilesystem(IResource resource) {
+ java.io.File osFile = resource.getLocation().toFile();
+ // Ensure the resource exists in the filesystem
+ if (!osFile.exists())
+ ensureExistsInFileSystem(resource);
+ // Manually check that the core.resource time-stamp is out-of-sync
+ // with the java.io.File last modified. #isSynchronized() will schedule
+ // out-of-sync resources for refresh, so we don't use that here.
+ for (int count = 0; count < 30 && osFile.lastModified() == resource.getLocalTimeStamp(); count++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
+ resource.getLocation().toFile().setLastModified(System.currentTimeMillis());
}
+ assertTrue("File not out of sync: " + resource.getLocation().toOSString(), osFile.lastModified() != resource.getLocalTimeStamp());
}
private boolean existsInFileSystem(IResource resource) {
Index: src/org/eclipse/core/tests/resources/regression/AllTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/AllTests.java,v
retrieving revision 1.45
diff -u -r1.45 AllTests.java
--- src/org/eclipse/core/tests/resources/regression/AllTests.java 12 Jan 2011 09:38:31 -0000 1.45
+++ src/org/eclipse/core/tests/resources/regression/AllTests.java 25 Mar 2011 12:36:15 -0000
@@ -58,6 +58,7 @@
suite.addTest(Bug_265810.suite());
suite.addTest(Bug_264182.suite());
suite.addTest(Bug_288315.suite());
+ suite.addTest(Bug_303517.suite());
suite.addTest(Bug_329836.suite());
suite.addTest(Bug_331445.suite());
suite.addTest(Bug_332543.suite());
Index: src/org/eclipse/core/tests/resources/regression/Bug_303517.java
===================================================================
RCS file: src/org/eclipse/core/tests/resources/regression/Bug_303517.java
diff -N src/org/eclipse/core/tests/resources/regression/Bug_303517.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/core/tests/resources/regression/Bug_303517.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Broadcom 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:
+ * James Blackburn (Broadcom Corp.) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.tests.resources.regression;
+
+import java.io.File;
+import java.io.InputStream;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.eclipse.core.internal.refresh.RefreshManager;
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.core.tests.resources.ResourceTest;
+
+/**
+ * Tests that, when the workspace discovery a resource is out-of-sync
+ * it brings the resource back into sync in a timely manner.
+ */
+public class Bug_303517 extends ResourceTest {
+
+ public static Test suite() {
+ return new TestSuite(Bug_303517.class);
+ }
+
+ String[] resources = new String[] {"/", "/Bug303517/", "/Bug303517/Folder/", "/Bug303517/Folder/Resource",};
+
+ public String[] defineHierarchy() {
+ return resources;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).putBoolean(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, true);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.setUp();
+ InstanceScope.INSTANCE.getNode(ResourcesPlugin.PI_RESOURCES).putBoolean(RefreshManager.PREF_LIGHTWEIGHT_AUTO_REFRESH, false);
+ }
+
+ /**
+ * Tests that file deleted is udpated after #getContents
+ * @throws Exception
+ */
+ public void testExists() throws Exception {
+ createHierarchy();
+ IFile f = getWorkspace().getRoot().getFile(new Path(resources[resources.length - 1]));
+ assertTrue("1.0", f.exists());
+ assertTrue("1.1", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Touch on file-system
+ f.getLocation().toFile().delete();
+ // Core.resources still thinks the file exists
+ assertTrue("1.2", f.exists());
+ try {
+ InputStream in = f.getContents();
+ in.close();
+ assertTrue("1.3", false);
+ } catch (CoreException e) {
+ // File doesn't exist - expected
+ }
+
+ // Wait for auto-refresh to happen
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+
+ // Core.resources should be aware that the file no longer exists...
+ assertFalse("1.4", f.exists());
+ }
+
+ /**
+ * Tests that file discovered out-of-sync during #getContents is updated
+ * @throws Exception
+ */
+ public void testGetContents() throws Exception {
+ createHierarchy();
+ IFile f = getWorkspace().getRoot().getFile(new Path(resources[resources.length - 1]));
+ assertTrue("1.0", f.exists());
+ assertTrue("1.1", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Touch on file-system
+ touchInFilesystem(f);
+ try {
+ InputStream in = f.getContents(false);
+ in.close();
+ assertTrue("1.2", false);
+ } catch (CoreException e) {
+ // File is out-of-sync, so this is good
+ }
+
+ // Wait for auto-refresh to happen
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+
+ // File is now in sync.
+ try {
+ InputStream in = f.getContents(false);
+ in.close();
+ } catch (CoreException e) {
+ // Bad, file shouldn't be out-of-sync
+ fail("1.3", e);
+ }
+ }
+
+ /**
+ * Tests that file discovered out-of-sync during #getContents is updated
+ * @throws Exception
+ */
+ public void testGetContentsTrue() throws Exception {
+ createHierarchy();
+ IFile f = getWorkspace().getRoot().getFile(new Path(resources[resources.length - 1]));
+ assertTrue("1.0", f.exists());
+ assertTrue("1.1", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Touch on file-system
+ touchInFilesystem(f);
+ try {
+ InputStream in = f.getContents(true);
+ in.close();
+ } catch (CoreException e) {
+ // File is out-of-sync, so this is good
+ fail("1.2", e);
+ }
+
+ // Wait for auto-refresh to happen
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+
+ // File is now in sync.
+ try {
+ InputStream in = f.getContents();
+ in.close();
+ } catch (CoreException e) {
+ // Bad, file shouldn't be out-of-sync
+ fail("1.3", e);
+ }
+ }
+
+ /**
+ * Tests that resource discovered out-of-sync during #isSynchronized is updated
+ * @throws Exception
+ */
+ public void testIsSynchronized() throws Exception {
+ createHierarchy();
+ IFile f = getWorkspace().getRoot().getFile(new Path(resources[resources.length - 1]));
+ assertTrue("1.0", f.exists());
+ assertTrue("1.1", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Touch on file-system
+ touchInFilesystem(f);
+ assertFalse("1.2", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Wait for auto-refresh to happen
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+
+ // File is now in sync.
+ assertTrue("1.3", f.isSynchronized(IResource.DEPTH_ONE));
+ }
+
+ /**
+ * Tests that when changing resource gender is correctly picked up.
+ * @throws Exception
+ */
+ public void testChangeResourceGender() throws Exception {
+ createHierarchy();
+ IResource f = getWorkspace().getRoot().getFile(new Path(resources[resources.length - 1]));
+ assertTrue("1.0", f.exists());
+ assertTrue("1.1", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Replace the file with a folder
+ File osResource = f.getLocation().toFile();
+ osResource.delete();
+ osResource.mkdir();
+ assertTrue(osResource.exists());
+ File osChild = new File(osResource, "child");
+ osChild.createNewFile();
+ assertTrue(osChild.exists());
+
+ assertFalse("1.2", f.isSynchronized(IResource.DEPTH_ONE));
+
+ // Wait for auto-refresh to happen
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, getMonitor());
+
+ // File is no longer a file - i.e. still out-of-sync
+ assertFalse("1.3", f.exists());
+ assertFalse("1.4", f.isSynchronized(IResource.DEPTH_ONE));
+ // Folder + child are now in-sync
+ f = getWorkspace().getRoot().getFolder(new Path(resources[resources.length - 1]));
+ assertTrue("1.5", f.exists());
+ assertTrue("1.6", f.isSynchronized(IResource.DEPTH_INFINITE));
+ }
+}
Index: src/org/eclipse/core/tests/resources/regression/IProjectTest.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/resources/regression/IProjectTest.java,v
retrieving revision 1.19
diff -u -r1.19 IProjectTest.java
--- src/org/eclipse/core/tests/resources/regression/IProjectTest.java 20 May 2009 23:50:56 -0000 1.19
+++ src/org/eclipse/core/tests/resources/regression/IProjectTest.java 25 Mar 2011 12:36:17 -0000
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 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
@@ -241,13 +241,7 @@
try {
project.create(null);
project.open(null);
- while (dotProject.isSynchronized(IResource.DEPTH_ZERO)) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- dotProject.getLocation().toFile().setLastModified(System.currentTimeMillis());
- }
+ touchInFilesystem(dotProject);
project.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
fail("0.99", e);