Bug 333726 - [prefs] EclipsePreferences#flush synchronization problems
diff --git a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectPreferences.java b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectPreferences.java
index 2591599..a33e826 100644
--- a/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectPreferences.java
+++ b/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectPreferences.java
@@ -346,7 +346,8 @@
 			return;
 		isWriting = true;
 		try {
-			super.flush();
+			// call the internal method because we don't want to be synchronized, we will do that ourselves later.
+			super.internalFlush();
 		} finally {
 			isWriting = false;
 		}
@@ -512,70 +513,71 @@
 				Policy.debug("Not saving preferences since there is no file for node: " + absolutePath()); //$NON-NLS-1$
 			return;
 		}
-		Properties table = convertToProperties(new SortedProperties(), ""); //$NON-NLS-1$
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
 		IResourceRuleFactory factory = workspace.getRuleFactory();
+		final BackingStoreException[] bse = new BackingStoreException[1];
 		try {
-			if (table.isEmpty()) {
-				IWorkspaceRunnable operation = new IWorkspaceRunnable() {
-					public void run(IProgressMonitor monitor) throws CoreException {
-						// nothing to save. delete existing file if one exists.
-						if (fileInWorkspace.exists()) {
-							if (Policy.DEBUG_PREFERENCES)
-								Policy.debug("Deleting preference file: " + fileInWorkspace.getFullPath()); //$NON-NLS-1$
-							if (fileInWorkspace.isReadOnly()) {
-								IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT);
-								if (!status.isOK())
-									throw new CoreException(status);
-							}
-							try {
-								fileInWorkspace.delete(true, null);
-							} catch (CoreException e) {
-								String message = NLS.bind(Messages.preferences_deleteException, fileInWorkspace.getFullPath());
-								log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IStatus.WARNING, message, null));
-							}
-						}
-					}
-				};
-				ISchedulingRule rule = factory.deleteRule(fileInWorkspace);
-				try {
-					ResourcesPlugin.getWorkspace().run(operation, rule, IResource.NONE, null);
-				} catch (OperationCanceledException e) {
-					throw new BackingStoreException(Messages.preferences_operationCanceled);
-				}
-				return;
-			}
-			table.put(VERSION_KEY, VERSION_VALUE);
-			// print the table to a string and remove the timestamp that Properties#store always adds
-			String s = removeTimestampFromTable(table);
-			final InputStream input = new BufferedInputStream(new ByteArrayInputStream(s.getBytes("UTF-8"))); //$NON-NLS-1$
-			final String finalQualifier = qualifier;
 			IWorkspaceRunnable operation = new IWorkspaceRunnable() {
 				public void run(IProgressMonitor monitor) throws CoreException {
-					if (fileInWorkspace.exists()) {
-						if (Policy.DEBUG_PREFERENCES)
-							Policy.debug("Setting preference file contents for: " + fileInWorkspace.getFullPath()); //$NON-NLS-1$
-						if (fileInWorkspace.isReadOnly()) {
-							IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT);
-							if (!status.isOK())
-								throw new CoreException(status);
+					try {
+						Properties table = convertToProperties(new SortedProperties(), ""); //$NON-NLS-1$
+						// nothing to save. delete existing file if one exists.
+						if (table.isEmpty()) {
+							if (fileInWorkspace.exists()) {
+								if (Policy.DEBUG_PREFERENCES)
+									Policy.debug("Deleting preference file: " + fileInWorkspace.getFullPath()); //$NON-NLS-1$
+								if (fileInWorkspace.isReadOnly()) {
+									IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT);
+									if (!status.isOK())
+										throw new CoreException(status);
+								}
+								try {
+									fileInWorkspace.delete(true, null);
+								} catch (CoreException e) {
+									String message = NLS.bind(Messages.preferences_deleteException, fileInWorkspace.getFullPath());
+									log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IStatus.WARNING, message, null));
+								}
+							}
+							return;
 						}
-						// set the contents
-						fileInWorkspace.setContents(input, IResource.KEEP_HISTORY, null);
-					} else {
-						// create the file
-						IFolder folder = (IFolder) fileInWorkspace.getParent();
-						if (!folder.exists()) {
+						table.put(VERSION_KEY, VERSION_VALUE);
+						// print the table to a string and remove the timestamp that Properties#store always adds
+						String s = removeTimestampFromTable(table);
+						final InputStream input = new BufferedInputStream(new ByteArrayInputStream(s.getBytes("UTF-8"))); //$NON-NLS-1$
+						final String finalQualifier = qualifier;
+						if (fileInWorkspace.exists()) {
 							if (Policy.DEBUG_PREFERENCES)
-								Policy.debug("Creating parent preference directory: " + folder.getFullPath()); //$NON-NLS-1$
-							folder.create(IResource.NONE, true, null);
+								Policy.debug("Setting preference file contents for: " + fileInWorkspace.getFullPath()); //$NON-NLS-1$
+							if (fileInWorkspace.isReadOnly()) {
+								IStatus status = fileInWorkspace.getWorkspace().validateEdit(new IFile[] {fileInWorkspace}, IWorkspace.VALIDATE_PROMPT);
+								if (!status.isOK()) {
+									input.close();
+									throw new CoreException(status);
+								}
+							}
+							// set the contents
+							fileInWorkspace.setContents(input, IResource.KEEP_HISTORY, null);
+						} else {
+							// create the file
+							IFolder folder = (IFolder) fileInWorkspace.getParent();
+							if (!folder.exists()) {
+								if (Policy.DEBUG_PREFERENCES)
+									Policy.debug("Creating parent preference directory: " + folder.getFullPath()); //$NON-NLS-1$
+								folder.create(IResource.NONE, true, null);
+							}
+							if (Policy.DEBUG_PREFERENCES)
+								Policy.debug("Creating preference file: " + fileInWorkspace.getLocation()); //$NON-NLS-1$
+							fileInWorkspace.create(input, IResource.NONE, null);
 						}
-						if (Policy.DEBUG_PREFERENCES)
-							Policy.debug("Creating preference file: " + fileInWorkspace.getLocation()); //$NON-NLS-1$
-						fileInWorkspace.create(input, IResource.NONE, null);
+						if (PREFS_DERIVED_QUALIFIER.equals(finalQualifier))
+							fileInWorkspace.setDerived(true, null);
+					} catch (BackingStoreException e) {
+						bse[0] = e;
+					} catch (IOException e) {
+						String message = NLS.bind(Messages.preferences_saveProblems, fileInWorkspace.getFullPath());
+						log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e));
+						bse[0] = new BackingStoreException(message);
 					}
