Refactor WorkbenchPage.saveAll(*) method
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
index fc5c258..f5ac1e1 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
@@ -3607,165 +3607,32 @@
 		if (closing) {
 			// if the parts are going to be closed, then we only save those that
 			// need to be saved when closed, see bug 272070
-			for (Iterator it = dirtyParts.iterator(); it.hasNext();) {
-				ISaveablePart saveablePart = (ISaveablePart) it.next();
-				if (!saveablePart.isSaveOnCloseNeeded()) {
-					it.remove();
-				}
-			}
+			removeSaveOnCloseNotNeededParts(dirtyParts);
 		}
 
 		List modelsToSave;
 		if (confirm) {
-			boolean saveable2Processed = false;
-			// Process all parts that implement ISaveablePart2.
-			// These parts are removed from the list after saving
-			// them. We then need to restore the workbench to
-			// its previous state, for now this is just last
-			// active perspective.
-			// Note that the given parts may come from multiple
-			// windows, pages and perspectives.
-			ListIterator listIterator = dirtyParts.listIterator();
-
-			WorkbenchPage currentPage = null;
-			Perspective currentPageOriginalPerspective = null;
-			while (listIterator.hasNext()) {
-				IWorkbenchPart part = (IWorkbenchPart) listIterator.next();
-				if (part instanceof ISaveablePart2) {
-					WorkbenchPage page = (WorkbenchPage) part.getSite().getPage();
-					if (!Util.equals(currentPage, page)) {
-						if (currentPage != null && currentPageOriginalPerspective != null) {
-							if (!currentPageOriginalPerspective.equals(currentPage
-									.getActivePerspective())) {
-								currentPage
-										.setPerspective(currentPageOriginalPerspective.getDesc());
-							}
-						}
-						currentPage = page;
-						currentPageOriginalPerspective = page.getActivePerspective();
-					}
-					if (confirm) {
-						// if (part instanceof IViewPart) {
-						// Perspective perspective = page
-						// .getFirstPerspectiveWithView((IViewPart) part);
-						// if (perspective != null) {
-						// page.setPerspective(perspective.getDesc());
-						// }
-						// }
-						// // show the window containing the page?
-						// IWorkbenchWindow partsWindow =
-						// page.getWorkbenchWindow();
-						// if (partsWindow !=
-						// partsWindow.getWorkbench().getActiveWorkbenchWindow())
-						// {
-						// Shell shell = partsWindow.getShell();
-						// if (shell.getMinimized()) {
-						// shell.setMinimized(false);
-						// }
-						// shell.setActive();
-						// }
-						page.bringToTop(part);
-					}
-					// try to save the part
-					int choice = SaveableHelper.savePart((ISaveablePart2) part,
-							page.getWorkbenchWindow(), confirm);
-					if (choice == ISaveablePart2.CANCEL) {
-						// If the user cancels, don't restore the previous
-						// workbench state, as that will
-						// be an unexpected switch from the current state.
-						return false;
-					} else if (choice != ISaveablePart2.DEFAULT) {
-						saveable2Processed = true;
-						listIterator.remove();
-					}
-				}
-			}
-
-			// try to restore the workbench to its previous state
-			if (currentPage != null && currentPageOriginalPerspective != null) {
-				if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) {
-					currentPage.setPerspective(currentPageOriginalPerspective.getDesc());
-				}
-			}
-
-			// if processing a ISaveablePart2 caused other parts to be
-			// saved, remove them from the list presented to the user.
-			if (saveable2Processed) {
-				listIterator = dirtyParts.listIterator();
-				while (listIterator.hasNext()) {
-					ISaveablePart part = (ISaveablePart) listIterator.next();
-					if (!part.isDirty()) {
-						listIterator.remove();
-					}
-				}
+			if (processSaveable2(dirtyParts)) {
+				return false;
 			}
 
 			modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources);
-
 			// If nothing to save, return.
 			if (modelsToSave.isEmpty()) {
 				return true;
 			}
