Bug 303833 - [sfs] inconsistent last modified handling
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CacheService.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CacheService.java
index dc74b3d..63ff364 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CacheService.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CacheService.java
@@ -14,9 +14,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -39,7 +36,6 @@
 	private final Lock readLock = this.rwl.readLock();
 	private final Lock writeLock = this.rwl.writeLock();
 	private IContentHandleFactory handleFactory;
-	private static final DateFormat DFFORTRACE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss::SSS"); //$NON-NLS-1$
 
 	/**
 	 * @param handleFactory
@@ -82,43 +78,11 @@
 
 			tempHandle.setContents(input, monitor);
 
-			// os = tempHandle.openOutputStream(append, monitor);
 		} finally {
 			unlockForWrite();
 		}
 
-		// Util.transferStreams(input, os, monitor);
-
-		this.addFromTempHandle(tempHandle, System.currentTimeMillis());
-	}
-
-	public void addContentWithTimestamp(IPath path, InputStream input, long timestamp, int options, IProgressMonitor monitor)
-			throws CoreException {
-
-		boolean append = (options & ISemanticFileSystem.CONTENT_APPEND) > 0;
-
-		if (SfsSpiTraceLocation.CACHESERVICE.isActive()) {
-			SfsSpiTraceLocation.getTrace().traceEntry(SfsSpiTraceLocation.CACHESERVICE.getLocation(),
-					new Object[] {path.toString(), DFFORTRACE.format(new Date(timestamp)), new Boolean(append)});
-		}
-
-		ITemporaryContentHandle tempHandle;
-
-		try {
-			lockForWrite();
-
-			tempHandle = this.handleFactory.createTemporaryHandle(this, path, append);
-
-			tempHandle.setContents(input, monitor);
-
-			// os = tempHandle.openOutputStream(append, monitor);
-		} finally {
-			unlockForWrite();
-		}
-
-		// Util.transferStreams(input, os, monitor);
-
-		this.addFromTempHandle(tempHandle, timestamp);
+		this.addFromTempHandle(tempHandle);
 	}
 
 	public InputStream getContent(IPath path) throws CoreException {
@@ -181,60 +145,6 @@
 		}
 	}
 
-	public long getContentTimestamp(IPath path) throws CoreException {
-
-		if (SfsSpiTraceLocation.CACHESERVICE.isActive()) {
-			SfsSpiTraceLocation.getTrace().traceEntry(SfsSpiTraceLocation.CACHESERVICE.getLocation(), path.toString());
-		}
-
-		try {
-			lockForRead();
-
-			ICachedContentHandle cacheFile = createCacheContentHandle(path);
-
-			long result;
-			if (cacheFile.exists()) {
-				result = cacheFile.lastModified();
-			} else {
-				result = -1;
-			}
-
-			if (SfsSpiTraceLocation.CACHESERVICE.isActive()) {
-				if (result >= 0) {
-					SfsSpiTraceLocation.getTrace().traceExit(SfsSpiTraceLocation.CACHESERVICE.getLocation(),
-							DFFORTRACE.format(new Date(result)));
-				} else {
-					SfsSpiTraceLocation.getTrace().traceExit(SfsSpiTraceLocation.CACHESERVICE.getLocation(), new Long(result));
-				}
-			}
-
-			return result;
-		} finally {
-			unlockForRead();
-		}
-	}
-
-	public void setContentTimestamp(IPath path, long timestamp) throws CoreException {
-
-		if (SfsSpiTraceLocation.CACHESERVICE.isActive()) {
-			SfsSpiTraceLocation.getTrace().traceEntry(SfsSpiTraceLocation.CACHESERVICE.getLocation(),
-					new Object[] {path.toString(), DFFORTRACE.format(new Date(timestamp))});
-		}
-
-		try {
-			lockForWrite();
-
-			ICachedContentHandle cacheFile = createCacheContentHandle(path);
-
-			if (cacheFile.exists()) {
-				cacheFile.setLastModified(timestamp);
-			}
-			// TODO 0.1: if the entry doesn't exist
-		} finally {
-			unlockForWrite();
-		}
-	}
-
 	public void removeContent(IPath path, IProgressMonitor monitor) throws CoreException {
 
 		if (SfsSpiTraceLocation.CACHESERVICE.isActive()) {
@@ -276,15 +186,14 @@
 	 * used from {@link CachingOutputStream#close()}
 	 * 
 	 * @param tempHandle
-	 * @param timestamp
 	 * @throws CoreException
 	 */
