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));