-			boolean canceled = SaveableHelper.waitForBackgroundSaveJobs(modelsToSave);
-			if (canceled) {
+
+			if (SaveableHelper.waitForBackgroundSaveJobs(modelsToSave)) {
 				return false;
 			}
-			// Use a simpler dialog if there's only one
+
 			if (modelsToSave.size() == 1) {
-				Saveable model = (Saveable) modelsToSave.get(0);
-				String message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion,
-						model.getName());
-				// Show a dialog.
-				String[] buttons = new String[] { IDialogConstants.YES_LABEL,
-						IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL };
-				MessageDialog d = new MessageDialog(shellProvider.getShell(),
-						WorkbenchMessages.Save_Resource, null, message, MessageDialog.QUESTION,
-						buttons, 0) {
-					@Override
-					protected int getShellStyle() {
-						return super.getShellStyle() | SWT.SHEET;
-					}
-				};
-
-				int choice = SaveableHelper.testGetAutomatedResponse();
-				if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
-					choice = d.open();
-				}
-
-				// Branch on the user choice.
-				// The choice id is based on the order of button labels
-				// above.
-				switch (choice) {
-				case ISaveablePart2.YES: // yes
-					break;
-				case ISaveablePart2.NO: // no
-					return true;
-				default:
-				case ISaveablePart2.CANCEL: // cancel
-					return false;
-				}
+				modelsToSave = promptForSaving(shellProvider, (Saveable) modelsToSave.get(0));
 			} else {
-				ListSelectionDialog dlg = new ListSelectionDialog(shellProvider.getShell(),
-						modelsToSave, new ArrayContentProvider(), new WorkbenchPartLabelProvider(),
-						WorkbenchMessages.EditorManager_saveResourcesMessage) {
-					@Override
-					protected int getShellStyle() {
-						return super.getShellStyle() | SWT.SHEET;
-					}
-				};
-				dlg.setInitialSelections(modelsToSave.toArray());
-				dlg.setTitle(WorkbenchMessages.EditorManager_saveResourcesTitle);
-
-				// this "if" statement aids in testing.
-				if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
-					int result = dlg.open();
-					// Just return false to prevent the operation continuing
-					if (result == IDialogConstants.CANCEL_ID) {
-						return false;
-					}
-
-					modelsToSave = Arrays.asList(dlg.getResult());
-				}
+				modelsToSave = promptForSaving(shellProvider, modelsToSave);
+			}
+			if (modelsToSave == null) {
+				return false;
 			}
 		} else {
 			modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources);
@@ -3778,7 +3645,184 @@
 
 		// Create save block.
 		final List finalModels = modelsToSave;
