Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 482162
Collapse All | Expand All

(-)a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java (-3 / +13 lines)
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Terry Parker <tparker@google.com> - Bug 416673
10
 ******************************************************************************/
11
 ******************************************************************************/
11
12
12
package org.eclipse.e4.ui.internal.workbench.swt;
13
package org.eclipse.e4.ui.internal.workbench.swt;
Lines 167-176 public class E4Application implements IApplication { Link Here
167
168
168
	public void saveModel() {
169
	public void saveModel() {
169
		try {
170
		try {
170
			handler.save();
171
			if (!(handler instanceof ResourceHandler)
172
					|| ((ResourceHandler) handler).hasTopLevelWindows()) {
173
				handler.save();
174
			} else {
175
				Logger logger = new WorkbenchLogger(PLUGIN_ID);
176
				logger.error(
177
						new Exception(), // log a stack trace for debugging
178
						"Attempted to save a workbench model that had no top-level windows! " //$NON-NLS-1$
179
								+ "Skipped saving the model to avoid corruption."); //$NON-NLS-1$
180
			}
171
		} catch (IOException e) {
181
		} catch (IOException e) {
172
			// TODO Auto-generated catch block
182
			Logger logger = new WorkbenchLogger(PLUGIN_ID);
173
			e.printStackTrace();
183
			logger.error(e, "Error saving the workbench model"); //$NON-NLS-1$
174
		}
184
		}
175
	}
185
	}
176
186
(-)a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java (-2 / +43 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2009, 2012 IBM Corporation and others.
2
 * Copyright (c) 2009, 2014 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Terry Parker <tparker@google.com> - Bug 416673
10
 ******************************************************************************/
11
 ******************************************************************************/
11
12
12
package org.eclipse.e4.ui.internal.workbench;
13
package org.eclipse.e4.ui.internal.workbench;
Lines 121-126 public class ResourceHandler implements IModelResourceHandler { Link Here
121
122
122
	}
123
	}
123
124
125
	/**
126
	 * @return {@code true} if the current application model has top-level windows.
127
	 */
128
	public boolean hasTopLevelWindows() {
129
		return hasTopLevelWindows(resource);
130
	}
131
132
	/**
133
	 * @return {@code true} if the specified application model has top-level windows.
134
	 */
135
	private boolean hasTopLevelWindows(Resource applicationResource) {
136
		if (applicationResource == null || applicationResource.getContents() == null) {
137
			// If the application resource doesn't exist or has no contents, then it has no
138
			// top-level windows (and we are in an error state).
139
			return false;
140
		}
141
		MApplication application = (MApplication) applicationResource.getContents().get(0);
142
		return !application.getChildren().isEmpty();
143
	}
144
124
	public Resource loadMostRecentModel() {
145
	public Resource loadMostRecentModel() {
125
		File baseLocation;
146
		File baseLocation;
126
		try {
147
		try {
Lines 173-180 public class ResourceHandler implements IModelResourceHandler { Link Here
173
						logger.error(e);
194
						logger.error(e);
174
					}
195
					}
175
				}
196
				}
176
				if (appElement != null)
197
				if (appElement != null) {
177
					resource.getContents().add((EObject) appElement);
198
					resource.getContents().add((EObject) appElement);
199
					if (!hasTopLevelWindows(resource) && logger != null) {
200
						logger.error("No top-level windows seen when migrating from existing delta files"); //$NON-NLS-1$
201
					}
202
				}
178
				return resource;
203
				return resource;
179
			}
204
			}
180
		}
205
		}