-	void addFromTempHandle(ITemporaryContentHandle tempHandle, long timestamp) throws CoreException {
+	void addFromTempHandle(ITemporaryContentHandle tempHandle) throws CoreException {
 
 		try {
 			lockForWrite();
 
-			tempHandle.commit(timestamp);
+			tempHandle.commit();
 
 		} finally {
 			unlockForWrite();
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedFileHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedFileHandle.java
index 8eb31aa..1851bf9 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedFileHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedFileHandle.java
@@ -45,14 +45,6 @@
 		return this.factory.checkFileExists(this.cacheFile);
 	}
 
-	public long lastModified() {
-		return this.factory.getLastModified(this.cacheFile);
-	}
-
-	public void setLastModified(long timestamp) throws CoreException {
-		this.factory.setLastModified(this.cacheFile, timestamp);
-	}
-
 	public void delete() {
 		this.factory.tryDelete(this.cacheFile);
 	}
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedMemoryHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedMemoryHandle.java
index e8a936d..90e0f00 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedMemoryHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachedMemoryHandle.java
@@ -28,7 +28,6 @@
 	private byte[] myContent = new byte[0];
 
 	boolean exists = false;
-	long time = 0l;
 
 	/**
 	 * @param path
@@ -45,14 +44,6 @@
 		return this.exists;
 	}
 
-	public long lastModified() {
-		return this.time;
-	}
-
-	public void setLastModified(long timestamp) {
-		this.time = timestamp;
-	}
-
 	public void delete() {
 		this.exists = false;
 		this.myCache.removeStore(this.myPath);
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachingOutputStream.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachingOutputStream.java
index 7492faf..80e0039 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachingOutputStream.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/CachingOutputStream.java
@@ -42,13 +42,13 @@
 	public void close() throws IOException {
 		InputStream stream = null;
 		try {
+			long timestamp = System.currentTimeMillis();
 
-			this.cacheService.addFromTempHandle(this.fileHandle, System.currentTimeMillis());
+			this.cacheService.addFromTempHandle(this.fileHandle);
 
 			IPath path = this.fileHandle.getKey();
 
 			stream = this.cacheService.getContent(path);
-			long cacheTimestamp = this.cacheService.getContentTimestamp(path);
 			long appendPosition = this.fileHandle.getAppendPosition();
 			long skipped = 0l;
 
@@ -60,7 +60,7 @@
 				throw new IOException(MessageFormat.format(Messages.CachingOutputStream_CouldNotSkip_XMSG, appendPosition, skipped));
 			}
 
-			this.callback.cacheUpdated(stream, cacheTimestamp, this.appendMode);
+			this.callback.cacheUpdated(stream, timestamp, this.appendMode);
 
 		} catch (CoreException e) {
 			// $JL-EXC$ ignore
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/FileHandleFactory.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/FileHandleFactory.java
index 4c499f0..7f29fc3 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/FileHandleFactory.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/FileHandleFactory.java
@@ -260,39 +260,6 @@
 	/**
 	 * 
 	 * @param cacheFile
-	 * @return last modified
-	 */
-	public long getLastModified(File cacheFile) {
-		try {
-			lockForWrite();
-			return getActiveFileHandle(cacheFile).lastModified();
-		} finally {
-			unlockForWrite();
-		}
-	}
-
-	/**
-	 * 
-	 * @param cacheFile
-	 * @param timestamp
-	 * @throws CoreException
-	 */
-	public void setLastModified(File cacheFile, long timestamp) throws CoreException {
-		try {
-			lockForWrite();
-			if (!getActiveFileHandle(cacheFile).setLastModified(timestamp)) {
-				throw new SemanticResourceException(SemanticResourceStatusCode.FILECACHE_ERROR_SETTING_TIMESTAMP, new Path(cacheFile
-						.getAbsolutePath()), MessageFormat.format(Messages.TemporaryFileHandle_TimstampSetOnCommit_XMSG, cacheFile
-						.getAbsolutePath()));
-			}
-		} finally {
-			unlockForWrite();
-		}
-	}
-
-	/**
-	 * 
-	 * @param cacheFile
 	 * @return input stream
 	 * @throws FileNotFoundException
 	 */
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ICachedContentHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ICachedContentHandle.java
index e8eddb4..ba6f4db 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ICachedContentHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ICachedContentHandle.java
@@ -29,21 +29,6 @@
 	public boolean exists();
 
 	/**
-	 * 
-	 * @return the content timestamp
-	 */
-	public long lastModified();
-
-	/**
-	 * 
-	 * @param timestamp
-	 *            the timestamp
-	 * @throws CoreException
-	 *             upon failure
-	 */
-	public void setLastModified(long timestamp) throws CoreException;
-
-	/**
 	 */
 	public void delete();
 
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ITemporaryContentHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ITemporaryContentHandle.java
index d19dc84..7731fa9 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ITemporaryContentHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/ITemporaryContentHandle.java
@@ -24,8 +24,8 @@
  * <p>
  * This is instantiated when content is to be written to the cache. The
  * {@link OutputStream}-like write methods below are used to store the content
- * temporarily. Eventually, the cache service will call the
- * {@link #commit(long)} method which must (logically) copy the content into a
+ * temporarily. Eventually, the cache service will call the {@link #commit()}
+ * method which must (logically) copy the content into a
  * {@link ICachedContentHandle}.
  * 
  */
@@ -38,14 +38,12 @@
 	public IPath getKey();
 
 	/**
-	 * Commits temporary content into cache and sets the timestamp
+	 * Commits temporary content into cache
 	 * 
-	 * @param timestamp
-	 *            the timestamp to set
 	 * @throws CoreException
 	 * 
 	 */
-	public void commit(long timestamp) throws CoreException;
+	public void commit() throws CoreException;
 
 	/**
 	 * 
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryFileHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryFileHandle.java
index 6f10d7d..5f020f1 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryFileHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryFileHandle.java
@@ -76,7 +76,7 @@
 		return this.file;
 	}
 
-	public void commit(long timestamp) throws CoreException {
+	public void commit() throws CoreException {
 
 		try {
 			this.outputStream.flush();
@@ -99,8 +99,6 @@
 		if (!this.appendMode) {
 			this.factory.doRename(this.getFile(), this.cacheFile);
 		}
-
-		this.factory.setLastModified(cacheFile, timestamp);
 	}
 
 	public IPath getKey() {
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryMemoryHandle.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryMemoryHandle.java
index 6279cca..072e061 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryMemoryHandle.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/internal/resources/semantic/cacheservice/TemporaryMemoryHandle.java
@@ -35,15 +35,13 @@
 	/**
 	 * @throws CoreException
 	 */
-	public void commit(long timestamp) throws CoreException {
+	public void commit() throws CoreException {
 		CachedMemoryHandle handle = MemoryCache.getInstance().getOrCreateMemoryStore(this.path.toString());
 		byte[] content;
 
 		Util.safeClose(this.bos);
 		content = this.bos.toByteArray();
 		handle.setContents(content, this.appendMode);
-
-		handle.setLastModified(timestamp);
 	}
 
 	public IPath getKey() {
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/CachingContentProvider.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/CachingContentProvider.java
index 463e9ac..26ec78a 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/CachingContentProvider.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/CachingContentProvider.java
@@ -30,8 +30,6 @@
 import org.eclipse.core.runtime.QualifiedName;
 import org.eclipse.osgi.util.NLS;
 
-
-
 /**
  * This will delegate calls to openInputStream and openOutputStream to local
  * copies of the semantic files.
@@ -61,7 +59,7 @@
  * 
  */
 public abstract class CachingContentProvider extends ContentProvider {
-	
+
 	private static final QualifiedName RESOURCE_TIMESTAMP = new QualifiedName(SemanticResourcesPlugin.PLUGIN_ID, "ResourceTimestamp"); //$NON-NLS-1$
 	// TODO 0.1: add convenience/helper methods to cleanup cache along with
 	// file/folder removal
@@ -151,7 +149,9 @@
 			try {
 				is = openInputStreamInternal(childStore, monitor, setter);
 
-				cacheService.addContentWithTimestamp(path, is, setter.getTimestamp(), EFS.NONE, monitor);
+				cacheService.addContent(path, is, EFS.NONE, monitor);
+
+				setResourceTimestamp(childStore, setter.getTimestamp(), monitor);
 			} finally {
 				Util.safeClose(is);
 			}
@@ -169,9 +169,10 @@
 
 		ICacheUpdateCallback callback = new ICacheUpdateCallback() {
 
-			public void cacheUpdated(InputStream newContent, long cacheTimestamp, boolean append) {
-				onCacheUpdate(childStore, newContent, cacheTimestamp, append, monitor);
+			public void cacheUpdated(InputStream newContent, long timestamp, boolean append) throws CoreException {
+				setResourceTimestamp(childStore, timestamp, monitor);
 
+				onCacheUpdate(childStore, newContent, timestamp, append, monitor);
 			}
 		};
 		return cacheService.wrapOutputStream(path, appendMode, callback, monitor);
@@ -343,8 +344,8 @@
 	 * To be implemented by concrete subclasses.
 	 * <p>
 	 * This method is called both from
-	 * {@link #openInputStream(ISemanticFileStore, IProgressMonitor)} and from
-	 * the default implementation of
+	 * {@link #openInputStream(ISemanticFileStore, IProgressMonitor)} and
+	 * (indirectly) from the default implementation of
 	 * {@link #getResourceTimestamp(ISemanticFileStore, IProgressMonitor)}. This
 	 * method allows retrieval of content and content timestamp with one
 	 * roundtrip (e.g. via plain HTTP GET). But this approach has a drawback
@@ -352,14 +353,9 @@
 	 * update of the resource tree.
 	 * <p>
 	 * Important: The timestamp that is obtained via {@code timeStampSetter}
-	 * parameter is only used to set timestamp on cache service entry.
+	 * parameter is then passed to
 	 * {@link #setResourceTimestamp(ISemanticFileStore, long, IProgressMonitor)}
-	 * method is not called by
-	 * {@link #openInputStream(ISemanticFileStore, IProgressMonitor)}. This is
-	 * done because the standard implementation of
-	 * {@link #getResourceTimestamp(ISemanticFileStore, IProgressMonitor)} uses
-	 * cache service to consistently store both content and timestamps in one
-	 * place.
+	 * method.
 	 * <p>
 	 * Content providers that are able to retrieve the resource timestamp
 	 * independently from content, should override the methods
@@ -367,9 +363,7 @@
 	 * {@link #setResourceTimestamp(ISemanticFileStore, long, IProgressMonitor)}
 	 * and
 	 * {@link #onCacheUpdate(ISemanticFileStore, InputStream, long, boolean, IProgressMonitor)}
-	 * and provide an own timestamp handling that is independent from the cache
-	 * service and allows lazy content retrieval. In this case, the value
-	 * returned via timeStampSetter parameter is irrelevant and may be 0.
+	 * and provide an own timestamp handling that allows lazy content retrieval.
 	 * <p>
 	 * When implementing own timestamp handling, it is important to take into
 	 * account that the method
@@ -415,8 +409,8 @@
 	 *            the semantic file store
 	 * @param newContent
 	 *            the new cache content
-	 * @param cacheTimestamp
-	 *            the timestamp as read from the cache
+	 * @param timestamp
+	 *            the timestamp of the change
 	 * @param append
 	 *            <code>true</code> to indicate that the cache was updated in
 	 *            append mode; in this case, only the appended data will be
@@ -424,30 +418,25 @@
 	 * @param monitor
 	 *            may be null
 	 */
-	public void onCacheUpdate(ISemanticFileStore semanticFileStore, InputStream newContent, long cacheTimestamp, boolean append,
+	public void onCacheUpdate(ISemanticFileStore semanticFileStore, InputStream newContent, long timestamp, boolean append,
 			IProgressMonitor monitor) {
 		// by default, we do nothing
 	}
 
 	public long getResourceTimestamp(ISemanticFileStore semanticFileStore, IProgressMonitor monitor) throws CoreException {
-		
+
+		if (!semanticFileStore.isExists()) {
+			return EFS.NONE;
+		}
 
 		String stampString = semanticFileStore.getPersistentProperty(RESOURCE_TIMESTAMP);
-		if (stampString != null){
+		if (stampString != null) {
 			return Long.parseLong(stampString);
 		}
-		// the cache service can also give some information, but depending on the
-		// underlying file system, precision may be seconds, not milliseconds
-		ICacheService cacheService = this.getCacheService();
-		IPath path = semanticFileStore.getPath();
-		long timestamp = cacheService.getContentTimestamp(path);
 
-		if (timestamp >= 0) {			
-			return timestamp;
-		}
+		// no property set, fill cache that will retrieve the content that will
+		// set the timestamp
 
-		// timestamp == -1 means that the content is not in the cache, so we try
-		// to get it
 		MultiStatus stat = new MultiStatus(SemanticResourcesPlugin.PLUGIN_ID, IStatus.OK, NLS.bind(
 				Messages.CachingContentProvider_FillCache_XGRP, semanticFileStore.getPath().toString()), null);
 
@@ -458,9 +447,10 @@
 			throw new CoreException(stat);
 		}
 
-		timestamp = cacheService.getContentTimestamp(path);
-		if (timestamp >= 0) {
-			return timestamp;
+		// try to read the property again
+		stampString = semanticFileStore.getPersistentProperty(RESOURCE_TIMESTAMP);
+		if (stampString != null) {
+			return Long.parseLong(stampString);
 		}
 
 		throw new SemanticResourceException(SemanticResourceStatusCode.CACHED_CONTENT_NOT_FOUND, semanticFileStore.getPath(),
@@ -468,24 +458,9 @@
 	}
 
 	public void setResourceTimestamp(ISemanticFileStore semanticFileStore, long timestamp, IProgressMonitor monitor) throws CoreException {
-		
-		semanticFileStore.setPersistentProperty(RESOURCE_TIMESTAMP, Long.toString(timestamp));
-		
-		// we also update the cache information, but this is additional information only
-		ICacheService cacheService = this.getCacheService();
-		IPath path = semanticFileStore.getPath();
 
-		if (cacheService.hasContent(path)) {
-			cacheService.setContentTimestamp(path, timestamp);
-		}
-		// TODO we probably don't want to get a cache update, do we?
-//		else {
-//			// ugly as it is, this will set the timestamp on the cache file
-//			// properly
-//			InputStream is = openInputStream(semanticFileStore, monitor);
-//			Util.safeClose(is);
-//			cacheService.setContentTimestamp(path, timestamp);
-//		}
+		semanticFileStore.setPersistentProperty(RESOURCE_TIMESTAMP, Long.toString(timestamp));
+
 	}
 
 }
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheService.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheService.java
index d5c4fce..45ad905 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheService.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheService.java
@@ -15,7 +15,6 @@
 import java.io.OutputStream;
 
 import org.eclipse.core.filesystem.EFS;
-import org.eclipse.core.resources.semantic.ISemanticFileSystem;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -48,25 +47,6 @@
 	public void addContent(IPath path, InputStream input, int options, IProgressMonitor monitor) throws CoreException;
 
 	/**
-	 * Adds the given content to the cache with timestamp
-	 * 
-	 * @param path
-	 *            the path
-	 * @param input
-	 *            the content
-	 * @param timestamp
-	 *            the timestamp
-	 * @param options
-	 *            only {@link ISemanticFileSystem#CONTENT_APPEND} is supported
-	 * @param monitor
-	 *            may be null
-	 * @throws CoreException
-	 *             upon failure
-	 */
-	public void addContentWithTimestamp(IPath path, InputStream input, long timestamp, int options, IProgressMonitor monitor)
-			throws CoreException;
-
-	/**
 	 * @param path
 	 *            the path
 	 * @return the content the content
@@ -89,27 +69,6 @@
 	 * 
 	 * @param path
 	 *            the path
-	 * @return timestamp or -1 if content doesn't exist
-	 * @throws CoreException
-	 *             upon failure
-	 */
-	public long getContentTimestamp(IPath path) throws CoreException;
-
-	/**
-	 * 
-	 * @param path
-	 *            the path
-	 * @param timestamp
-	 *            the timestamp
-	 * @throws CoreException
-	 *             upon failure
-	 */
-	public void setContentTimestamp(IPath path, long timestamp) throws CoreException;
-
-	/**
-	 * 
-	 * @param path
-	 *            the path
 	 * @param monitor
 	 *            may be null
 	 * @throws CoreException
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheUpdateCallback.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheUpdateCallback.java
index 0e08543..bb4061d 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheUpdateCallback.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ICacheUpdateCallback.java
@@ -13,6 +13,8 @@
 
 import java.io.InputStream;
 
+import org.eclipse.core.runtime.CoreException;
+
 /**
  * Called after successful cache updates
  * 
@@ -28,6 +30,7 @@
 	 * @param append
 	 *            if <code>true</code>, the content only represents the appended
 	 *            portion of the cache
+	 * @throws CoreException
 	 */
-	public void cacheUpdated(InputStream newContent, long cacheTimestamp, boolean append);
+	public void cacheUpdated(InputStream newContent, long cacheTimestamp, boolean append) throws CoreException;
 }
diff --git a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ISemanticContentProvider.java b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ISemanticContentProvider.java
index ed16ab9..924c2ec 100644
--- a/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ISemanticContentProvider.java
+++ b/bundles/org.eclipse.core.resources.semantic/src/org/eclipse/core/resources/semantic/spi/ISemanticContentProvider.java
@@ -16,6 +16,7 @@
 
 import org.eclipse.core.filesystem.IFileStore;
 import org.eclipse.core.resources.semantic.ISemanticFileSystem;
+import org.eclipse.core.resources.semantic.ISemanticResource;
 import org.eclipse.core.resources.semantic.SyncDirection;
 import org.eclipse.core.resources.team.FileModificationValidator;
 import org.eclipse.core.runtime.CoreException;
@@ -55,8 +56,7 @@
  * <p>
  * If some data/state must be preserved between Eclipse restarts,
  * {@link ISemanticFileStore#setPersistentProperty(org.eclipse.core.runtime.QualifiedName, String)}
- * should be used.
- * </li>
+ * should be used.</li>
  * </ul>
  * The Semantic File System will initialize content providers via extension
  * point <code>org.eclipse.core.resources.semantic.spi.contentProvider</code>
@@ -427,6 +427,7 @@
 	/**
 	 * This may be called by
 	 * {@link IFileStore#putInfo(org.eclipse.core.filesystem.IFileInfo, int, IProgressMonitor)}
+	 * or other methods.
 	 * <p>
 	 * 
 	 * @param semanticFileStore
diff --git a/examples/org.eclipse.core.resources.semantic.examples/src/org/eclipse/core/resources/semantic/examples/providers/RemoteStoreContentProvider.java b/examples/org.eclipse.core.resources.semantic.examples/src/org/eclipse/core/resources/semantic/examples/providers/RemoteStoreContentProvider.java
index 6d67c03..6e05a18 100644
--- a/examples/org.eclipse.core.resources.semantic.examples/src/org/eclipse/core/resources/semantic/examples/providers/RemoteStoreContentProvider.java
+++ b/examples/org.eclipse.core.resources.semantic.examples/src/org/eclipse/core/resources/semantic/examples/providers/RemoteStoreContentProvider.java
@@ -294,13 +294,13 @@
 				long localTime = -1l;
 				ICacheService srv = getCacheService();
 				if (srv.hasContent(semanticFileStore.getPath())) {
-					localTime = srv.getContentTimestamp(semanticFileStore.getPath());
+					localTime = getResourceTimestamp(semanticFileStore, monitor);
 				}
 				if (direction == SyncDirection.OUTGOING || localTime > remoteTime) {
 					// outgoing
 					OutputStream os = file.getOutputStream(false);
 					Util.transferStreams(srv.getContent(semanticFileStore.getPath()), os, monitor);
-					file.setTimestamp(srv.getContentTimestamp(semanticFileStore.getPath()));
+					file.setTimestamp(localTime);
 					store.serialize(monitor);
 				} else if (direction == SyncDirection.INCOMING || remoteTime > localTime) {
 					// incoming
@@ -417,8 +417,9 @@
 
 		RemoteFile file = ((RemoteFile) item);
 
-		getCacheService().addContentWithTimestamp(semanticFileStore.getPath(), new ByteArrayInputStream(file.getContent()),
-				file.getTimestamp(), ISemanticFileSystem.NONE, monitor);
+		getCacheService().addContent(semanticFileStore.getPath(), new ByteArrayInputStream(file.getContent()), ISemanticFileSystem.NONE,
+				monitor);
+		setResourceTimestamp(semanticFileStore, file.getTimestamp(), monitor);
 		setReadOnly(semanticFileStore, true, monitor);
 
 	}
diff --git a/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/TestsCachingProvider.java b/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/TestsCachingProvider.java
index 14c0cd1..1d12c53 100644
--- a/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/TestsCachingProvider.java
+++ b/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/TestsCachingProvider.java
@@ -28,6 +28,7 @@
 import org.eclipse.core.resources.semantic.ISemanticFile;
 import org.eclipse.core.resources.semantic.ISemanticFileSystem;
 import org.eclipse.core.resources.semantic.ISemanticFolder;
+import org.eclipse.core.resources.semantic.SyncDirection;
 import org.eclipse.core.resources.semantic.spi.Util;
 import org.eclipse.core.resources.semantic.test.provider.CachingTestContentProvider;
 import org.eclipse.core.resources.semantic.test.provider.CachingTestContentProviderBase;
@@ -301,4 +302,119 @@
 		Assert.assertEquals("File existence", false, file.exists());
 
 	}
+
+	/**
+	 * TODO move this to the base class to test all content provider after
+	 * refactoring of tests wrt obtaining the remote file
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void testParallelReadAndWrite() throws Exception {
+
+		final IFolder root = this.testProject.getFolder("root");
+		final IFolder parent = root.getFolder("Folder1");
+
+		final IFile file = parent.getFile("File1");
+		Assert.assertFalse("File should not exist", file.exists());
+
+		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+
+			public void run(IProgressMonitor monitor) throws CoreException {
+				ISemanticFolder sfr = (ISemanticFolder) parent.getAdapter(ISemanticFolder.class);
+				sfr.addFile("File1", ISemanticFileSystem.NONE, monitor);
+				try {
+					Util.transferStreams(new ByteArrayInputStream("New Remote".getBytes("UTF-8")), file1.getOutputStream(false), monitor);
+				} catch (UnsupportedEncodingException e) {
+					throw new RuntimeException(e);
+				}
+			}
+		};
+
+		ResourcesPlugin.getWorkspace().run(runnable, new NullProgressMonitor());
+
+		runnable = new IWorkspaceRunnable() {
+
+			public void run(IProgressMonitor monitor) throws CoreException {
+				InputStream is = null;
+				try {
+					is = file.getContents();
+					assertContentsEqual(file, "Hello");
+
+					ISemanticFile sFile = (ISemanticFile) file.getAdapter(ISemanticFile.class);
+					sFile.synchronizeContentWithRemote(SyncDirection.INCOMING, ISemanticFileSystem.NONE, monitor);
+					// we are still holding the file input stream, so we are
+					// seeing the out dated content
+					assertContentsEqual(file, "New Remote");
+					// drop the input stream
+					Util.safeClose(is);
+
+					// TODO now we need a refresh!
+					file.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+
+					assertContentsEqual(file, "New Remote");
+
+				} finally {
+					Util.safeClose(is);
+				}
+
+			}
+		};
+
+		ResourcesPlugin.getWorkspace().run(runnable, new NullProgressMonitor());
+
+	}
+
+	/**
+	 * 
+	 * TODO move this to the base class to test all content provider after
+	 * refactoring of tests wrt obtaining the remote file
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void testAppendContentsToOpenFile() throws Exception {
+
+		final IFolder root = this.testProject.getFolder("root");
+		final IFolder parent = root.getFolder("Folder1");
+
+		final IFile file = parent.getFile("File1");
+
+		final ISemanticFile sfile = (ISemanticFile) file.getAdapter(ISemanticFile.class);
+
+		IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+
+			public void run(IProgressMonitor monitor) throws CoreException {
+				ISemanticFolder folder = (ISemanticFolder) file.getParent().getAdapter(ISemanticFolder.class);
+				folder.addFile(file.getName(), ISemanticFileSystem.NONE, monitor);
+				assertContentsEqual(file, "Hello");
+				sfile.validateEdit(null);
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+					// $JL-EXC$
+				}
+				file.appendContents(new ByteArrayInputStream(" appended".getBytes()), EFS.NONE, monitor);
+				// TODO does not work with plain provider; fix after integration
+				// of other tests
+				assertContentsEqual(file, "Hello appended");
+				InputStream is = null;
+				try {
+					is = file.getContents();
+					assertContentsEqual(file, "Hello appended");
+					file.appendContents(new ByteArrayInputStream(" again".getBytes()), EFS.NONE, monitor);
+					assertContentsEqual(file, "Hello appended again");
+
+					// TODO this should also work with an opened file
+					sfile.synchronizeContentWithRemote(SyncDirection.OUTGOING, ISemanticFileSystem.NONE, monitor);
+					Assert.assertEquals("Wrong remote content", new String(file1.getContent()), "Hello appended again");
+				} finally {
+					Util.safeClose(is);
+				}
+			}
+		};
+
+		ResourcesPlugin.getWorkspace().run(runnable, new NullProgressMonitor());
+
+	}
 }
diff --git a/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/provider/CachingTestContentProviderBase.java b/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/provider/CachingTestContentProviderBase.java
index 2066dff..a811377 100644
--- a/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/provider/CachingTestContentProviderBase.java
+++ b/tests/org.eclipse.core.resources.semantic.test/src/org/eclipse/core/resources/semantic/test/provider/CachingTestContentProviderBase.java
@@ -54,7 +54,7 @@
  * 
  */
 public abstract class CachingTestContentProviderBase extends CachingContentProvider implements ISemanticContentProviderRemote,
-ISemanticContentProviderLocking {
+		ISemanticContentProviderLocking {
 	/**
 	 * If set to any value, this indicates that write-through should be
 	 * performed
@@ -90,20 +90,20 @@
 	}
 
 	public void addResource(ISemanticFileStore parentStore, String name, ResourceType resourceType, IProgressMonitor monitor)
-	throws CoreException {
+			throws CoreException {
 		switch (resourceType) {
-		case FILE_TYPE:
-			this.addFileFromRemote(parentStore, name, monitor);
-			break;
-		case FOLDER_TYPE:
-			this.addFolderFromRemote(parentStore, name, monitor);
-			break;
-		case UNKNOWN_TYPE:
-			addResourceFromRemote(parentStore, name, monitor);
-			break;
-		default:
-			throw new CoreException(new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, "Can not create resource of type "
-					+ resourceType.name()));
+			case FILE_TYPE :
+				this.addFileFromRemote(parentStore, name, monitor);
+				break;
+			case FOLDER_TYPE :
+				this.addFolderFromRemote(parentStore, name, monitor);
+				break;
+			case UNKNOWN_TYPE :
+				addResourceFromRemote(parentStore, name, monitor);
+				break;
+			default :
+				throw new CoreException(new Status(IStatus.ERROR, SemanticResourcesPlugin.PLUGIN_ID, "Can not create resource of type "
+						+ resourceType.name()));
 		}
 	}
 
@@ -115,7 +115,7 @@
 		RemoteItem item = ((RemoteFolder) parentItem).getChild(name);
 		if (item == null) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.REMOTE_RESOURCE_NOT_FOUND, childStore.getPath(),
-			"No such resource");
+					"No such resource");
 		}
 		if (item.getType() != RemoteItem.Type.FILE) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_WITH_OTHER_TYPE_EXISTS, item.getPath(), "");
@@ -133,7 +133,7 @@
 		RemoteItem item = ((RemoteFolder) parentItem).getChild(name);
 		if (item == null) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.REMOTE_RESOURCE_NOT_FOUND, childStore.getPath(),
-			"No such resource");
+					"No such resource");
 		}
 		if (item.getType() != RemoteItem.Type.FOLDER) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_WITH_OTHER_TYPE_EXISTS, item.getPath(), "");
@@ -152,7 +152,7 @@
 		RemoteItem item = ((RemoteFolder) parentItem).getChild(name);
 		if (item == null) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.REMOTE_RESOURCE_NOT_FOUND, childStore.getPath(),
-			"No such resource");
+					"No such resource");
 		}
 		if (item.getType() == Type.FILE) {
 			addFileFromRemote(childStore, name, monitor);
@@ -165,7 +165,7 @@
 	}
 
 	public void createFileRemotely(ISemanticFileStore childStore, String name, InputStream source, Object context, IProgressMonitor monitor)
-	throws CoreException {
+			throws CoreException {
 
 		byte[] buffer;
 		if (source != null) {
@@ -196,7 +196,7 @@
 	}
 
 	public void createResourceRemotely(ISemanticFileStore childStore, String name, Object context, IProgressMonitor monitor)
-	throws CoreException {
+			throws CoreException {
 
 		createFileRemotely(childStore, name, null, context, monitor);
 
@@ -229,17 +229,15 @@
 	}
 
 	public ISemanticSpiResourceInfo fetchResourceInfo(ISemanticFileStore semanticFileStore, int options, IProgressMonitor monitor)
-	throws CoreException {
-		return new SemanticSpiResourceInfo(options, semanticFileStore
-				.getSessionProperty(LOCKHANDLE) != null, true, semanticFileStore
+			throws CoreException {
+		return new SemanticSpiResourceInfo(options, semanticFileStore.getSessionProperty(LOCKHANDLE) != null, true, semanticFileStore
 				.getPersistentProperty(READONLY) != null,
-				getStore().getItemByPath(semanticFileStore.getPath().removeFirstSegments(2)) != null,
-				null, null);
+				getStore().getItemByPath(semanticFileStore.getPath().removeFirstSegments(2)) != null, null, null);
 	}
 
 	@Override
-	public InputStream openInputStreamInternal(ISemanticFileStore store, IProgressMonitor monitor,
-			ICacheTimestampSetter timeStampSetter) throws CoreException {
+	public InputStream openInputStreamInternal(ISemanticFileStore store, IProgressMonitor monitor, ICacheTimestampSetter timeStampSetter)
+			throws CoreException {
 		RemoteItem item = getStore().getItemByPath(store.getPath().removeFirstSegments(2));
 		if (item.getType() != Type.FILE) {
 			throw new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_WITH_OTHER_TYPE_EXISTS, item.getPath(), "");
@@ -281,12 +279,11 @@
 		}
 	}
 
-	public void synchronizeContentWithRemote(ISemanticFileStore store, SyncDirection direction, IProgressMonitor monitor,
-			MultiStatus status) {
+	public void synchronizeContentWithRemote(ISemanticFileStore store, SyncDirection direction, IProgressMonitor monitor, MultiStatus status) {
 		RemoteItem item = getStore().getItemByPath(store.getPath().removeFirstSegments(2));
 		if (item.getType() != Type.FILE) {
 			status.add(new SemanticResourceException(SemanticResourceStatusCode.RESOURCE_WITH_OTHER_TYPE_EXISTS, item.getPath(), "")
-			.getStatus());
+					.getStatus());
 			return;
 		}
 		try {
@@ -305,7 +302,7 @@
 			ICacheService srv = getCacheService();
 			IPath storePath = store.getPath();
 
-			long localStamp = srv.getContentTimestamp(storePath);
+			long localStamp = getResourceTimestamp(store, monitor);
 			long remoteStamp = file.getTimestamp();
 
 			// we need more elaborate checks here (read-only...)
@@ -331,9 +328,9 @@
 
 			if (syncIn) {
 
-				srv.addContentWithTimestamp(storePath, new ByteArrayInputStream(file.getContent()), file.getTimestamp(),
-						ISemanticFileSystem.NONE, monitor);
+				srv.addContent(storePath, new ByteArrayInputStream(file.getContent()), ISemanticFileSystem.NONE, monitor);
 
+				setResourceTimestamp(store, file.getTimestamp(), monitor);
 			}
 		} catch (CoreException ce) {
 			status.add(ce.getStatus());
diff --git a/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/TestsRestContentProvider.java b/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/TestsRestContentProvider.java
index 576fdc4..a192475 100644
--- a/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/TestsRestContentProvider.java
+++ b/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/TestsRestContentProvider.java
@@ -295,7 +295,7 @@
 
 					try {
 						// make sure we get another file timestamp
-						Thread.sleep(2000);
+						Thread.sleep(100);
 					} catch (InterruptedException e1) {
 						// TODO Auto-generated catch block
 						e1.printStackTrace();
@@ -324,7 +324,7 @@
 
 					try {
 						// make sure we get another file timestamp
-						Thread.sleep(2000);
+						Thread.sleep(100);
 					} catch (InterruptedException e1) {
 						// TODO Auto-generated catch block
 						e1.printStackTrace();
diff --git a/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/provider/RestTestContentProvider.java b/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/provider/RestTestContentProvider.java
index 7e2c309..88e935c 100644
--- a/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/provider/RestTestContentProvider.java
+++ b/tests/org.eclipse.ui.resources.semantic.examples.test/src/org/eclipse/core/resources/semantic/test/provider/RestTestContentProvider.java
@@ -48,29 +48,23 @@
 public class RestTestContentProvider extends SampleRESTReadonlyContentProvider {
 
 	@Override
-	public ISemanticSpiResourceInfo fetchResourceInfo(
-			ISemanticFileStore semanticFileStore, int options,
-			IProgressMonitor monitor) throws CoreException {
+	public ISemanticSpiResourceInfo fetchResourceInfo(ISemanticFileStore semanticFileStore, int options, IProgressMonitor monitor)
+			throws CoreException {
 		String uriString;
-		if (SemanticSpiResourceInfo.isOptionRequested(
-				ISemanticFileSystem.RESOURCE_INFO_URI_STRING, options)) {
+		if (SemanticSpiResourceInfo.isOptionRequested(ISemanticFileSystem.RESOURCE_INFO_URI_STRING, options)) {
 			uriString = this.getURIStringInternal(semanticFileStore);
 		} else {
 			uriString = null;
 		}
 
 		boolean existsRemotely = false;
-		if (SemanticSpiResourceInfo.isOptionRequested(
-				ISemanticFileSystem.RESOURCE_INFO_EXISTS_REMOTELY, options)) {
+		if (SemanticSpiResourceInfo.isOptionRequested(ISemanticFileSystem.RESOURCE_INFO_EXISTS_REMOTELY, options)) {
 
 			String remoteURI = getURIString(semanticFileStore);
 
 			if (remoteURI == null) {
-				throw new SemanticResourceException(
-						SemanticResourceStatusCode.REMOTE_URI_NOT_FOUND,
-						semanticFileStore.getPath(), NLS.bind(
-								"Remote URI is not set for file {0}",
-								semanticFileStore.getPath().toString()));
+				throw new SemanticResourceException(SemanticResourceStatusCode.REMOTE_URI_NOT_FOUND, semanticFileStore.getPath(), NLS.bind(
+						"Remote URI is not set for file {0}", semanticFileStore.getPath().toString()));
 			}
 
 			try {
@@ -84,18 +78,15 @@
 		}
 
 		boolean isReadOnly = isReadOnlyInternal(semanticFileStore);
-		return new SemanticSpiResourceInfo(options, false, false, isReadOnly,
-				existsRemotely, uriString, this
-						.getContentTypeInternal(semanticFileStore));
+		return new SemanticSpiResourceInfo(options, false, false, isReadOnly, existsRemotely, uriString, this
+				.getContentTypeInternal(semanticFileStore));
 	}
 
 	@Override
-	public void revertChanges(ISemanticFileStore semanticFileStore,
-			IProgressMonitor monitor) throws CoreException {
+	public void revertChanges(ISemanticFileStore semanticFileStore, IProgressMonitor monitor) throws CoreException {
 
-		MultiStatus status = new MultiStatus(TestPlugin.PLUGIN_ID, IStatus.OK,
-				NLS.bind("Revert Change Result for {0}", semanticFileStore
-						.getPath().toString()), null);
+		MultiStatus status = new MultiStatus(TestPlugin.PLUGIN_ID, IStatus.OK, NLS.bind("Revert Change Result for {0}", semanticFileStore
+				.getPath().toString()), null);
 		dropCache(semanticFileStore, monitor, new IDropCacheVisitor() {
 
 			public boolean shouldDrop(ISemanticFileStore store) {
@@ -108,19 +99,19 @@
 			throw new CoreException(status);
 		}
 
+		// this can only happen on files, no recursion
+		this.setReadOnly(semanticFileStore, true, monitor);
+
 		fillCache(semanticFileStore, monitor, status);
 
 		if (!status.isOK()) {
 			throw new CoreException(status);
 		}
-		// this can only happen on files, no recursion
-		this.setReadOnly(semanticFileStore, true, monitor);
 	}
 
 	@Override
-	public void synchronizeContentWithRemote(
-			ISemanticFileStore semanticFileStore, SyncDirection direction,
-			IProgressMonitor monitor, MultiStatus status) {
+	public void synchronizeContentWithRemote(ISemanticFileStore semanticFileStore, SyncDirection direction, IProgressMonitor monitor,
+			MultiStatus status) {
 
 		if (semanticFileStore.getType() == ISemanticFileStore.FILE) {
 			if (semanticFileStore.isLocalOnly()) {
@@ -132,9 +123,7 @@
 				uri = new URI(getURIString(semanticFileStore));
 			} catch (URISyntaxException e) {
 				// $JL-EXC$ ignore
-				status.add(new Status(IStatus.ERROR,
-						SemanticResourcesPluginExamples.PLUGIN_ID, e
-								.getMessage()));
+				status.add(new Status(IStatus.ERROR, SemanticResourcesPluginExamples.PLUGIN_ID, e.getMessage()));
 				return;
 			} catch (CoreException e) {
 				status.add(e.getStatus());
@@ -147,25 +136,19 @@
 
 				long remoteTimestamp;
 				try {
-					remoteTimestamp = uri.toURL().openConnection()
-							.getLastModified();
+					remoteTimestamp = uri.toURL().openConnection().getLastModified();
 				} catch (MalformedURLException e) {
 					// $JL-EXC$ ignore
-					status.add(new Status(IStatus.ERROR,
-							SemanticResourcesPluginExamples.PLUGIN_ID, e
-									.getMessage()));
+					status.add(new Status(IStatus.ERROR, SemanticResourcesPluginExamples.PLUGIN_ID, e.getMessage()));
 					return;
 				} catch (IOException e) {
 					// $JL-EXC$ ignore
-					status.add(new Status(IStatus.ERROR,
-							SemanticResourcesPluginExamples.PLUGIN_ID, e
-									.getMessage()));
+					status.add(new Status(IStatus.ERROR, SemanticResourcesPluginExamples.PLUGIN_ID, e.getMessage()));
 					return;
 				}
 				long localTimestamp;
 				try {
-					localTimestamp = getCacheService().getContentTimestamp(
-							semanticFileStore.getPath());
+					localTimestamp = getResourceTimestamp(semanticFileStore, monitor);
 				} catch (CoreException e) {
 					status.add(e.getStatus());
 					return;
@@ -175,25 +158,19 @@
 			}
 
 			if (direction == SyncDirection.INCOMING || syncIn) {
-				this.dropCache(semanticFileStore, monitor,
-						this.deleteAllVisitor, status);
+				this.dropCache(semanticFileStore, monitor, this.deleteAllVisitor, status);
 				this.fillCache(semanticFileStore, monitor, status);
 			}
 			if (direction == SyncDirection.OUTGOING || syncOut) {
 				try {
 					File file = new File(uri);
-					Util.transferStreams(getCacheService().getContent(
-							semanticFileStore.getPath()), new FileOutputStream(
-							file), monitor);
-					file.setLastModified(getCacheService().getContentTimestamp(
-							semanticFileStore.getPath()));
+					Util.transferStreams(getCacheService().getContent(semanticFileStore.getPath()), new FileOutputStream(file), monitor);
+					file.setLastModified(getResourceTimestamp(semanticFileStore, monitor));
 				} catch (CoreException e) {
 					status.add(e.getStatus());
 				} catch (IOException e) {
 					// $JL-EXC$ ignore
-					status.add(new Status(IStatus.ERROR,
-							SemanticResourcesPluginExamples.PLUGIN_ID, e
-									.getMessage()));
+					status.add(new Status(IStatus.ERROR, SemanticResourcesPluginExamples.PLUGIN_ID, e.getMessage()));
 					return;
 				}
 			}
@@ -208,8 +185,7 @@
 			}
 			for (IFileStore store : childStores) {
 				if (store instanceof ISemanticFileStore) {
-					synchronizeContentWithRemote((ISemanticFileStore) store,
-							direction, monitor, status);
+					synchronizeContentWithRemote((ISemanticFileStore) store, direction, monitor, status);
 				}
 			}
 		}
@@ -220,20 +196,17 @@
 	//
 
 	@Override
-	public void addResource(ISemanticFileStore childStore, String name,
-			ResourceType resourceType, IProgressMonitor monitor)
+	public void addResource(ISemanticFileStore childStore, String name, ResourceType resourceType, IProgressMonitor monitor)
 			throws CoreException {
 		switch (resourceType) {
-		case FOLDER_TYPE:
-			// create internal data
-			childStore.addChildFolder(name);
+			case FOLDER_TYPE :
+				// create internal data
+				childStore.addChildFolder(name);
 
-			break;
+				break;
 
-		default:
-			throw new SemanticResourceException(
-					SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, childStore
-							.getPath(), "Not supported");
+			default :
+				throw new SemanticResourceException(SemanticResourceStatusCode.METHOD_NOT_SUPPORTED, childStore.getPath(), "Not supported");
 		}
 	}
 
@@ -246,14 +219,12 @@
 				return e.getStatus();
 			}
 		}
-		return new Status(IStatus.OK,
-				SemanticResourcesPluginExamples.PLUGIN_ID, null);
+		return new Status(IStatus.OK, SemanticResourcesPluginExamples.PLUGIN_ID, null);
 	}
 
 	@Override
 	public IStatus validateSave(ISemanticFileStore semanticFileStore) {
-		return validateEdit(new ISemanticFileStore[] { semanticFileStore },
-				null);
+		return validateEdit(new ISemanticFileStore[] {semanticFileStore}, null);
 	}
 
 }