-		IRunnableWithProgress progressOp = new IRunnableWithProgress() {
+		IRunnableWithProgress progressOp = createRunnableWithProgress(confirm, closing, shellProvider, finalModels);
+
+		// Do the save.
+		return SaveableHelper.runProgressMonitorOperation(WorkbenchMessages.Save_All, progressOp,
+				runnableContext, shellProvider);
+	}
+
+	/**
+	 * Removes from the provided list parts that don't need to be saved on
+	 * close.
+	 *
+	 * @param parts
+	 *            the list of the parts (ISaveablePart)
+	 */
+	private static void removeSaveOnCloseNotNeededParts(List parts) {
+		for (Iterator it = parts.iterator(); it.hasNext();) {
+			ISaveablePart saveablePart = (ISaveablePart) it.next();
+			if (!saveablePart.isSaveOnCloseNeeded()) {
+				it.remove();
+			}
+		}
+	}
+
+	/**
+	 * Processes all parts that implement ISaveablePart2 and removes them from
+	 * the list.
+	 *
+	 * @param dirtyParts
+	 *            the list of the parts
+	 * @return true if cancelled
+	 */
+	private static boolean processSaveable2(List dirtyParts) {
+		boolean saveable2Processed = false;
+		// Process all parts that implement ISaveablePart2.
+		// These parts are removed from the list after saving
+		// them. We then need to restore the workbench to
+		// its previous state, for now this is just last
+		// active perspective.
+		// Note that the given parts may come from multiple
+		// windows, pages and perspectives.
+		ListIterator listIterator = dirtyParts.listIterator();
+
+		WorkbenchPage currentPage = null;
+		Perspective currentPageOriginalPerspective = null;
+		while (listIterator.hasNext()) {
+			IWorkbenchPart part = (IWorkbenchPart) listIterator.next();
+			if (part instanceof ISaveablePart2) {
+				WorkbenchPage page = (WorkbenchPage) part.getSite().getPage();
+				if (!Util.equals(currentPage, page)) {
+					if (currentPage != null && currentPageOriginalPerspective != null) {
+						if (!currentPageOriginalPerspective.equals(currentPage
+								.getActivePerspective())) {
+							currentPage
+									.setPerspective(currentPageOriginalPerspective.getDesc());
+						}
+					}
+					currentPage = page;
+					currentPageOriginalPerspective = page.getActivePerspective();
+				}
+				page.bringToTop(part);
+				// try to save the part
+				int choice = SaveableHelper.savePart((ISaveablePart2) part, page.getWorkbenchWindow(), true);
+				if (choice == ISaveablePart2.CANCEL) {
+					// If the user cancels, don't restore the previous
+					// workbench state, as that will
+					// be an unexpected switch from the current state.
+					return true;
+				} else if (choice != ISaveablePart2.DEFAULT) {
+					saveable2Processed = true;
+					listIterator.remove();
+				}
+			}
+		}
+
+		// try to restore the workbench to its previous state
+		if (currentPage != null && currentPageOriginalPerspective != null) {
+			if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) {
+				currentPage.setPerspective(currentPageOriginalPerspective.getDesc());
+			}
+		}
+
+		// if processing a ISaveablePart2 caused other parts to be
+		// saved, remove them from the list presented to the user.
+		if (saveable2Processed) {
+			removeNonDirtyParts(dirtyParts);
+		}
+
+		return false;
+	}
+
+	private static void removeNonDirtyParts(List parts) {
+		ListIterator listIterator;
+		listIterator = parts.listIterator();
+		while (listIterator.hasNext()) {
+			ISaveablePart part = (ISaveablePart) listIterator.next();
+			if (!part.isDirty()) {
+				listIterator.remove();
+			}
+		}
+	}
+
+	/**
+	 * Prompt the user to save the given saveable.
+	 *
+	 * @param shellProvider
+	 *            the provider used to obtain a shell in prompting is required
+	 * @param modelToSave
+	 *            the saveable to be saved
+	 * @return a list with the model to save (empty if the saveable is not
+	 *         accepted to be saved) or null if canceled
+	 */
+	private static List promptForSaving(final IShellProvider shellProvider, Saveable modelToSave) {
+		String message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion,
+ modelToSave.getName());
+		// Show a dialog.
+		String[] buttons = new String[] { IDialogConstants.YES_LABEL,
+				IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL };
+		MessageDialog d = new MessageDialog(shellProvider.getShell(),
+				WorkbenchMessages.Save_Resource, null, message, MessageDialog.QUESTION,
+				buttons, 0) {
+			@Override
+			protected int getShellStyle() {
+				return super.getShellStyle() | SWT.SHEET;
+			}
+		};
+
+		int choice = SaveableHelper.testGetAutomatedResponse();
+		if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
+			choice = d.open();
+		}
+		if (choice == ISaveablePart2.CANCEL) {
+			return null;
+		}
+
+		List<Saveable> modelsToSave = new ArrayList<Saveable>();
+		if (choice != ISaveablePart2.NO) {
+			modelsToSave.add(modelToSave);
+		}
+		return modelsToSave;
+	}
+
+	/**
+	 * Prompt the user to save the given saveables.
+	 *
+	 * @param shellProvider
+	 *            the provider used to obtain a shell in prompting is required
+	 * @param modelsToSave
+	 *            the saveables to be saved
+	 * @return a list with the models selected to save or null if canceled
+	 */
+	private static List promptForSaving(final IShellProvider shellProvider, List modelsToSave) {
+		ListSelectionDialog dlg = new ListSelectionDialog(shellProvider.getShell(), modelsToSave,
+				new ArrayContentProvider(), new WorkbenchPartLabelProvider(),
+				WorkbenchMessages.EditorManager_saveResourcesMessage) {
+			@Override
+			protected int getShellStyle() {
+				return super.getShellStyle() | SWT.SHEET;
+			}
+		};
+		dlg.setInitialSelections(modelsToSave.toArray());
+		dlg.setTitle(WorkbenchMessages.EditorManager_saveResourcesTitle);
+
+		// this "if" statement aids in testing.
+		if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
+			int result = dlg.open();
+			// Just return false to prevent the operation continuing
+			if (result == IDialogConstants.CANCEL_ID) {
+				return null;
+			}
+
+			modelsToSave = Arrays.asList(dlg.getResult());
+		}
+		return modelsToSave;
+	}
+
+	private static IRunnableWithProgress createRunnableWithProgress(final boolean confirm, final boolean closing,
+			final IShellProvider shellProvider, final List finalModels) {
+		return new IRunnableWithProgress() {
 			@Override
 			public void run(IProgressMonitor monitor) {
 				IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor);
@@ -3791,8 +3835,8 @@
 						monitor.worked(1);
 						continue;
 					}
-					SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1),
-							shellProvider, closing || confirm);
+					SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), shellProvider, closing
+							|| confirm);
 					if (monitorWrap.isCanceled()) {
 						break;
 					}
@@ -3800,10 +3844,6 @@
 				monitorWrap.done();
 			}
 		};
-
-		// Do the save.
-		return SaveableHelper.runProgressMonitorOperation(WorkbenchMessages.Save_All, progressOp,
-				runnableContext, shellProvider);
 	}
 
 	/**