Lines 200-205 public class ResourceHandler implements IModelResourceHandler { Link Here
200
		resource = null;
225
		resource = null;
201
		if (restore && saveAndRestore) {
226
		if (restore && saveAndRestore) {
202
			resource = loadResource(restoreLocation);
227
			resource = loadResource(restoreLocation);
228
			// If the saved model does not have any top-level windows, Eclipse will exit
229
			// immediately, so throw out the persisted state and reinitialize with the defaults.
230
			if (!hasTopLevelWindows(resource)) {
231
				if (logger != null) {
232
					logger.error(new Exception(), // log a stack trace to help debug the corruption
233
							"The persisted workbench has no top-level windows, so reinitializing with defaults."); //$NON-NLS-1$
234
				}
235
				resource = null;
236
			}
203
		}
237
		}
204
		if (resource == null) {
238
		if (resource == null) {
205
			Resource applicationResource = loadResource(applicationDefinitionInstance);
239
			Resource applicationResource = loadResource(applicationDefinitionInstance);
Lines 220-225 public class ResourceHandler implements IModelResourceHandler { Link Here
220
				context);
254
				context);
221
		contribProcessor.processModel();
255
		contribProcessor.processModel();
222
256
257
		if (!hasTopLevelWindows(resource) && logger != null) {
258
			logger.error(new Exception(), // log a stack trace to help debug the
259
											// corruption
260
					"Initializing from the application definition instance yields no top-level windows! " //$NON-NLS-1$
261
							+ "Continuing execution, but the missing windows may cause other initialization failures."); //$NON-NLS-1$
262
		}
263
223
		return resource;
264
		return resource;
224
	}
265
	}
225
266
(-)a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java (+17 lines)
Lines 1732-1737 UIEvents.Context.TOPIC_CONTEXT, Link Here
1732
					}
1732
					}
1733
				});
1733
				});
1734
		
1734
		
1735
		eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN, new EventHandler() {
1736
			public void handleEvent(org.osgi.service.event.Event event) {
1737
				Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
1738
				if (!(element instanceof MApplication)) {
1739
					return;
1740
				}
1741
				MApplication app = (MApplication) element;
1742
				if (UIEvents.isREMOVE(event)) {
1743
					if (app.getChildren().isEmpty()) {
1744
						Object oldValue = event.getProperty(UIEvents.EventTags.OLD_VALUE);
1745
						WorkbenchPlugin.log("The final top level window " + oldValue //$NON-NLS-1$
1746
								+ " was just removed", new Exception()); //$NON-NLS-1$
1747
					}
1748
				}
1749
			}
1750
		});
1751
1735
		boolean found = false;
1752
		boolean found = false;
1736
		List<MPartDescriptor> currentDescriptors = application.getDescriptors();
1753
		List<MPartDescriptor> currentDescriptors = application.getDescriptors();
1737
		for (MPartDescriptor desc : currentDescriptors) {
1754
		for (MPartDescriptor desc : currentDescriptors) {
(-)a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java (-1 / +26 lines)
Lines 1203-1210 public class WorkbenchWindow implements IWorkbenchWindow { Link Here
1203
	 * Assumes that busy cursor is active.
1203
	 * Assumes that busy cursor is active.
1204
	 */
1204
	 */
1205
	private boolean busyClose(boolean remove) {
1205
	private boolean busyClose(boolean remove) {
1206
		if (closing)
1206
		/*
1207
		 * Warning: Intricate flow of control and re-entrant invocations of this
1208
		 * method:
1209
		 *
1210
		 * - busyClose(true) is called from WorkbenchWindow#close() when the
1211
		 * user closes a workbench window.
1212
		 *
1213
		 * - busyClose(false) is called from Workbench#close(int, boolean). This
1214
		 * happens on File > Exit/Restart, [Mac] Quit Eclipse, AND ... tadaa ...
1215
		 * from busyClose(true) when the user closes the last window => [Case A]
1216
		 *
1217
		 * Additional complication: busyClose(true) can also be called again
1218
		 * when someone runs an event loop during the shutdown sequence. In that
1219
		 * case, the nested busyClose(true) should be dropped (bug 381555) =>
1220
		 * [Case B]
1221
		 */
1222
		if (closing) {
1223
			// [Case A] Window is already closing.
1224
			return false;
1225
		}
1226
		if (updateDisabled && remove) {
1227
			// [Case B] User closed this window, which triggered
1228
			// "workbench.close()", during which the user tried to close this
1229
			// window again.
1207
			return false;
1230
			return false;
1231
		}
1232
1208
		// Whether the window was actually closed or not
1233
		// Whether the window was actually closed or not
1209
		boolean windowClosed = false;
1234
		boolean windowClosed = false;
1210
1235

Return to bug 482162