-					if (PREFS_DERIVED_QUALIFIER.equals(finalQualifier))
-						fileInWorkspace.setDerived(true, null);
 				}
 			};
 			//don't bother with scheduling rules if we are already inside an operation
@@ -584,16 +586,14 @@
 					operation.run(null);
 				} else {
 					// we might: create the .settings folder, create the file, modify the file, or set derived flag for the file.
-					ISchedulingRule rule = MultiRule.combine(new ISchedulingRule[] {factory.createRule(fileInWorkspace.getParent()), factory.modifyRule(fileInWorkspace), factory.derivedRule(fileInWorkspace)});
+					ISchedulingRule rule = MultiRule.combine(new ISchedulingRule[] {factory.deleteRule(fileInWorkspace), factory.createRule(fileInWorkspace.getParent()), factory.modifyRule(fileInWorkspace), factory.derivedRule(fileInWorkspace)});
 					workspace.run(operation, rule, IResource.NONE, null);
+					if (bse[0] != null)
+						throw bse[0];
 				}
 			} catch (OperationCanceledException e) {
 				throw new BackingStoreException(Messages.preferences_operationCanceled);
 			}
-		} catch (IOException e) {
-			String message = NLS.bind(Messages.preferences_saveProblems, fileInWorkspace.getFullPath());
-			log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e));
-			throw new BackingStoreException(message);
 		} catch (CoreException e) {
 			String message = NLS.bind(Messages.preferences_saveProblems, fileInWorkspace.getFullPath());
 			log(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, e));