KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > Workbench


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal;
13
14 import java.io.BufferedInputStream JavaDoc;
15 import java.io.BufferedReader JavaDoc;
16 import java.io.File JavaDoc;
17 import java.io.FileInputStream JavaDoc;
18 import java.io.FileOutputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.InputStreamReader JavaDoc;
22 import java.io.OutputStreamWriter JavaDoc;
23 import java.lang.reflect.Method JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Dictionary JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Set JavaDoc;
31
32 import org.eclipse.core.commands.Command;
33 import org.eclipse.core.commands.CommandManager;
34 import org.eclipse.core.commands.common.EventManager;
35 import org.eclipse.core.commands.contexts.ContextManager;
36 import org.eclipse.core.databinding.observable.Realm;
37 import org.eclipse.core.runtime.Assert;
38 import org.eclipse.core.runtime.IAdaptable;
39 import org.eclipse.core.runtime.IExtension;
40 import org.eclipse.core.runtime.IExtensionDelta;
41 import org.eclipse.core.runtime.IExtensionPoint;
42 import org.eclipse.core.runtime.IExtensionRegistry;
43 import org.eclipse.core.runtime.IPath;
44 import org.eclipse.core.runtime.IProduct;
45 import org.eclipse.core.runtime.IProgressMonitor;
46 import org.eclipse.core.runtime.IRegistryChangeEvent;
47 import org.eclipse.core.runtime.IRegistryChangeListener;
48 import org.eclipse.core.runtime.IStatus;
49 import org.eclipse.core.runtime.ListenerList;
50 import org.eclipse.core.runtime.MultiStatus;
51 import org.eclipse.core.runtime.Platform;
52 import org.eclipse.core.runtime.SafeRunner;
53 import org.eclipse.core.runtime.Status;
54 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
55 import org.eclipse.core.runtime.jobs.Job;
56 import org.eclipse.jface.action.ActionContributionItem;
57 import org.eclipse.jface.action.ExternalActionManager;
58 import org.eclipse.jface.action.IAction;
59 import org.eclipse.jface.action.MenuManager;
60 import org.eclipse.jface.action.ExternalActionManager.CommandCallback;
61 import org.eclipse.jface.action.ExternalActionManager.IActiveChecker;
62 import org.eclipse.jface.bindings.BindingManager;
63 import org.eclipse.jface.bindings.BindingManagerEvent;
64 import org.eclipse.jface.bindings.IBindingManagerListener;
65 import org.eclipse.jface.databinding.swt.SWTObservables;
66 import org.eclipse.jface.dialogs.ErrorDialog;
67 import org.eclipse.jface.dialogs.IDialogConstants;
68 import org.eclipse.jface.dialogs.MessageDialog;
69 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
70 import org.eclipse.jface.operation.IRunnableContext;
71 import org.eclipse.jface.operation.ModalContext;
72 import org.eclipse.jface.preference.IPreferenceStore;
73 import org.eclipse.jface.preference.PreferenceManager;
74 import org.eclipse.jface.resource.ImageDescriptor;
75 import org.eclipse.jface.util.OpenStrategy;
76 import org.eclipse.jface.util.SafeRunnable;
77 import org.eclipse.jface.viewers.ISelection;
78 import org.eclipse.jface.window.IShellProvider;
79 import org.eclipse.jface.window.Window;
80 import org.eclipse.jface.window.WindowManager;
81 import org.eclipse.osgi.service.runnable.StartupMonitor;
82 import org.eclipse.osgi.util.NLS;
83 import org.eclipse.swt.SWT;
84 import org.eclipse.swt.custom.BusyIndicator;
85 import org.eclipse.swt.graphics.DeviceData;
86 import org.eclipse.swt.graphics.Image;
87 import org.eclipse.swt.widgets.Control;
88 import org.eclipse.swt.widgets.Display;
89 import org.eclipse.swt.widgets.Event;
90 import org.eclipse.swt.widgets.Listener;
91 import org.eclipse.swt.widgets.Shell;
92 import org.eclipse.ui.IDecoratorManager;
93 import org.eclipse.ui.IEditorPart;
94 import org.eclipse.ui.IEditorRegistry;
95 import org.eclipse.ui.IElementFactory;
96 import org.eclipse.ui.ILocalWorkingSetManager;
97 import org.eclipse.ui.IMemento;
98 import org.eclipse.ui.IPerspectiveDescriptor;
99 import org.eclipse.ui.IPerspectiveRegistry;
100 import org.eclipse.ui.ISaveableFilter;
101 import org.eclipse.ui.ISaveablePart;
102 import org.eclipse.ui.ISaveablesLifecycleListener;
103 import org.eclipse.ui.ISharedImages;
104 import org.eclipse.ui.IWindowListener;
105 import org.eclipse.ui.IWorkbench;
106 import org.eclipse.ui.IWorkbenchListener;
107 import org.eclipse.ui.IWorkbenchPage;
108 import org.eclipse.ui.IWorkbenchPart;
109 import org.eclipse.ui.IWorkbenchPreferenceConstants;
110 import org.eclipse.ui.IWorkbenchWindow;
111 import org.eclipse.ui.IWorkingSetManager;
112 import org.eclipse.ui.PlatformUI;
113 import org.eclipse.ui.Saveable;
114 import org.eclipse.ui.WorkbenchException;
115 import org.eclipse.ui.XMLMemento;
116 import org.eclipse.ui.activities.IWorkbenchActivitySupport;
117 import org.eclipse.ui.application.IWorkbenchConfigurer;
118 import org.eclipse.ui.application.WorkbenchAdvisor;
119 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
120 import org.eclipse.ui.commands.ICommandService;
121 import org.eclipse.ui.commands.IWorkbenchCommandSupport;
122 import org.eclipse.ui.contexts.IContextService;
123 import org.eclipse.ui.contexts.IWorkbenchContextSupport;
124 import org.eclipse.ui.handlers.IHandlerService;
125 import org.eclipse.ui.help.IWorkbenchHelpSystem;
126 import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
127 import org.eclipse.ui.internal.activities.ws.WorkbenchActivitySupport;
128 import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport;
129 import org.eclipse.ui.internal.commands.CommandImageManager;
130 import org.eclipse.ui.internal.commands.CommandImageService;
131 import org.eclipse.ui.internal.commands.CommandService;
132 import org.eclipse.ui.internal.commands.ICommandImageService;
133 import org.eclipse.ui.internal.commands.WorkbenchCommandSupport;
134 import org.eclipse.ui.internal.contexts.ActiveContextSourceProvider;
135 import org.eclipse.ui.internal.contexts.ContextService;
136 import org.eclipse.ui.internal.contexts.WorkbenchContextSupport;
137 import org.eclipse.ui.internal.dialogs.PropertyPageContributorManager;
138 import org.eclipse.ui.internal.handlers.HandlerService;
139 import org.eclipse.ui.internal.help.WorkbenchHelpSystem;
140 import org.eclipse.ui.internal.intro.IIntroRegistry;
141 import org.eclipse.ui.internal.intro.IntroDescriptor;
142 import org.eclipse.ui.internal.keys.BindingService;
143 import org.eclipse.ui.internal.menus.FocusControlSourceProvider;
144 import org.eclipse.ui.internal.menus.WorkbenchMenuService;
145 import org.eclipse.ui.internal.misc.Policy;
146 import org.eclipse.ui.internal.misc.StatusUtil;
147 import org.eclipse.ui.internal.misc.UIStats;
148 import org.eclipse.ui.internal.progress.ProgressManager;
149 import org.eclipse.ui.internal.registry.IActionSetDescriptor;
150 import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
151 import org.eclipse.ui.internal.registry.UIExtensionTracker;
152 import org.eclipse.ui.internal.services.ActionSetSourceProvider;
153 import org.eclipse.ui.internal.services.ActivePartSourceProvider;
154 import org.eclipse.ui.internal.services.ActiveShellSourceProvider;
155 import org.eclipse.ui.internal.services.CurrentSelectionSourceProvider;
156 import org.eclipse.ui.internal.services.EvaluationService;
157 import org.eclipse.ui.internal.services.IEvaluationService;
158 import org.eclipse.ui.internal.services.ISourceProviderService;
159 import org.eclipse.ui.internal.services.MenuSourceProvider;
160 import org.eclipse.ui.internal.services.ServiceLocator;
161 import org.eclipse.ui.internal.services.SourceProviderService;
162 import org.eclipse.ui.internal.splash.EclipseSplashHandler;
163 import org.eclipse.ui.internal.splash.SplashHandlerFactory;
164 import org.eclipse.ui.internal.testing.WorkbenchTestable;
165 import org.eclipse.ui.internal.themes.ColorDefinition;
166 import org.eclipse.ui.internal.themes.FontDefinition;
167 import org.eclipse.ui.internal.themes.ThemeElementHelper;
168 import org.eclipse.ui.internal.themes.WorkbenchThemeManager;
169 import org.eclipse.ui.internal.tweaklets.GrabFocus;
170 import org.eclipse.ui.internal.tweaklets.Tweaklets;
171 import org.eclipse.ui.internal.util.PrefUtil;
172 import org.eclipse.ui.internal.util.Util;
173 import org.eclipse.ui.intro.IIntroManager;
174 import org.eclipse.ui.keys.IBindingService;
175 import org.eclipse.ui.menus.IMenuService;
176 import org.eclipse.ui.operations.IWorkbenchOperationSupport;
177 import org.eclipse.ui.progress.IProgressService;
178 import org.eclipse.ui.services.IDisposable;
179 import org.eclipse.ui.splash.AbstractSplashHandler;
180 import org.eclipse.ui.statushandlers.StatusManager;
181 import org.eclipse.ui.swt.IFocusService;
182 import org.eclipse.ui.themes.IThemeManager;
183 import org.eclipse.ui.views.IViewRegistry;
184 import org.eclipse.ui.wizards.IWizardRegistry;
185 import org.osgi.framework.BundleContext;
186 import org.osgi.framework.BundleEvent;
187 import org.osgi.framework.Constants;
188 import org.osgi.framework.ServiceRegistration;
189 import org.osgi.framework.SynchronousBundleListener;
190
191 /**
192  * The workbench class represents the top of the Eclipse user interface. Its
193  * primary responsability is the management of workbench windows, dialogs,
194  * wizards, and other workbench-related windows.
195  * <p>
196  * Note that any code that is run during the creation of a workbench instance
197  * should not required access to the display.
198  * </p>
199  * <p>
200  * Note that this internal class changed significantly between 2.1 and 3.0.
201  * Applications that used to define subclasses of this internal class need to be
202  * rewritten to use the new workbench advisor API.
203  * </p>
204  */

205 public final class Workbench extends EventManager implements IWorkbench {
206
207     private final class StartupProgressBundleListener implements
208             SynchronousBundleListener {
209
210         private final IProgressMonitor progressMonitor;
211
212         private final int maximumProgressCount;
213
214         // stack of names of bundles currently starting
215
private final List JavaDoc starting;
216
217         StartupProgressBundleListener(IProgressMonitor progressMonitor,
218                 int maximumProgressCount) {
219             super();
220             this.progressMonitor = progressMonitor;
221             this.maximumProgressCount = maximumProgressCount;
222             this.starting = new ArrayList JavaDoc();
223         }
224
225         public void bundleChanged(BundleEvent event) {
226             int eventType = event.getType();
227             String JavaDoc bundleName;
228
229             synchronized (this) {
230                 if (eventType == BundleEvent.STARTING) {
231                     starting.add(bundleName = event.getBundle()
232                             .getSymbolicName());
233                 } else if (eventType == BundleEvent.STARTED) {
234                     progressCount++;
235                     if (progressCount <= maximumProgressCount) {
236                         progressMonitor.worked(1);
237                     }
238                     int index = starting.lastIndexOf(event.getBundle()
239                             .getSymbolicName());
240                     if (index >= 0) {
241                         starting.remove(index);
242                     }
243                     if (index != starting.size()) {
244                         return; // not currently displayed
245
}
246                     bundleName = index == 0 ? null : (String JavaDoc) starting
247                             .get(index - 1);
248                 } else {
249                     return; // uninteresting event
250
}
251             }
252
253             String JavaDoc taskName;
254
255             if (bundleName == null) {
256                 taskName = WorkbenchMessages.Startup_Loading_Workbench;
257             } else {
258                 taskName = NLS.bind(WorkbenchMessages.Startup_Loading,
259                         bundleName);
260             }
261
262             progressMonitor.subTask(taskName);
263         }
264     }
265
266     /**
267      * Family for the early startup job.
268      */

269     public static final String JavaDoc EARLY_STARTUP_FAMILY = "earlyStartup"; //$NON-NLS-1$
270

271     static final String JavaDoc VERSION_STRING[] = { "0.046", "2.0" }; //$NON-NLS-1$ //$NON-NLS-2$
272

273     static final String JavaDoc DEFAULT_WORKBENCH_STATE_FILENAME = "workbench.xml"; //$NON-NLS-1$
274

275     /**
276      * Holds onto the only instance of Workbench.
277      */

278     private static Workbench instance;
279
280     /**
281      * The testable object facade.
282      *
283      * @since 3.0
284      */

285     private static WorkbenchTestable testableObject;
286
287     /**
288      * Signals that the workbench should create a splash implementation when
289      * instantiated. Intial value is <code>true</code>.
290      *
291      * @since 3.3
292      */

293     private static boolean createSplash = true;
294
295     /**
296      * The splash handler.
297      */

298     private static AbstractSplashHandler splash;
299
300     /**
301      * The display used for all UI interactions with this workbench.
302      *
303      * @since 3.0
304      */

305     private Display display;
306
307     private WindowManager windowManager;
308
309     private WorkbenchWindow activatedWindow;
310
311     private EditorHistory editorHistory;
312
313     private boolean runEventLoop = true;
314
315     private boolean isStarting = true;
316
317     private boolean isClosing = false;
318
319     /**
320      * PlatformUI return code (as opposed to IPlatformRunnable return code).
321      */

322     private int returnCode = PlatformUI.RETURN_UNSTARTABLE;
323
324     /**
325      * Advisor providing application-specific configuration and customization of
326      * the workbench.
327      *
328      * @since 3.0
329      */

330     private WorkbenchAdvisor advisor;
331
332     /**
333      * Object for configuring the workbench. Lazily initialized to an instance
334      * unique to the workbench instance.
335      *
336      * @since 3.0
337      */

338     private WorkbenchConfigurer workbenchConfigurer;
339
340     // for dynamic UI
341
/**
342      * ExtensionEventHandler handles extension life-cycle events.
343      */

344     private ExtensionEventHandler extensionEventHandler;
345
346     /**
347      * A count of how many large updates are going on. This tracks nesting of
348      * requests to disable services during a large update -- similar to the
349      * <code>setRedraw</code> functionality on <code>Control</code>. When
350      * this value becomes greater than zero, services are disabled. When this
351      * value becomes zero, services are enabled. Please see
352      * <code>largeUpdateStart()</code> and <code>largeUpdateEnd()</code>.
353      */

354     private int largeUpdates = 0;
355
356     /**
357      * The service locator maintained by the workbench. These services are
358      * initialized during workbench during the <code>init</code> method.
359      */

360     private final ServiceLocator serviceLocator = new ServiceLocator();
361
362     /**
363      * A count of how many plug-ins were loaded while restoring the workbench
364      * state. Initially -1 for unknown number.
365      */

366     private int progressCount = -1;
367
368     /**
369      * A field to hold the workbench windows that have been restored. In the
370      * event that not all windows have been restored, this field allows the
371      * openWindowsAfterRestore method to open some windows.
372      */

373     private WorkbenchWindow[] createdWindows;
374
375     /**
376      * Listener list for registered IWorkbenchListeners .
377      */

378     private ListenerList workbenchListeners = new ListenerList(
379             ListenerList.IDENTITY);
380
381     /**
382      * Creates a new workbench.
383      *
384      * @param display
385      * the display to be used for all UI interactions with the
386      * workbench
387      * @param advisor
388      * the application-specific advisor that configures and
389      * specializes this workbench instance
390      * @since 3.0
391      */

392     private Workbench(Display display, WorkbenchAdvisor advisor) {
393         super();
394         StartupThreading.setWorkbench(this);
395         if (instance != null && instance.isRunning()) {
396             throw new IllegalStateException JavaDoc(
397                     WorkbenchMessages.Workbench_CreatingWorkbenchTwice);
398         }
399         Assert.isNotNull(display);
400         Assert.isNotNull(advisor);
401         this.advisor = advisor;
402         this.display = display;
403         Workbench.instance = this;
404
405         // for dynamic UI [This seems to be for everything that isn't handled by
406
// some
407
// subclass of RegistryManager. I think that when an extension is moved
408
// to the
409
// RegistryManager implementation, then it should be removed from the
410
// list in
411
// ExtensionEventHandler#appear.
412
// I've found that the new wizard extension in particular is a poor
413
// choice to
414
// use as an example, since the result of reading the registry is not
415
// cached
416
// -- so it is re-read each time. The only real contribution of this
417
// dialog is
418
// to show the user a nice dialog describing the addition.]
419
extensionEventHandler = new ExtensionEventHandler(this);
420         Platform.getExtensionRegistry().addRegistryChangeListener(
421                 extensionEventHandler);
422     }
423
424     /**
425      * Returns the one and only instance of the workbench, if there is one.
426      *
427      * @return the workbench, or <code>null</code> if the workbench has not
428      * been created, or has been created and already completed
429      */

430     public static final Workbench getInstance() {
431         return instance;
432     }
433
434     /**
435      * Creates the workbench and associates it with the the given display and
436      * workbench advisor, and runs the workbench UI. This entails processing and
437      * dispatching events until the workbench is closed or restarted.
438      * <p>
439      * This method is intended to be called by <code>PlatformUI</code>. Fails
440      * if the workbench UI has already been created.
441      * </p>
442      * <p>
443      * The display passed in must be the default display.
444      * </p>
445      *
446      * @param display
447      * the display to be used for all UI interactions with the
448      * workbench
449      * @param advisor
450      * the application-specific advisor that configures and
451      * specializes the workbench
452      * @return return code {@link PlatformUI#RETURN_OK RETURN_OK}for normal
453      * exit; {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
454      * workbench was terminated with a call to
455      * {@link IWorkbench#restart IWorkbench.restart}; other values
456      * reserved for future use
457      */

458     public static final int createAndRunWorkbench(final Display display,
459             final WorkbenchAdvisor advisor) {
460         final int[] returnCode = new int[1];
461         Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable JavaDoc() {
462             public void run() {
463                 // create the workbench instance
464
Workbench workbench = new Workbench(display, advisor);
465                 // run the workbench event loop
466
returnCode[0] = workbench.runUI();
467             }
468         });
469         return returnCode[0];
470     }
471
472     /**
473      * Creates the <code>Display</code> to be used by the workbench.
474      *
475      * @return the display
476      */

477     public static Display createDisplay() {
478         // setup the application name used by SWT to lookup resources on some
479
// platforms
480
String JavaDoc applicationName = WorkbenchPlugin.getDefault().getAppName();
481         if (applicationName != null) {
482             Display.setAppName(applicationName);
483         }
484
485         // create the display
486
Display newDisplay = Display.getCurrent();
487         if(newDisplay == null) {
488             if (Policy.DEBUG_SWT_GRAPHICS || Policy.DEBUG_SWT_DEBUG) {
489                 DeviceData data = new DeviceData();
490                 if (Policy.DEBUG_SWT_GRAPHICS) {
491                     data.tracking = true;
492                 }
493                 if (Policy.DEBUG_SWT_DEBUG) {
494                     data.debug = true;
495                 }
496                 newDisplay = new Display(data);
497             } else {
498                 newDisplay = new Display();
499             }
500         }
501
502         // workaround for 1GEZ9UR and 1GF07HN
503
newDisplay.setWarnings(false);
504
505         // Set the priority higher than normal so as to be higher
506
// than the JobManager.
507
Thread.currentThread().setPriority(
508                 Math.min(Thread.MAX_PRIORITY, Thread.NORM_PRIORITY + 1));
509
510         initializeImages();
511
512         return newDisplay;
513     }
514
515     /**
516      * Create the splash wrapper and set it to work.
517      *
518      * @since 3.3
519      */

520     private void createSplashWrapper() {
521         final Display display = getDisplay();
522         String JavaDoc splashLoc = System.getProperty("org.eclipse.equinox.launcher.splash.location"); //$NON-NLS-1$
523
final Image background = loadImage(splashLoc);
524         
525         SafeRunnable run = new SafeRunnable() {
526
527             public void run() throws Exception JavaDoc {
528                 String JavaDoc splashHandle = System.getProperty("org.eclipse.equinox.launcher.splash.handle"); //$NON-NLS-1$
529
if (splashHandle == null) {
530                     createSplash = false;
531                     return;
532                 }
533                 
534                 // create the splash
535
getSplash();
536                 if (splash == null) {
537                     createSplash = false;
538                     return;
539                 }
540                 
541                 Shell splashShell = splash.getSplash();
542                 if (splashShell == null) {
543                     // look for the 32 bit internal_new shell method
544
try {
545                         Method JavaDoc method = Shell.class
546                                 .getMethod(
547                                         "internal_new", new Class JavaDoc[] { Display.class, int.class }); //$NON-NLS-1$
548
// we're on a 32 bit platform so invoke it with splash
549
// handle as an int
550
splashShell = (Shell) method.invoke(null, new Object JavaDoc[] {
551                                 display, new Integer JavaDoc(splashHandle) });
552                     } catch (NoSuchMethodException JavaDoc e) {
553                         // look for the 64 bit internal_new shell method
554
try {
555                             Method JavaDoc method = Shell.class
556                                     .getMethod(
557                                             "internal_new", new Class JavaDoc[] { Display.class, long.class }); //$NON-NLS-1$
558

559                             // we're on a 64 bit platform so invoke it with a long
560
splashShell = (Shell) method.invoke(null,
561                                     new Object JavaDoc[] { display,
562                                             new Long JavaDoc(splashHandle) });
563                         } catch (NoSuchMethodException JavaDoc e2) {
564                             // cant find either method - don't do anything.
565
}
566                     }
567                     
568                     if (splashShell == null)
569                         return;
570                     if (background != null)
571                         splashShell.setBackgroundImage(background);
572                 }
573
574                 Dictionary JavaDoc properties = new Hashtable JavaDoc();
575                 properties.put(Constants.SERVICE_RANKING, new Integer JavaDoc(Integer.MAX_VALUE));
576                 BundleContext context = WorkbenchPlugin.getDefault().getBundleContext();
577                 final ServiceRegistration registration[] = new ServiceRegistration[1];
578                 StartupMonitor startupMonitor = new StartupMonitor() {
579
580                     public void applicationRunning() {
581                         splash.dispose();
582                         if (background != null)
583                             background.dispose();
584                         registration[0].unregister(); // unregister ourself
585
}
586
587                     public void update() {
588                         // do nothing - we come into the picture far too late
589
// for this to be relevant
590
}
591                 };
592                 registration[0] = context.registerService(StartupMonitor.class
593                         .getName(), startupMonitor, properties);
594                 
595                 splash.init(splashShell);
596             }
597             /* (non-Javadoc)
598              * @see org.eclipse.jface.util.SafeRunnable#handleException(java.lang.Throwable)
599              */

600             public void handleException(Throwable JavaDoc e) {
601                 StatusManager.getManager().handle(
602                         StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH,
603                                 "Could not instantiate splash", e)); //$NON-NLS-1$
604
createSplash = false;
605                 splash = null;
606                 if (background != null)
607                     background.dispose();
608                 
609             }
610             };
611             SafeRunner.run(run);
612     }
613
614     /**
615      * Load an image from a filesystem path.
616      *
617      * @param splashLoc the location to load from
618      * @return the image or <code>null</code>
619      * @since 3.3
620      */

621     private Image loadImage(String JavaDoc splashLoc) {
622         Image background = null;
623         if (splashLoc != null) {
624             try {
625                 InputStream JavaDoc input = new BufferedInputStream JavaDoc(
626                         new FileInputStream JavaDoc(splashLoc));
627                 background = new Image(display, input);
628             } catch (IOException JavaDoc e) {
629                 StatusManager.getManager().handle(
630                         StatusUtil.newStatus(WorkbenchPlugin.PI_WORKBENCH, e));
631             }
632         }
633         return background;
634     }
635
636     /**
637      * Return the splash handler for this application. If none is specifically
638      * provided the default Eclipse implementation is returned.
639      *
640      * @return the splash handler for this application or <code>null</code>
641      * @since 3.3
642      */

643     private static AbstractSplashHandler getSplash() {
644         if (!createSplash)
645             return null;
646         
647         if (splash == null) {
648             
649             IProduct product = Platform.getProduct();
650             if (product != null)
651                 splash = SplashHandlerFactory.findSplashHandlerFor(product);
652             
653             if (splash == null)
654                 splash = new EclipseSplashHandler();
655         }
656         return splash;
657     }
658
659     /**
660      * Returns the testable object facade, for use by the test harness.
661      *
662      * @return the testable object facade
663      * @since 3.0
664      */

665     public static WorkbenchTestable getWorkbenchTestable() {
666         if (testableObject == null) {
667             testableObject = new WorkbenchTestable();
668         }
669         return testableObject;
670     }
671
672     /*
673      * (non-Javadoc) Method declared on IWorkbench.
674      *
675      * @since 3.2
676      */

677     public void addWorkbenchListener(IWorkbenchListener listener) {
678         workbenchListeners.add(listener);
679     }
680
681     /*
682      * (non-Javadoc) Method declared on IWorkbench.
683      *
684      * @since 3.2
685      */

686     public void removeWorkbenchListener(IWorkbenchListener listener) {
687         workbenchListeners.remove(listener);
688     }
689
690     /**
691      * Fire workbench preShutdown event, stopping at the first one to veto
692      *
693      * @param forced
694      * flag indicating whether the shutdown is being forced
695      * @return <code>true</code> to allow the workbench to proceed with
696      * shutdown, <code>false</code> to veto a non-forced shutdown
697      * @since 3.2
698      */

699     boolean firePreShutdown(final boolean forced) {
700         Object JavaDoc list[] = workbenchListeners.getListeners();
701         for (int i = 0; i < list.length; i++) {
702             final IWorkbenchListener l = (IWorkbenchListener) list[i];
703             final boolean[] result = new boolean[] { false };
704             SafeRunnable.run(new SafeRunnable() {
705                 public void run() {
706                     result[0] = l.preShutdown(Workbench.this, forced);
707                 }
708             });
709             if (!result[0]) {
710                 return false;
711             }
712         }
713         return true;
714     }
715
716     /**
717      * Fire workbench postShutdown event.
718      *
719      * @since 3.2
720      */

721     void firePostShutdown() {
722         Object JavaDoc list[] = workbenchListeners.getListeners();
723         for (int i = 0; i < list.length; i++) {
724             final IWorkbenchListener l = (IWorkbenchListener) list[i];
725             SafeRunnable.run(new SafeRunnable() {
726                 public void run() {
727                     l.postShutdown(Workbench.this);
728                 }
729             });
730         }
731     }
732
733     /*
734      * (non-Javadoc) Method declared on IWorkbench.
735      */

736     public void addWindowListener(IWindowListener l) {
737         addListenerObject(l);
738     }
739
740     /*
741      * (non-Javadoc) Method declared on IWorkbench.
742      */

743     public void removeWindowListener(IWindowListener l) {
744         removeListenerObject(l);
745     }
746
747     /**
748      * Fire window opened event.
749      *
750      * @param window
751      * The window which just opened; should not be <code>null</code>.
752      */

753     protected void fireWindowOpened(final IWorkbenchWindow window) {
754         Object JavaDoc list[] = getListeners();
755         for (int i = 0; i < list.length; i++) {
756             final IWindowListener l = (IWindowListener) list[i];
757             SafeRunner.run(new SafeRunnable() {
758                 public void run() {
759                     l.windowOpened(window);
760                 }
761             });
762         }
763     }
764
765     /**
766      * Fire window closed event.
767      *
768      * @param window
769      * The window which just closed; should not be <code>null</code>.
770      */

771     protected void fireWindowClosed(final IWorkbenchWindow window) {
772         if (activatedWindow == window) {
773             // Do not hang onto it so it can be GC'ed
774
activatedWindow = null;
775         }
776
777         Object JavaDoc list[] = getListeners();
778         for (int i = 0; i < list.length; i++) {
779             final IWindowListener l = (IWindowListener) list[i];
780             SafeRunner.run(new SafeRunnable() {
781                 public void run() {
782                     l.windowClosed(window);
783                 }
784             });
785         }
786     }
787
788     /**
789      * Fire window activated event.
790      *
791      * @param window
792      * The window which was just activated; should not be
793      * <code>null</code>.
794      */

795     protected void fireWindowActivated(final IWorkbenchWindow window) {
796         Object JavaDoc list[] = getListeners();
797         for (int i = 0; i < list.length; i++) {
798             final IWindowListener l = (IWindowListener) list[i];
799             SafeRunner.run(new SafeRunnable() {
800                 public void run() {
801                     l.windowActivated(window);
802                 }
803             });
804         }
805     }
806
807     /**
808      * Fire window deactivated event.
809      *
810      * @param window
811      * The window which was just deactivated; should not be
812      * <code>null</code>.
813      */

814     protected void fireWindowDeactivated(final IWorkbenchWindow window) {
815         Object JavaDoc list[] = getListeners();
816         for (int i = 0; i < list.length; i++) {
817             final IWindowListener l = (IWindowListener) list[i];
818             SafeRunner.run(new SafeRunnable() {
819                 public void run() {
820                     l.windowDeactivated(window);
821                 }
822             });
823         }
824     }
825
826     /**
827      * Closes the workbench. Assumes that the busy cursor is active.
828      *
829      * @param force
830      * true if the close is mandatory, and false if the close is
831      * allowed to fail
832      * @return true if the close succeeded, and false otherwise
833      */

834     private boolean busyClose(final boolean force) {
835
836         // notify the advisor of preShutdown and allow it to veto if not forced
837
isClosing = advisor.preShutdown();
838         if (!force && !isClosing) {
839             return false;
840         }
841
842         // notify regular workbench clients of preShutdown and allow them to
843
// veto if not forced
844
isClosing = firePreShutdown(force);
845         if (!force && !isClosing) {
846             return false;
847         }
848
849         // save any open editors if they are dirty
850
isClosing = saveAllEditors(!force);
851         if (!force && !isClosing) {
852             return false;
853         }
854
855         boolean closeEditors = !force
856                 && PrefUtil.getAPIPreferenceStore().getBoolean(
857                         IWorkbenchPreferenceConstants.CLOSE_EDITORS_ON_EXIT);
858         if (closeEditors) {
859             SafeRunner.run(new SafeRunnable() {
860                 public void run() {
861                     IWorkbenchWindow windows[] = getWorkbenchWindows();
862                     for (int i = 0; i < windows.length; i++) {
863                         IWorkbenchPage pages[] = windows[i].getPages();
864                         for (int j = 0; j < pages.length; j++) {
865                             isClosing = isClosing
866                                     && pages[j].closeAllEditors(false);
867                         }
868                     }
869                 }
870             });
871             if (!force && !isClosing) {
872                 return false;
873             }
874         }
875
876         if (getWorkbenchConfigurer().getSaveAndRestore()) {
877             SafeRunner.run(new SafeRunnable() {
878                 public void run() {
879                     XMLMemento mem = recordWorkbenchState();
880                     // Save the IMemento to a file.
881
saveMementoToFile(mem);
882                 }
883
884                 public void handleException(Throwable JavaDoc e) {
885                     String JavaDoc message;
886                     if (e.getMessage() == null) {
887                         message = WorkbenchMessages.ErrorClosingNoArg;
888                     } else {
889                         message = NLS.bind(
890                                 WorkbenchMessages.ErrorClosingOneArg, e
891                                         .getMessage());
892                     }
893
894                     if (!MessageDialog.openQuestion(null,
895                             WorkbenchMessages.Error, message)) {
896                         isClosing = false;
897                     }
898                 }
899             });
900         }
901         if (!force && !isClosing) {
902             return false;
903         }
904
905         SafeRunner.run(new SafeRunnable(WorkbenchMessages.ErrorClosing) {
906             public void run() {
907                 if (isClosing || force) {
908                     isClosing = windowManager.close();
909                 }
910             }
911         });
912
913         if (!force && !isClosing) {
914             return false;
915         }
916
917         shutdown();
918
919         runEventLoop = false;
920         return true;
921     }
922
923     
924     /* (non-Javadoc)
925      * @see org.eclipse.ui.IWorkbench#saveAllEditors(boolean)
926      */

927     public boolean saveAllEditors(boolean confirm) {
928         final boolean finalConfirm = confirm;
929         final boolean[] result = new boolean[1];
930         result[0] = true;
931
932         SafeRunner.run(new SafeRunnable(WorkbenchMessages.ErrorClosing) {
933             public void run() {
934                 // Collect dirtyParts
935
ArrayList JavaDoc dirtyParts = new ArrayList JavaDoc();
936                 ArrayList JavaDoc dirtyEditorsInput = new ArrayList JavaDoc();
937                 IWorkbenchWindow windows[] = getWorkbenchWindows();
938                 for (int i = 0; i < windows.length; i++) {
939                     IWorkbenchPage pages[] = windows[i].getPages();
940                     for (int j = 0; j < pages.length; j++) {
941                         WorkbenchPage page = (WorkbenchPage) pages[j];
942
943                         ISaveablePart[] parts = page.getDirtyParts();
944
945                         for (int k = 0; k < parts.length; k++) {
946                             ISaveablePart part = parts[k];
947
948                             if (part.isSaveOnCloseNeeded()) {
949                                 if (part instanceof IEditorPart) {
950                                     IEditorPart editor = (IEditorPart) part;
951                                     if (!dirtyEditorsInput.contains(editor
952                                             .getEditorInput())) {
953                                         dirtyParts.add(editor);
954                                         dirtyEditorsInput.add(editor
955                                                 .getEditorInput());
956                                     }
957                                 } else {
958                                     dirtyParts.add(part);
959                                 }
960                             }
961                         }
962                     }
963                 }
964                 IShellProvider shellProvider;
965                 IRunnableContext runnableContext;
966                 IWorkbenchWindow w = getActiveWorkbenchWindow();
967                 if (w == null && windows.length > 0) {
968                     w = windows[0];
969                 }
970                 if (w != null) {
971                     shellProvider = (WorkbenchWindow)w;
972                     runnableContext = w;
973                 } else {
974                     shellProvider = new IShellProvider() {
975                         public Shell getShell() {
976                             return null;
977                         }
978                     };
979                     runnableContext = new ProgressMonitorDialog(null);
980                 }
981                 // The fourth parameter is true to also save saveables from
982
// non-part sources, see bug 139004.
983
result[0] = EditorManager.saveAll(dirtyParts, finalConfirm,
984                         false, true, runnableContext, shellProvider);
985             }
986         });
987         return result[0];
988     }
989
990     /**
991      * Opens a new workbench window and page with a specific perspective.
992      *
993      * Assumes that busy cursor is active.
994      */

995     private IWorkbenchWindow busyOpenWorkbenchWindow(final String JavaDoc perspID,
996             final IAdaptable input) throws WorkbenchException {
997         // Create a workbench window (becomes active window)
998
final WorkbenchWindow newWindowArray[] = new WorkbenchWindow[1];
999         StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {
1000            public void runWithException() {
1001                newWindowArray[0] = newWorkbenchWindow();
1002            }
1003        });
1004
1005        final WorkbenchWindow newWindow = newWindowArray[0];
1006        
1007        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1008
1009            public void runWithException() {
1010                newWindow.create(); // must be created before adding to window
1011
// manager
1012
}
1013        });
1014        windowManager.add(newWindow);
1015
1016        final WorkbenchException [] exceptions = new WorkbenchException[1];
1017        // Create the initial page.
1018
if (perspID != null) {
1019            StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {
1020
1021                public void runWithException() throws WorkbenchException {
1022                    try {
1023                        newWindow.busyOpenPage(perspID, input);
1024                    } catch (WorkbenchException e) {
1025                        windowManager.remove(newWindow);
1026                        exceptions[0] = e;
1027                    }
1028                }});
1029        }
1030        if (exceptions[0] != null)
1031            throw exceptions[0];
1032
1033        // Open window after opening page, to avoid flicker.
1034
StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {
1035
1036            public void runWithException() {
1037                newWindow.open();
1038            }
1039        });
1040
1041        return newWindow;
1042    }
1043
1044    /*
1045     * (non-Javadoc) Method declared on IWorkbench.
1046     */

1047    public boolean close() {
1048        return close(PlatformUI.RETURN_OK, false);
1049    }
1050
1051    /**
1052     * Closes the workbench, returning the given return code from the run
1053     * method. If forced, the workbench is closed no matter what.
1054     *
1055     * @param returnCode
1056     * {@link PlatformUI#RETURN_OK RETURN_OK}for normal exit;
1057     * {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
1058     * workbench was terminated with a call to
1059     * {@link IWorkbench#restart IWorkbench.restart};
1060     * {@link PlatformUI#RETURN_EMERGENCY_CLOSE} for an emergency
1061     * shutdown
1062     * {@link PlatformUI#RETURN_UNSTARTABLE RETURN_UNSTARTABLE}if
1063     * the workbench could not be started; other values reserved for
1064     * future use
1065     *
1066     * @param force
1067     * true to force the workbench close, and false for a "soft"
1068     * close that can be canceled
1069     * @return true if the close was successful, and false if the close was
1070     * canceled
1071     */

1072    /* package */
1073    boolean close(int returnCode, final boolean force) {
1074        this.returnCode = returnCode;
1075        final boolean[] ret = new boolean[1];
1076        BusyIndicator.showWhile(null, new Runnable JavaDoc() {
1077            public void run() {
1078                ret[0] = busyClose(force);
1079            }
1080        });
1081        return ret[0];
1082    }
1083
1084    /*
1085     * (non-Javadoc) Method declared on IWorkbench.
1086     */

1087    public IWorkbenchWindow getActiveWorkbenchWindow() {
1088        // Return null if called from a non-UI thread.
1089
// This is not spec'ed behaviour and is misleading, however this is how
1090
// it
1091
// worked in 2.1 and we cannot change it now.
1092
// For more details, see [Bug 57384] [RCP] Main window not active on
1093
// startup
1094
if (Display.getCurrent() == null) {
1095            return null;
1096        }
1097
1098        // Look at the current shell and up its parent
1099
// hierarchy for a workbench window.
1100
Control shell = display.getActiveShell();
1101        while (shell != null) {
1102            Object JavaDoc data = shell.getData();
1103            if (data instanceof IWorkbenchWindow) {
1104                return (IWorkbenchWindow) data;
1105            }
1106            shell = shell.getParent();
1107        }
1108
1109        // Look for the window that was last known being
1110
// the active one
1111
WorkbenchWindow win = getActivatedWindow();
1112        if (win != null) {
1113            return win;
1114        }
1115
1116        // Look at all the shells and pick the first one
1117
// that is a workbench window.
1118
Shell shells[] = display.getShells();
1119        for (int i = 0; i < shells.length; i++) {
1120            Object JavaDoc data = shells[i].getData();
1121            if (data instanceof IWorkbenchWindow) {
1122                return (IWorkbenchWindow) data;
1123            }
1124        }
1125
1126        // Can't find anything!
1127
return null;
1128    }
1129
1130    /*
1131     * Returns the editor history.
1132     */

1133    public EditorHistory getEditorHistory() {
1134        if (editorHistory == null) {
1135            editorHistory = new EditorHistory();
1136        }
1137        return editorHistory;
1138    }
1139
1140    /*
1141     * (non-Javadoc) Method declared on IWorkbench.
1142     */

1143    public IEditorRegistry getEditorRegistry() {
1144        return WorkbenchPlugin.getDefault().getEditorRegistry();
1145    }
1146
1147    /*
1148     * Returns the number for a new window. This will be the first number > 0
1149     * which is not used to identify another window in the workbench.
1150     */

1151    private int getNewWindowNumber() {
1152        // Get window list.
1153
Window[] windows = windowManager.getWindows();
1154        int count = windows.length;
1155
1156        // Create an array of booleans (size = window count).
1157
// Cross off every number found in the window list.
1158
boolean checkArray[] = new boolean[count];
1159        for (int nX = 0; nX < count; nX++) {
1160            if (windows[nX] instanceof WorkbenchWindow) {
1161                WorkbenchWindow ww = (WorkbenchWindow) windows[nX];
1162                int index = ww.getNumber() - 1;
1163                if (index >= 0 && index < count) {
1164                    checkArray[index] = true;
1165                }
1166            }
1167        }
1168
1169        // Return first index which is not used.
1170
// If no empty index was found then every slot is full.
1171
// Return next index.
1172
for (int index = 0; index < count; index++) {
1173            if (!checkArray[index]) {
1174                return index + 1;
1175            }
1176        }
1177        return count + 1;
1178    }
1179
1180    /*
1181     * (non-Javadoc) Method declared on IWorkbench.
1182     */

1183    public IWorkbenchOperationSupport getOperationSupport() {
1184        return WorkbenchPlugin.getDefault().getOperationSupport();
1185    }
1186
1187    /*
1188     * (non-Javadoc) Method declared on IWorkbench.
1189     */

1190    public IPerspectiveRegistry getPerspectiveRegistry() {
1191        return WorkbenchPlugin.getDefault().getPerspectiveRegistry();
1192    }
1193
1194    /*
1195     * (non-Javadoc) Method declared on IWorkbench.
1196     */

1197    public PreferenceManager getPreferenceManager() {
1198        return WorkbenchPlugin.getDefault().getPreferenceManager();
1199    }
1200
1201    /*
1202     * (non-Javadoc) Method declared on IWorkbench.
1203     */

1204    public IPreferenceStore getPreferenceStore() {
1205        return WorkbenchPlugin.getDefault().getPreferenceStore();
1206    }
1207
1208    /*
1209     * (non-Javadoc) Method declared on IWorkbench.
1210     */

1211    public ISharedImages getSharedImages() {
1212        return WorkbenchPlugin.getDefault().getSharedImages();
1213    }
1214
1215    /**
1216     * Returns the window manager for this workbench.
1217     *
1218     * @return the window manager
1219     */

1220    /* package */
1221    WindowManager getWindowManager() {
1222        return windowManager;
1223    }
1224
1225    /*
1226     * Answer the workbench state file.
1227     */

1228    private File JavaDoc getWorkbenchStateFile() {
1229        IPath path = WorkbenchPlugin.getDefault().getDataLocation();
1230        if (path == null) {
1231            return null;
1232        }
1233        path = path.append(DEFAULT_WORKBENCH_STATE_FILENAME);
1234        return path.toFile();
1235    }
1236
1237    /*
1238     * (non-Javadoc) Method declared on IWorkbench.
1239     */

1240    public int getWorkbenchWindowCount() {
1241        return windowManager.getWindowCount();
1242    }
1243
1244    /*
1245     * (non-Javadoc) Method declared on IWorkbench.
1246     */

1247    public IWorkbenchWindow[] getWorkbenchWindows() {
1248        Window[] windows = windowManager.getWindows();
1249        IWorkbenchWindow[] dwindows = new IWorkbenchWindow[windows.length];
1250        System.arraycopy(windows, 0, dwindows, 0, windows.length);
1251        return dwindows;
1252    }
1253
1254    /*
1255     * (non-Javadoc) Method declared on IWorkbench.
1256     */

1257    public IWorkingSetManager getWorkingSetManager() {
1258        return WorkbenchPlugin.getDefault().getWorkingSetManager();
1259    }
1260
1261    /**
1262     * {@inheritDoc}
1263     */

1264    public ILocalWorkingSetManager createLocalWorkingSetManager() {
1265        return new LocalWorkingSetManager(WorkbenchPlugin.getDefault()
1266                .getBundleContext());
1267    }
1268
1269    /**
1270     * Initializes the workbench now that the display is created.
1271     *
1272     * @return true if init succeeded.
1273     */

1274    private boolean init() {
1275        // setup debug mode if required.
1276
if (WorkbenchPlugin.getDefault().isDebugging()) {
1277            WorkbenchPlugin.DEBUG = true;
1278            ModalContext.setDebugMode(true);
1279        }
1280
1281        // Set up the JFace preference store
1282
JFaceUtil.initializeJFacePreferences();
1283
1284        // create workbench window manager
1285
windowManager = new WindowManager();
1286
1287        IIntroRegistry introRegistry = WorkbenchPlugin.getDefault()
1288                .getIntroRegistry();
1289        if (introRegistry.getIntroCount() > 0) {
1290            IProduct product = Platform.getProduct();
1291            if (product != null) {
1292                introDescriptor = (IntroDescriptor) introRegistry
1293                        .getIntroForProduct(product.getId());
1294            }
1295        }
1296
1297        // Initialize the activity support.
1298
workbenchActivitySupport = new WorkbenchActivitySupport();
1299        activityHelper = ActivityPersistanceHelper.getInstance();
1300
1301        initializeDefaultServices();
1302        initializeFonts();
1303        initializeColors();
1304        initializeApplicationColors();
1305
1306        // now that the workbench is sufficiently initialized, let the advisor
1307
// have a turn.
1308
StartupThreading.runWithoutExceptions(new StartupRunnable() {
1309
1310            public void runWithException() {
1311                advisor.internalBasicInitialize(getWorkbenchConfigurer());
1312            }
1313        });
1314        
1315        // configure use of color icons in toolbars
1316
boolean useColorIcons = PrefUtil.getInternalPreferenceStore()
1317                .getBoolean(IPreferenceConstants.COLOR_ICONS);
1318        ActionContributionItem.setUseColorIconsInToolbars(useColorIcons);
1319
1320        // initialize workbench single-click vs double-click behavior
1321
initializeSingleClickOption();
1322        
1323        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1324
1325            public void runWithException() {
1326                ((GrabFocus) Tweaklets.get(GrabFocus.KEY))
1327                        .init(getDisplay());
1328            }
1329        });
1330        
1331
1332        // attempt to restore a previous workbench state
1333
try {
1334            UIStats.start(UIStats.RESTORE_WORKBENCH, "Workbench"); //$NON-NLS-1$
1335

1336            final boolean bail [] = new boolean[1];
1337            StartupThreading.runWithoutExceptions(new StartupRunnable() {
1338
1339                public void runWithException() throws Throwable JavaDoc {
1340                    advisor.preStartup();
1341                    
1342                    if (!advisor.openWindows()) {
1343                        bail[0] = true;
1344                    }
1345                }});
1346            
1347            if (bail[0])
1348                return false;
1349
1350        } finally {
1351            UIStats.end(UIStats.RESTORE_WORKBENCH, this, "Workbench"); //$NON-NLS-1$
1352
}
1353
1354        forceOpenPerspective();
1355
1356        return true;
1357    }
1358
1359    /**
1360     * Establishes the relationship between JFace actions and the command
1361     * manager.
1362     */

1363    private void initializeCommandResolver() {
1364        ExternalActionManager.getInstance().setCallback(
1365                new CommandCallback(bindingManager, commandManager,
1366                        new IActiveChecker() {
1367                            public final boolean isActive(final String JavaDoc commandId) {
1368                                return workbenchActivitySupport
1369                                        .getActivityManager().getIdentifier(
1370                                                commandId).isEnabled();
1371                            }
1372                        }));
1373    }
1374
1375    /**
1376     * Initialize colors defined by the new colorDefinitions extension point.
1377     * Note this will be rolled into initializeColors() at some point.
1378     *
1379     * @since 3.0
1380     */

1381    private void initializeApplicationColors() {
1382        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1383
1384            public void runWithException() {
1385                ColorDefinition[] colorDefinitions = WorkbenchPlugin
1386                        .getDefault().getThemeRegistry().getColors();
1387                ThemeElementHelper.populateRegistry(getThemeManager().getTheme(
1388                        IThemeManager.DEFAULT_THEME), colorDefinitions,
1389                        PrefUtil.getInternalPreferenceStore());
1390            }
1391        });
1392    }
1393
1394    private void initializeSingleClickOption() {
1395        IPreferenceStore store = WorkbenchPlugin.getDefault()
1396                .getPreferenceStore();
1397        boolean openOnSingleClick = store
1398                .getBoolean(IPreferenceConstants.OPEN_ON_SINGLE_CLICK);
1399        boolean selectOnHover = store
1400                .getBoolean(IPreferenceConstants.SELECT_ON_HOVER);
1401        boolean openAfterDelay = store
1402                .getBoolean(IPreferenceConstants.OPEN_AFTER_DELAY);
1403        int singleClickMethod = openOnSingleClick ? OpenStrategy.SINGLE_CLICK
1404                : OpenStrategy.DOUBLE_CLICK;
1405        if (openOnSingleClick) {
1406            if (selectOnHover) {
1407                singleClickMethod |= OpenStrategy.SELECT_ON_HOVER;
1408            }
1409            if (openAfterDelay) {
1410                singleClickMethod |= OpenStrategy.ARROW_KEYS_OPEN;
1411            }
1412        }
1413        OpenStrategy.setOpenMethod(singleClickMethod);
1414    }
1415
1416    /*
1417     * Initializes the workbench fonts with the stored values.
1418     */

1419    private void initializeFonts() {
1420        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1421
1422            public void runWithException() {
1423                FontDefinition[] fontDefinitions = WorkbenchPlugin.getDefault()
1424                        .getThemeRegistry().getFonts();
1425
1426                ThemeElementHelper.populateRegistry(getThemeManager()
1427                        .getCurrentTheme(), fontDefinitions, PrefUtil
1428                        .getInternalPreferenceStore());
1429            }
1430        });
1431    }
1432
1433    /*
1434     * Initialize the workbench images.
1435     *
1436     * @param windowImages An array of the descriptors of the images to be used
1437     * in the corner of each window, or <code>null</code> if none. It is
1438     * expected that the array will contain the same icon, rendered at different
1439     * sizes.
1440     *
1441     * @since 3.0
1442     */

1443    private static void initializeImages() {
1444        ImageDescriptor[] windowImages = WorkbenchPlugin.getDefault()
1445                .getWindowImages();
1446        if (windowImages == null) {
1447            return;
1448        }
1449
1450        Image[] images = new Image[windowImages.length];
1451        for (int i = 0; i < windowImages.length; ++i) {
1452            images[i] = windowImages[i].createImage();
1453        }
1454        Window.setDefaultImages(images);
1455    }
1456
1457    /*
1458     * Take the workbenches' images out of the shared registry.
1459     *
1460     * @since 3.0
1461     */

1462    private void uninitializeImages() {
1463        WorkbenchImages.dispose();
1464        Image[] images = Window.getDefaultImages();
1465        Window.setDefaultImage(null);
1466        for (int i = 0; i < images.length; i++) {
1467            images[i].dispose();
1468        }
1469    }
1470
1471    /*
1472     * Initialize the workbench colors.
1473     *
1474     * @since 3.0
1475     */

1476    private void initializeColors() {
1477        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1478            public void runWithException() {
1479                WorkbenchColors.startup();
1480            }});
1481    }
1482
1483    /*
1484     * (non-Javadoc) Method declared on IWorkbench.
1485     */

1486    public boolean isClosing() {
1487        return isClosing;
1488    }
1489
1490    /**
1491     * Initializes all of the default services for the workbench. For
1492     * initializing the command-based services, this also parses the registry
1493     * and hooks up all the required listeners.
1494     */

1495    private final void initializeDefaultServices() {
1496        
1497        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1498
1499            public void runWithException() {
1500                serviceLocator.registerService(IWorkbench.class,
1501                        Workbench.this);
1502            }
1503        });
1504        
1505        // TODO Correctly order service initialization
1506
// there needs to be some serious consideration given to
1507
// the services, and hooking them up in the correct order
1508
final EvaluationService evaluationService = new EvaluationService();
1509        
1510        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1511
1512            public void runWithException() {
1513                serviceLocator.registerService(IEvaluationService.class,
1514                        evaluationService);
1515            }
1516        });
1517        
1518        
1519
1520        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1521
1522            public void runWithException() {
1523                serviceLocator.registerService(ISaveablesLifecycleListener.class,
1524                        new SaveablesList());
1525            }});
1526        
1527        /*
1528         * Phase 1 of the initialization of commands. When this phase completes,
1529         * all the services and managers will exist, and be accessible via the
1530         * getService(Object) method.
1531         */

1532        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1533
1534            public void runWithException() {
1535                Command.DEBUG_COMMAND_EXECUTION = Policy.DEBUG_COMMANDS;
1536                commandManager = new CommandManager();
1537            }});
1538        
1539        final CommandService [] commandService = new CommandService[1];
1540        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1541
1542            public void runWithException() {
1543                commandService[0] = new CommandService(commandManager);
1544                commandService[0].readRegistry();
1545                serviceLocator.registerService(ICommandService.class, commandService[0]);
1546
1547            }});
1548        
1549        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1550
1551            public void runWithException() {
1552                ContextManager.DEBUG = Policy.DEBUG_CONTEXTS;
1553                contextManager = new ContextManager();
1554                }});
1555        
1556        final IContextService contextService = new ContextService(
1557                contextManager);
1558        
1559        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1560
1561            public void runWithException() {
1562                contextService.readRegistry();
1563                }});
1564        
1565        serviceLocator.registerService(IContextService.class, contextService);
1566    
1567        
1568        final IHandlerService [] handlerService = new IHandlerService[1];
1569    
1570        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1571
1572            public void runWithException() {
1573                handlerService[0] = new HandlerService(
1574                        commandService[0], evaluationService);
1575                handlerService[0].readRegistry();
1576            }});
1577        
1578        serviceLocator.registerService(IHandlerService.class, handlerService[0]);
1579
1580        final IBindingService [] bindingService = new BindingService[1];
1581        
1582        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1583
1584            public void runWithException() {
1585                BindingManager.DEBUG = Policy.DEBUG_KEY_BINDINGS;
1586                bindingManager = new BindingManager(contextManager, commandManager);
1587                bindingService[0] = new BindingService(
1588                        bindingManager, commandService[0], Workbench.this);
1589                
1590            }});
1591        
1592        bindingService[0].readRegistryAndPreferences(commandService[0]);
1593        serviceLocator.registerService(IBindingService.class, bindingService[0]);
1594
1595        final CommandImageManager commandImageManager = new CommandImageManager();
1596        final CommandImageService commandImageService = new CommandImageService(
1597                commandImageManager, commandService[0]);
1598        commandImageService.readRegistry();
1599        serviceLocator.registerService(ICommandImageService.class,
1600                commandImageService);
1601        
1602        final WorkbenchMenuService menuService = new WorkbenchMenuService(serviceLocator);
1603        
1604        serviceLocator.registerService(IMenuService.class, menuService);
1605        // the service must be registered before it is initialized - its
1606
// initialization uses the service locator to address a dependency on
1607
// the menu service
1608
StartupThreading.runWithoutExceptions(new StartupRunnable() {
1609
1610            public void runWithException() {
1611                menuService.readRegistry();
1612            }});
1613
1614        /*
1615         * Phase 2 of the initialization of commands. The source providers that
1616         * the workbench provides are creating and registered with the above
1617         * services. These source providers notify the services when particular
1618         * pieces of workbench state change.
1619         */

1620        final ISourceProviderService sourceProviderService = new SourceProviderService();
1621        serviceLocator.registerService(ISourceProviderService.class,
1622                sourceProviderService);
1623        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1624
1625            public void runWithException() {
1626                final ActiveShellSourceProvider activeShellSourceProvider = new ActiveShellSourceProvider(
1627                        Workbench.this);
1628                evaluationService.addSourceProvider(activeShellSourceProvider);
1629                handlerService[0].addSourceProvider(activeShellSourceProvider);
1630                contextService.addSourceProvider(activeShellSourceProvider);
1631                menuService.addSourceProvider(activeShellSourceProvider);
1632                sourceProviderService.registerProvider(activeShellSourceProvider);
1633            }});
1634        
1635        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1636
1637            public void runWithException() {
1638                final ActivePartSourceProvider activePartSourceProvider = new ActivePartSourceProvider(
1639                        Workbench.this);
1640                evaluationService.addSourceProvider(activePartSourceProvider);
1641                handlerService[0].addSourceProvider(activePartSourceProvider);
1642                contextService.addSourceProvider(activePartSourceProvider);
1643                menuService.addSourceProvider(activePartSourceProvider);
1644                sourceProviderService.registerProvider(activePartSourceProvider);
1645            }});
1646        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1647
1648            public void runWithException() {
1649                final ActiveContextSourceProvider activeContextSourceProvider = new ActiveContextSourceProvider(
1650                        contextService);
1651                evaluationService.addSourceProvider(activeContextSourceProvider);
1652                handlerService[0].addSourceProvider(activeContextSourceProvider);
1653                menuService.addSourceProvider(activeContextSourceProvider);
1654                sourceProviderService.registerProvider(activeContextSourceProvider);
1655            }});
1656        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1657
1658            public void runWithException() {
1659                final CurrentSelectionSourceProvider currentSelectionSourceProvider = new CurrentSelectionSourceProvider(
1660                        Workbench.this);
1661                evaluationService.addSourceProvider(currentSelectionSourceProvider);
1662                handlerService[0].addSourceProvider(currentSelectionSourceProvider);
1663                contextService.addSourceProvider(currentSelectionSourceProvider);
1664                menuService.addSourceProvider(currentSelectionSourceProvider);
1665                sourceProviderService.registerProvider(currentSelectionSourceProvider);
1666                
1667                actionSetSourceProvider = new ActionSetSourceProvider();
1668                evaluationService.addSourceProvider(actionSetSourceProvider);
1669                handlerService[0].addSourceProvider(actionSetSourceProvider);
1670                contextService.addSourceProvider(actionSetSourceProvider);
1671                menuService.addSourceProvider(actionSetSourceProvider);
1672                sourceProviderService.registerProvider(actionSetSourceProvider);
1673                
1674                FocusControlSourceProvider focusControl = new FocusControlSourceProvider();
1675                serviceLocator.registerService(IFocusService.class, focusControl);
1676                evaluationService.addSourceProvider(focusControl);
1677                handlerService[0].addSourceProvider(focusControl);
1678                contextService.addSourceProvider(focusControl);
1679                menuService.addSourceProvider(focusControl);
1680                sourceProviderService.registerProvider(focusControl);
1681                
1682                
1683                menuSourceProvider = new MenuSourceProvider();
1684                evaluationService.addSourceProvider(menuSourceProvider);
1685                handlerService[0].addSourceProvider(menuSourceProvider);
1686                contextService.addSourceProvider(menuSourceProvider);
1687                menuService.addSourceProvider(menuSourceProvider);
1688                sourceProviderService.registerProvider(menuSourceProvider);
1689            }});
1690        
1691        /*
1692         * Phase 3 of the initialization of commands. This handles the creation
1693         * of wrappers for legacy APIs. By the time this phase completes, any
1694         * code trying to access commands through legacy APIs should work.
1695         */

1696        workbenchContextSupport = new WorkbenchContextSupport(this,
1697                contextManager);
1698        workbenchCommandSupport = new WorkbenchCommandSupport(bindingManager,
1699                commandManager, contextManager, handlerService[0]);
1700        initializeCommandResolver();
1701
1702        addWindowListener(windowListener);
1703        bindingManager.addBindingManagerListener(bindingManagerListener);
1704
1705        serviceLocator.registerService(ISelectionConversionService.class,
1706                new SelectionConversionService());
1707    }
1708
1709    /**
1710     * Returns true if the Workbench is in the process of starting.
1711     *
1712     * @return <code>true</code> if the Workbench is starting, but not yet
1713     * running the event loop.
1714     */

1715    public boolean isStarting() {
1716        return isStarting;
1717    }
1718
1719    /*
1720     * Creates a new workbench window.
1721     *
1722     * @return the new workbench window
1723     */

1724    private WorkbenchWindow newWorkbenchWindow() {
1725        return new WorkbenchWindow(getNewWindowNumber());
1726    }
1727
1728    /*
1729     * If a perspective was specified on the command line (-perspective) then
1730     * force that perspective to open in the active window.
1731     */

1732    private void forceOpenPerspective() {
1733        if (getWorkbenchWindowCount() == 0) {
1734            // there should be an open window by now, bail out.
1735
return;
1736        }
1737
1738        String JavaDoc perspId = null;
1739        String JavaDoc[] commandLineArgs = Platform.getCommandLineArgs();
1740        for (int i = 0; i < commandLineArgs.length - 1; i++) {
1741            if (commandLineArgs[i].equalsIgnoreCase("-perspective")) { //$NON-NLS-1$
1742
perspId = commandLineArgs[i + 1];
1743                break;
1744            }
1745        }
1746        if (perspId == null) {
1747            return;
1748        }
1749        IPerspectiveDescriptor desc = getPerspectiveRegistry()
1750                .findPerspectiveWithId(perspId);
1751        if (desc == null) {
1752            return;
1753        }
1754
1755        IWorkbenchWindow win = getActiveWorkbenchWindow();
1756        if (win == null) {
1757            win = getWorkbenchWindows()[0];
1758        }
1759        
1760        final String JavaDoc threadPerspId = perspId;
1761        final IWorkbenchWindow threadWin = win;
1762        StartupThreading.runWithoutExceptions(new StartupRunnable() {
1763            public void runWithException() throws Throwable JavaDoc {
1764                try {
1765                    showPerspective(threadPerspId, threadWin);
1766                } catch (WorkbenchException e) {
1767                    String JavaDoc msg = "Workbench exception showing specified command line perspective on startup."; //$NON-NLS-1$
1768
WorkbenchPlugin.log(msg, new Status(IStatus.ERROR,
1769                            PlatformUI.PLUGIN_ID, 0, msg, e));
1770                }
1771            }});
1772    }
1773
1774    /**
1775     * Opens the initial workbench window.
1776     */

1777    /* package */void openFirstTimeWindow() {
1778        final boolean showProgress = PrefUtil.getAPIPreferenceStore()
1779                .getBoolean(
1780                        IWorkbenchPreferenceConstants.SHOW_PROGRESS_ON_STARTUP);
1781
1782        if (!showProgress) {
1783            doOpenFirstTimeWindow();
1784        } else {
1785            // We don't know how many plug-ins will be loaded,
1786
// assume we are loading a tenth of the installed plug-ins.
1787
// (The Eclipse SDK loads 7 of 86 plug-ins at startup as of
1788
// 2005-5-20)
1789
final int expectedProgressCount = Math.max(1, WorkbenchPlugin
1790                    .getDefault().getBundleCount() / 10);
1791
1792            runStartupWithProgress(expectedProgressCount, new Runnable JavaDoc() {
1793                public void run() {
1794                    doOpenFirstTimeWindow();
1795                }
1796            });
1797        }
1798    }
1799
1800    private void runStartupWithProgress(final int expectedProgressCount,
1801            final Runnable JavaDoc runnable) {
1802        progressCount = 0;
1803        final double cutoff = 0.95;
1804
1805        AbstractSplashHandler handler = getSplash();
1806        IProgressMonitor progressMonitor = null;
1807        if (handler != null)
1808            progressMonitor = handler.getBundleProgressMonitor();
1809         
1810        if (progressMonitor == null) {
1811            // cannot report progress (e.g. if the splash screen is not showing)
1812
// fall back to starting without showing progress.
1813
runnable.run();
1814        } else {
1815            progressMonitor.beginTask("", expectedProgressCount); //$NON-NLS-1$
1816
SynchronousBundleListener bundleListener = new StartupProgressBundleListener(
1817                    progressMonitor, (int) (expectedProgressCount * cutoff));
1818            WorkbenchPlugin.getDefault().addBundleListener(bundleListener);
1819            try {
1820                runnable.run();
1821                progressMonitor.subTask(WorkbenchMessages.Startup_Done);
1822                int remainingWork = expectedProgressCount
1823                        - Math.min(progressCount,
1824                                (int) (expectedProgressCount * cutoff));
1825                progressMonitor.worked(remainingWork);
1826                progressMonitor.done();
1827            } finally {
1828                WorkbenchPlugin.getDefault().removeBundleListener(
1829                        bundleListener);
1830            }
1831        }
1832    }
1833
1834    private void doOpenFirstTimeWindow() {
1835        try {
1836            final IAdaptable input [] = new IAdaptable[1];
1837            StartupThreading.runWithoutExceptions(new StartupRunnable() {
1838
1839                public void runWithException() throws Throwable JavaDoc {
1840                    input[0] = getDefaultPageInput();
1841                }});
1842            
1843            busyOpenWorkbenchWindow(getPerspectiveRegistry()
1844                    .getDefaultPerspective(), input[0]);
1845        } catch (final WorkbenchException e) {
1846            // Don't use the window's shell as the dialog parent,
1847
// as the window is not open yet (bug 76724).
1848
StartupThreading.runWithoutExceptions(new StartupRunnable() {
1849
1850                public void runWithException() throws Throwable JavaDoc {
1851                    ErrorDialog.openError(null,
1852                            WorkbenchMessages.Problems_Opening_Page, e.getMessage(), e
1853                                    .getStatus());
1854                }});
1855        }
1856    }
1857
1858    /*
1859     * Restores the workbench UI from the workbench state file (workbench.xml).
1860     *
1861     * @return a status object indicating OK if a window was opened,
1862     * RESTORE_CODE_RESET if no window was opened but one should be, and
1863     * RESTORE_CODE_EXIT if the workbench should close immediately
1864     */

1865    /* package */IStatus restoreState() {
1866
1867        if (!getWorkbenchConfigurer().getSaveAndRestore()) {
1868            String JavaDoc msg = WorkbenchMessages.Workbench_restoreDisabled;
1869            return new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
1870                    IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1871        }
1872        // Read the workbench state file.
1873
final File JavaDoc stateFile = getWorkbenchStateFile();
1874        // If there is no state file cause one to open.
1875
if (stateFile == null || !stateFile.exists()) {
1876            String JavaDoc msg = WorkbenchMessages.Workbench_noStateToRestore;
1877            return new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
1878                    IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1879        }
1880
1881        final IStatus result[] = { new Status(IStatus.OK,
1882                WorkbenchPlugin.PI_WORKBENCH, IStatus.OK, "", null) }; //$NON-NLS-1$
1883
SafeRunner.run(new SafeRunnable(WorkbenchMessages.ErrorReadingState) {
1884            public void run() throws Exception JavaDoc {
1885                FileInputStream JavaDoc input = new FileInputStream JavaDoc(stateFile);
1886                BufferedReader JavaDoc reader = new BufferedReader JavaDoc(
1887                        new InputStreamReader JavaDoc(input, "utf-8")); //$NON-NLS-1$
1888
IMemento memento = XMLMemento.createReadRoot(reader);
1889
1890                // Validate known version format
1891
String JavaDoc version = memento
1892                        .getString(IWorkbenchConstants.TAG_VERSION);
1893                boolean valid = false;
1894                for (int i = 0; i < VERSION_STRING.length; i++) {
1895                    if (VERSION_STRING[i].equals(version)) {
1896                        valid = true;
1897                        break;
1898                    }
1899                }
1900                if (!valid) {
1901                    reader.close();
1902                    String JavaDoc msg = WorkbenchMessages.Invalid_workbench_state_ve;
1903                    MessageDialog.openError((Shell) null,
1904                            WorkbenchMessages.Restoring_Problems, msg);
1905                    stateFile.delete();
1906                    result[0] = new Status(IStatus.ERROR,
1907                            WorkbenchPlugin.PI_WORKBENCH,
1908                            IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1909                    return;
1910                }
1911
1912                // Validate compatible version format
1913
// We no longer support the release 1.0 format
1914
if (VERSION_STRING[0].equals(version)) {
1915                    reader.close();
1916                    String JavaDoc msg = WorkbenchMessages.Workbench_incompatibleSavedStateVersion;
1917                    boolean ignoreSavedState = new MessageDialog(null,
1918                            WorkbenchMessages.Workbench_incompatibleUIState,
1919                            null, msg, MessageDialog.WARNING, new String JavaDoc[] {
1920                                    IDialogConstants.OK_LABEL,
1921                                    IDialogConstants.CANCEL_LABEL }, 0).open() == 0;
1922                    // OK is the default
1923
if (ignoreSavedState) {
1924                        stateFile.delete();
1925                        result[0] = new Status(IStatus.WARNING,
1926                                WorkbenchPlugin.PI_WORKBENCH,
1927                                IWorkbenchConfigurer.RESTORE_CODE_RESET, msg,
1928                                null);
1929                    } else {
1930                        result[0] = new Status(IStatus.WARNING,
1931                                WorkbenchPlugin.PI_WORKBENCH,
1932                                IWorkbenchConfigurer.RESTORE_CODE_EXIT, msg,
1933                                null);
1934                    }
1935                    return;
1936                }
1937
1938                // Restore the saved state
1939
final IStatus restoreResult = restoreState(memento);
1940                reader.close();
1941                if (restoreResult.getSeverity() == IStatus.ERROR) {
1942                    StartupThreading
1943                            .runWithoutExceptions(new StartupRunnable() {
1944
1945                                public void runWithException() throws Throwable JavaDoc {
1946                                    ErrorDialog
1947                                            .openError(
1948                                                    null,
1949                                                    WorkbenchMessages.Workspace_problemsTitle,
1950                                                    WorkbenchMessages.Workbench_problemsRestoringMsg,
1951                                                    restoreResult);
1952                                }
1953                            });
1954
1955                }
1956            }
1957
1958            public void handleException(final Throwable JavaDoc e) {
1959                StartupThreading.runWithoutExceptions(new StartupRunnable() {
1960
1961                    public void runWithException() {
1962                        handle(e);
1963                        String JavaDoc msg = e.getMessage() == null ? "" : e.getMessage(); //$NON-NLS-1$
1964
result[0] = new Status(IStatus.ERROR,
1965                                WorkbenchPlugin.PI_WORKBENCH,
1966                                IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, e);
1967                        stateFile.delete();
1968                    }});
1969            }
1970            
1971            private void handle(final Throwable JavaDoc e) {
1972                super.handleException(e);
1973            }
1974        });
1975        // ensure at least one window was opened
1976
if (result[0].isOK() && windowManager.getWindows().length == 0) {
1977            String JavaDoc msg = WorkbenchMessages.Workbench_noWindowsRestored;
1978            result[0] = new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH,
1979                    IWorkbenchConfigurer.RESTORE_CODE_RESET, msg, null);
1980        }
1981        return result[0];
1982    }
1983
1984    /*
1985     * (non-Javadoc) Method declared on IWorkbench.
1986     */

1987    public IWorkbenchWindow openWorkbenchWindow(IAdaptable input)
1988            throws WorkbenchException {
1989        return openWorkbenchWindow(getPerspectiveRegistry()
1990                .getDefaultPerspective(), input);
1991    }
1992
1993    /*
1994     * (non-Javadoc) Method declared on IWorkbench.
1995     */

1996    public IWorkbenchWindow openWorkbenchWindow(final String JavaDoc perspID,
1997            final IAdaptable input) throws WorkbenchException {
1998        // Run op in busy cursor.
1999
final Object JavaDoc[] result = new Object JavaDoc[1];
2000        BusyIndicator.showWhile(null, new Runnable JavaDoc() {
2001            public void run() {
2002                try {
2003                    result[0] = busyOpenWorkbenchWindow(perspID, input);
2004                } catch (WorkbenchException e) {
2005                    result[0] = e;
2006                }
2007            }
2008        });
2009        if (result[0] instanceof IWorkbenchWindow) {
2010            return (IWorkbenchWindow) result[0];
2011        } else if (result[0] instanceof WorkbenchException) {
2012            throw (WorkbenchException) result[0];
2013        } else {
2014            throw new WorkbenchException(
2015                    WorkbenchMessages.Abnormal_Workbench_Conditi);
2016        }
2017    }
2018
2019    /*
2020     * (non-Javadoc)
2021     *
2022     * @see org.eclipse.ui.IWorkbench#restoreWorkbenchWindow(org.eclipse.ui.IMemento)
2023     */

2024    IWorkbenchWindow restoreWorkbenchWindow(IMemento memento)
2025            throws WorkbenchException {
2026        WorkbenchWindow newWindow = newWorkbenchWindow();
2027        newWindow.create();
2028
2029        windowManager.add(newWindow);
2030
2031        // whether the window was opened
2032
boolean opened = false;
2033
2034        try {
2035            newWindow.restoreState(memento, null);
2036            newWindow.fireWindowRestored();
2037            newWindow.open();
2038            opened = true;
2039        } finally {
2040            if (!opened) {
2041                newWindow.close();
2042            }
2043        }
2044
2045        return newWindow;
2046    }
2047
2048    /*
2049     * Record the workbench UI in a document
2050     */

2051    private XMLMemento recordWorkbenchState() {
2052        XMLMemento memento = XMLMemento
2053                .createWriteRoot(IWorkbenchConstants.TAG_WORKBENCH);
2054        final IStatus status = saveState(memento);
2055        if (status.getSeverity() != IStatus.OK) {
2056            // don't use newWindow as parent because it has not yet been opened
2057
// (bug 76724)
2058
StartupThreading.runWithoutExceptions(new StartupRunnable() {
2059
2060                public void runWithException() throws Throwable JavaDoc {
2061                    ErrorDialog.openError(null,
2062                            WorkbenchMessages.Workbench_problemsSaving,
2063                            WorkbenchMessages.Workbench_problemsSavingMsg, status);
2064                }});
2065            
2066        }
2067        return memento;
2068    }
2069
2070    /*
2071     * (non-Javadoc) Method declared on IWorkbench.
2072     */

2073    public boolean restart() {
2074        // this is the return code from run() to trigger a restart
2075
return close(PlatformUI.RETURN_RESTART, false);
2076    }
2077
2078    /*
2079     * Restores the state of the previously saved workbench
2080     */

2081    private IStatus restoreState(final IMemento memento) {
2082
2083        final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
2084                IStatus.OK, WorkbenchMessages.Workbench_problemsRestoring, null);
2085
2086        final boolean showProgress = PrefUtil.getAPIPreferenceStore()
2087                .getBoolean(
2088                        IWorkbenchPreferenceConstants.SHOW_PROGRESS_ON_STARTUP);
2089
2090        try {
2091            /*
2092             * Restored windows will be set in the createdWindows field to be
2093             * used by the openWindowsAfterRestore() method
2094             */

2095            if (!showProgress) {
2096                doRestoreState(memento, result);
2097            } else {
2098                // Retrieve how many plug-ins were loaded while restoring the
2099
// workbench
2100
Integer JavaDoc lastProgressCount = memento
2101                        .getInteger(IWorkbenchConstants.TAG_PROGRESS_COUNT);
2102
2103                // If we don't know how many plug-ins were loaded last time,
2104
// assume we are loading half of the installed plug-ins.
2105
final int expectedProgressCount = Math.max(1,
2106                        lastProgressCount == null ? WorkbenchPlugin
2107                                .getDefault().getBundleCount() / 2
2108                                : lastProgressCount.intValue());
2109
2110                runStartupWithProgress(expectedProgressCount, new Runnable JavaDoc() {
2111                    public void run() {
2112                        doRestoreState(memento, result);
2113                    }
2114                });
2115            }
2116        } finally {
2117            openWindowsAfterRestore();
2118        }
2119        return result;
2120    }
2121
2122    /**
2123     * Returns the ids of all plug-ins that extend the
2124     * <code>org.eclipse.ui.startup</code> extension point.
2125     *
2126     * @return the ids of all plug-ins containing 1 or more startup extensions
2127     */

2128    public String JavaDoc[] getEarlyActivatedPlugins() {
2129        IExtensionPoint point = Platform.getExtensionRegistry()
2130                .getExtensionPoint(PlatformUI.PLUGIN_ID,
2131                        IWorkbenchRegistryConstants.PL_STARTUP);
2132        IExtension[] extensions = point.getExtensions();
2133        ArrayList JavaDoc pluginIds = new ArrayList JavaDoc(extensions.length);
2134        for (int i = 0; i < extensions.length; i++) {
2135            String JavaDoc id = extensions[i].getNamespace();
2136            if (!pluginIds.contains(id)) {
2137                pluginIds.add(id);
2138            }
2139        }
2140        return (String JavaDoc[]) pluginIds.toArray(new String JavaDoc[pluginIds.size()]);
2141    }
2142
2143    /**
2144     * Returns the ids of the early activated plug-ins that have been disabled
2145     * by the user.
2146     *
2147     * @return the ids of the early activated plug-ins that have been disabled
2148     * by the user
2149     */

2150    public String JavaDoc[] getDisabledEarlyActivatedPlugins() {
2151        String JavaDoc pref = PrefUtil.getInternalPreferenceStore().getString(
2152                IPreferenceConstants.PLUGINS_NOT_ACTIVATED_ON_STARTUP);
2153        return Util.getArrayFromList(pref, ";"); //$NON-NLS-1$
2154
}
2155
2156    /*
2157     * Starts all plugins that extend the <code> org.eclipse.ui.startup </code>
2158     * extension point, and that the user has not disabled via the preference
2159     * page.
2160     */

2161    private void startPlugins() {
2162        IExtensionRegistry registry = Platform.getExtensionRegistry();
2163
2164        // bug 55901: don't use getConfigElements directly, for pre-3.0
2165
// compat, make sure to allow both missing class
2166
// attribute and a missing startup element
2167
IExtensionPoint point = registry.getExtensionPoint(
2168                PlatformUI.PLUGIN_ID, IWorkbenchRegistryConstants.PL_STARTUP);
2169
2170        final IExtension[] extensions = point.getExtensions();
2171        if (extensions.length == 0) {
2172            return;
2173        }
2174        Job job = new Job("Workbench early startup") { //$NON-NLS-1$
2175
protected IStatus run(IProgressMonitor monitor) {
2176                HashSet JavaDoc disabledPlugins = new HashSet JavaDoc(Arrays
2177                        .asList(getDisabledEarlyActivatedPlugins()));
2178                monitor.beginTask(WorkbenchMessages.Workbench_startingPlugins,
2179                        extensions.length);
2180                for (int i = 0; i < extensions.length; ++i) {
2181                    if (monitor.isCanceled() || !isRunning()) {
2182                        return Status.CANCEL_STATUS;
2183                    }
2184                    IExtension extension = extensions[i];
2185
2186                    // if the plugin is not in the set of disabled plugins, then
2187
// execute the code to start it
2188
if (!disabledPlugins.contains(extension.getNamespace())) {
2189                        monitor.subTask(extension.getNamespace());
2190                        SafeRunner.run(new EarlyStartupRunnable(extension));
2191                    }
2192                    monitor.worked(1);
2193                }
2194                monitor.done();
2195                return Status.OK_STATUS;
2196            }
2197
2198            public boolean belongsTo(Object JavaDoc family) {
2199                return EARLY_STARTUP_FAMILY.equals(family);
2200            }
2201        };
2202        job.setSystem(true);
2203        job.schedule();
2204    }
2205
2206    /**
2207     * Internal method for running the workbench UI. This entails processing and
2208     * dispatching events until the workbench is closed or restarted.
2209     *
2210     * @return return code {@link PlatformUI#RETURN_OK RETURN_OK}for normal
2211     * exit; {@link PlatformUI#RETURN_RESTART RETURN_RESTART}if the
2212     * workbench was terminated with a call to
2213     * {@link IWorkbench#restart IWorkbench.restart};
2214     * {@link PlatformUI#RETURN_UNSTARTABLE RETURN_UNSTARTABLE}if the
2215     * workbench could not be started; other values reserved for future
2216     * use
2217     * @since 3.0
2218     */

2219    private int runUI() {
2220        UIStats.start(UIStats.START_WORKBENCH, "Workbench"); //$NON-NLS-1$
2221

2222        // deadlock code
2223
boolean avoidDeadlock = true;
2224
2225        String JavaDoc[] commandLineArgs = Platform.getCommandLineArgs();
2226        for (int i = 0; i < commandLineArgs.length; i++) {
2227            if (commandLineArgs[i].equalsIgnoreCase("-allowDeadlock")) { //$NON-NLS-1$
2228
avoidDeadlock = false;
2229            }
2230        }
2231
2232        final UISynchronizer synchronizer;
2233        
2234        if (avoidDeadlock) {
2235            UILockListener uiLockListener = new UILockListener(display);
2236            Platform.getJobManager().setLockListener(uiLockListener);
2237            synchronizer = new UISynchronizer(display, uiLockListener);
2238            display
2239                    .setSynchronizer(synchronizer);
2240            // declare the main thread to be a startup thread.
2241
UISynchronizer.startupThread.set(Boolean.TRUE);
2242        }
2243        else
2244            synchronizer = null;
2245        
2246        // prime the splash nice and early
2247
if (createSplash)
2248            createSplashWrapper();
2249
2250        // ModalContext should not spin the event loop (there is no UI yet to
2251
// block)
2252
ModalContext.setAllowReadAndDispatch(false);
2253
2254        // if the -debug command line argument is used and the event loop is
2255
// being
2256
// run while starting the Workbench, log a warning.
2257
if (WorkbenchPlugin.getDefault().isDebugging()) {
2258            display.asyncExec(new Runnable JavaDoc() {
2259                public void run() {
2260                    if (isStarting()) {
2261                        WorkbenchPlugin
2262                                .log(StatusUtil
2263                                        .newStatus(
2264                                                IStatus.WARNING,
2265                                                "Event loop should not be run while the Workbench is starting.", //$NON-NLS-1$
2266
new RuntimeException JavaDoc()));
2267                    }
2268                }
2269            });
2270        }
2271
2272        Listener closeListener = new Listener() {
2273            public void handleEvent(Event event) {
2274                event.doit = close();
2275            }
2276        };
2277
2278        // Initialize an exception handler.
2279
Window.IExceptionHandler handler = ExceptionHandler.getInstance();
2280
2281        try {
2282            // react to display close event by closing workbench nicely
2283
display.addListener(SWT.Close, closeListener);
2284
2285            // install backstop to catch exceptions thrown out of event loop
2286
Window.setExceptionHandler(handler);
2287
2288            final boolean [] initOK = new boolean[1];
2289            
2290            if (getSplash() != null) {
2291                
2292                final boolean[] initDone = new boolean[]{false};
2293                Thread JavaDoc initThread = new Thread JavaDoc() {
2294                /* (non-Javadoc)
2295                 * @see java.lang.Thread#run()
2296                 */

2297                public void run() {
2298                    try {
2299                        //declare us to be a startup thread so that our syncs will be executed
2300
UISynchronizer.startupThread.set(Boolean.TRUE);
2301                        initOK[0] = Workbench.this.init();
2302                    } finally {
2303                        initDone[0] = true;
2304                        display.wake();
2305                    }
2306                }};
2307                initThread.start();
2308                while (true) {
2309                    if (!display.readAndDispatch()) {
2310                        if (initDone[0])
2311                            break;
2312                        display.sleep();
2313                    }
2314                    
2315                }
2316            }
2317            else {
2318                // initialize workbench and restore or open one window
2319
initOK[0] = init();
2320
2321            }
2322            // drop the splash screen now that a workbench window is up
2323
Platform.endSplash();
2324
2325            // let the advisor run its start up code
2326
if (initOK[0]) {
2327                advisor.postStartup(); // may trigger a close/restart
2328
}
2329
2330            if (initOK[0] && runEventLoop) {
2331                // start eager plug-ins
2332
startPlugins();
2333                addStartupRegistryListener();
2334
2335                // WWinPluginAction.refreshActionList();
2336

2337                display.asyncExec(new Runnable JavaDoc() {
2338                    public void run() {
2339                        UIStats.end(UIStats.START_WORKBENCH, this, "Workbench"); //$NON-NLS-1$
2340
UIStats.startupComplete();
2341                    }
2342                });
2343
2344                getWorkbenchTestable().init(display, this);
2345
2346                // allow ModalContext to spin the event loop
2347
ModalContext.setAllowReadAndDispatch(true);
2348                isStarting = false;
2349
2350                if (synchronizer != null)
2351                    synchronizer.started();
2352                // the event loop
2353
runEventLoop(handler, display);
2354            }
2355
2356        } catch (final Exception JavaDoc e) {
2357            if (!display.isDisposed()) {
2358                handler.handleException(e);
2359            } else {
2360                String JavaDoc msg = "Exception in Workbench.runUI after display was disposed"; //$NON-NLS-1$
2361
WorkbenchPlugin.log(msg, new Status(IStatus.ERROR,
2362                        WorkbenchPlugin.PI_WORKBENCH, 1, msg, e));
2363            }
2364        } finally {
2365            // mandatory clean up
2366

2367            // The runEventLoop flag may not have been cleared if an exception
2368
// occurred
2369
// Needs to be false to ensure PlatformUI.isWorkbenchRunning()
2370
// returns false.
2371
runEventLoop = false;
2372
2373            if (!display.isDisposed()) {
2374                display.removeListener(SWT.Close, closeListener);
2375            }
2376        }
2377
2378        // restart or exit based on returnCode
2379
return returnCode;
2380    }
2381
2382    /*
2383     * Runs an event loop for the workbench.
2384     */

2385    private void runEventLoop(Window.IExceptionHandler handler, Display display) {
2386        runEventLoop = true;
2387        while (runEventLoop) {
2388            try {
2389                if (!display.readAndDispatch()) {
2390                    getAdvisor().eventLoopIdle(display);
2391                }
2392            } catch (Throwable JavaDoc t) {
2393                handler.handleException(t);
2394            }
2395        }
2396    }
2397
2398    /*
2399     * Saves the current state of the workbench so it can be restored later on
2400     */

2401    private IStatus saveState(IMemento memento) {
2402        MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID, IStatus.OK,
2403                WorkbenchMessages.Workbench_problemsSaving, null);
2404
2405        // Save the version number.
2406
memento.putString(IWorkbenchConstants.TAG_VERSION, VERSION_STRING[1]);
2407
2408        // Save how many plug-ins were loaded while restoring the workbench
2409
if (progressCount != -1) {
2410            memento.putInteger(IWorkbenchConstants.TAG_PROGRESS_COUNT,
2411                    progressCount);
2412        }
2413
2414        // Save the advisor state.
2415
IMemento advisorState = memento
2416                .createChild(IWorkbenchConstants.TAG_WORKBENCH_ADVISOR);
2417        result.add(getAdvisor().saveState(advisorState));
2418
2419        // Save the workbench windows.
2420
IWorkbenchWindow[] windows = getWorkbenchWindows();
2421        for (int nX = 0; nX < windows.length; nX++) {
2422            WorkbenchWindow window = (WorkbenchWindow) windows[nX];
2423            IMemento childMem = memento
2424                    .createChild(IWorkbenchConstants.TAG_WINDOW);
2425            result.merge(window.saveState(childMem));
2426        }
2427        result.add(getEditorHistory().saveState(
2428                memento.createChild(IWorkbenchConstants.TAG_MRU_LIST)));
2429        return result;
2430    }
2431
2432    /*
2433     * Save the workbench UI in a persistence file.
2434     */

2435    private boolean saveMementoToFile(XMLMemento memento) {
2436        // Save it to a file.
2437
// XXX: nobody currently checks the return value of this method.
2438
File JavaDoc stateFile = getWorkbenchStateFile();
2439        if (stateFile == null) {
2440            return false;
2441        }
2442        try {
2443            FileOutputStream JavaDoc stream = new FileOutputStream JavaDoc(stateFile);
2444            OutputStreamWriter JavaDoc writer = new OutputStreamWriter JavaDoc(stream, "utf-8"); //$NON-NLS-1$
2445
memento.save(writer);
2446            writer.close();
2447        } catch (IOException JavaDoc e) {
2448            stateFile.delete();
2449            MessageDialog.openError((Shell) null,
2450                    WorkbenchMessages.SavingProblem,
2451                    WorkbenchMessages.ProblemSavingState);
2452            return false;
2453        }
2454
2455        // Success !
2456
return true;
2457    }
2458
2459    /*
2460     * (non-Javadoc) Method declared on IWorkbench.
2461     */

2462    public IWorkbenchPage showPerspective(String JavaDoc perspectiveId,
2463            IWorkbenchWindow window) throws WorkbenchException {
2464        Assert.isNotNull(perspectiveId);
2465
2466        // If the specified window has the requested perspective open, then the
2467
// window
2468
// is given focus and the perspective is shown. The page's input is
2469
// ignored.
2470
WorkbenchWindow win = (WorkbenchWindow) window;
2471        if (win != null) {
2472            WorkbenchPage page = win.getActiveWorkbenchPage();
2473            if (page != null) {
2474                IPerspectiveDescriptor perspectives[] = page
2475                        .getOpenPerspectives();
2476                for (int i = 0; i < perspectives.length; i++) {
2477                    IPerspectiveDescriptor persp = perspectives[i];
2478                    if (perspectiveId.equals(persp.getId())) {
2479                        win.makeVisible();
2480                        page.setPerspective(persp);
2481                        return page;
2482                    }
2483                }
2484            }
2485        }
2486
2487        // If another window that has the workspace root as input and the
2488
// requested
2489
// perpective open and active, then the window is given focus.
2490
IAdaptable input = getDefaultPageInput();
2491        IWorkbenchWindow[] windows = getWorkbenchWindows();
2492        for (int i = 0; i < windows.length; i++) {
2493            win = (WorkbenchWindow) windows[i];
2494            if (window != win) {
2495                WorkbenchPage page = win.getActiveWorkbenchPage();
2496                if (page != null) {
2497                    boolean inputSame = false;
2498                    if (input == null) {
2499                        inputSame = (page.getInput() == null);
2500                    } else {
2501                        inputSame = input.equals(page.getInput());
2502                    }
2503                    if (inputSame) {
2504                        Perspective persp = page.getActivePerspective();
2505                        if (persp != null) {
2506                            IPerspectiveDescriptor desc = persp.getDesc();
2507                            if (desc != null) {
2508                                if (perspectiveId.equals(desc.getId())) {
2509                                    Shell shell = win.getShell();
2510                                    shell.open();
2511                                    if (shell.getMinimized()) {
2512                                        shell.setMinimized(false);
2513                                    }
2514                                    return page;
2515                                }
2516                            }
2517                        }
2518                    }
2519                }
2520            }
2521        }
2522
2523        // Otherwise the requested perspective is opened and shown in the
2524
// specified
2525
// window or in a new window depending on the current user preference
2526
// for opening
2527
// perspectives, and that window is given focus.
2528
win = (WorkbenchWindow) window;
2529        if (win != null) {
2530            IPreferenceStore store = WorkbenchPlugin.getDefault()
2531                    .getPreferenceStore();
2532            int mode = store.getInt(IPreferenceConstants.OPEN_PERSP_MODE);
2533            IWorkbenchPage page = win.getActiveWorkbenchPage();
2534            IPerspectiveDescriptor persp = null;
2535            if (page != null) {
2536                persp = page.getPerspective();
2537            }
2538
2539            // Only open a new window if user preference is set and the window
2540
// has an active perspective.
2541
if (IPreferenceConstants.OPM_NEW_WINDOW == mode && persp != null) {
2542                IWorkbenchWindow newWindow = openWorkbenchWindow(perspectiveId,
2543                        input);
2544                return newWindow.getActivePage();
2545            }
2546
2547            IPerspectiveDescriptor desc = getPerspectiveRegistry()
2548                    .findPerspectiveWithId(perspectiveId);
2549            if (desc == null) {
2550                throw new WorkbenchException(
2551                        NLS
2552                                .bind(
2553                                        WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2554                                        perspectiveId));
2555            }
2556            win.getShell().open();
2557            if (page == null) {
2558                page = win.openPage(perspectiveId, input);
2559            } else {
2560                page.setPerspective(desc);
2561            }
2562            return page;
2563        }
2564
2565        // Just throw an exception....
2566
throw new WorkbenchException(NLS
2567                .bind(WorkbenchMessages.Workbench_showPerspectiveError,
2568                        perspectiveId));
2569    }
2570
2571    /*
2572     * (non-Javadoc) Method declared on IWorkbench.
2573     */

2574    public IWorkbenchPage showPerspective(String JavaDoc perspectiveId,
2575            IWorkbenchWindow window, IAdaptable input)
2576            throws WorkbenchException {
2577        Assert.isNotNull(perspectiveId);
2578
2579        // If the specified window has the requested perspective open and the
2580
// same requested
2581
// input, then the window is given focus and the perspective is shown.
2582
boolean inputSameAsWindow = false;
2583        WorkbenchWindow win = (WorkbenchWindow) window;
2584        if (win != null) {
2585            WorkbenchPage page = win.getActiveWorkbenchPage();
2586            if (page != null) {
2587                boolean inputSame = false;
2588                if (input == null) {
2589                    inputSame = (page.getInput() == null);
2590                } else {
2591                    inputSame = input.equals(page.getInput());
2592                }
2593                if (inputSame) {
2594                    inputSameAsWindow = true;
2595                    IPerspectiveDescriptor perspectives[] = page
2596                            .getOpenPerspectives();
2597                    for (int i = 0; i < perspectives.length; i++) {
2598                        IPerspectiveDescriptor persp = perspectives[i];
2599                        if (perspectiveId.equals(persp.getId())) {
2600                            win.makeVisible();
2601                            page.setPerspective(persp);
2602                            return page;
2603                        }
2604                    }
2605                }
2606            }
2607        }
2608
2609        // If another window has the requested input and the requested
2610
// perpective open and active, then that window is given focus.
2611
IWorkbenchWindow[] windows = getWorkbenchWindows();
2612        for (int i = 0; i < windows.length; i++) {
2613            win = (WorkbenchWindow) windows[i];
2614            if (window != win) {
2615                WorkbenchPage page = win.getActiveWorkbenchPage();
2616                if (page != null) {
2617                    boolean inputSame = false;
2618                    if (input == null) {
2619                        inputSame = (page.getInput() == null);
2620                    } else {
2621                        inputSame = input.equals(page.getInput());
2622                    }
2623                    if (inputSame) {
2624                        Perspective persp = page.getActivePerspective();
2625                        if (persp != null) {
2626                            IPerspectiveDescriptor desc = persp.getDesc();
2627                            if (desc != null) {
2628                                if (perspectiveId.equals(desc.getId())) {
2629                                    win.getShell().open();
2630                                    return page;
2631                                }
2632                            }
2633                        }
2634                    }
2635                }
2636            }
2637        }
2638
2639        // If the specified window has the same requested input but not the
2640
// requested
2641
// perspective, then the window is given focus and the perspective is
2642
// opened and shown
2643
// on condition that the user preference is not to open perspectives in
2644
// a new window.
2645
win = (WorkbenchWindow) window;
2646        if (inputSameAsWindow && win != null) {
2647            IPreferenceStore store = WorkbenchPlugin.getDefault()
2648                    .getPreferenceStore();
2649            int mode = store.getInt(IPreferenceConstants.OPEN_PERSP_MODE);
2650
2651            if (IPreferenceConstants.OPM_NEW_WINDOW != mode) {
2652                IWorkbenchPage page = win.getActiveWorkbenchPage();
2653                IPerspectiveDescriptor desc = getPerspectiveRegistry()
2654                        .findPerspectiveWithId(perspectiveId);
2655                if (desc == null) {
2656                    throw new WorkbenchException(
2657                            NLS
2658                                    .bind(
2659                                            WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2660                                            perspectiveId));
2661                }
2662                win.getShell().open();
2663                if (page == null) {
2664                    page = win.openPage(perspectiveId, input);
2665                } else {
2666                    page.setPerspective(desc);
2667                }
2668                return page;
2669            }
2670        }
2671
2672        // If the specified window has no active perspective, then open the
2673
// requested perspective and show the specified window.
2674
if (win != null) {
2675            IWorkbenchPage page = win.getActiveWorkbenchPage();
2676            IPerspectiveDescriptor persp = null;
2677            if (page != null) {
2678                persp = page.getPerspective();
2679            }
2680            if (persp == null) {
2681                IPerspectiveDescriptor desc = getPerspectiveRegistry()
2682                        .findPerspectiveWithId(perspectiveId);
2683                if (desc == null) {
2684                    throw new WorkbenchException(
2685                            NLS
2686                                    .bind(
2687                                            WorkbenchMessages.WorkbenchPage_ErrorCreatingPerspective,
2688                                            perspectiveId));
2689                }
2690                win.getShell().open();
2691                if (page == null) {
2692                    page = win.openPage(perspectiveId, input);
2693                } else {
2694                    page.setPerspective(desc);
2695                }
2696                return page;
2697            }
2698        }
2699
2700        // Otherwise the requested perspective is opened and shown in a new
2701
// window, and the
2702
// window is given focus.
2703
IWorkbenchWindow newWindow = openWorkbenchWindow(perspectiveId, input);
2704        return newWindow.getActivePage();
2705    }
2706
2707    /*
2708     * Shuts down the application.
2709     */

2710    private void shutdown() {
2711        // shutdown application-specific portions first
2712
advisor.postShutdown();
2713
2714        // notify regular workbench clients of shutdown, and clear the list when
2715
// done
2716
firePostShutdown();
2717        workbenchListeners.clear();
2718
2719        cancelEarlyStartup();
2720
2721        // for dynamic UI
2722
Platform.getExtensionRegistry().removeRegistryChangeListener(
2723                extensionEventHandler);
2724        Platform.getExtensionRegistry().removeRegistryChangeListener(
2725                startupRegistryListener);
2726
2727        ((GrabFocus) Tweaklets.get(GrabFocus.KEY)).dispose();
2728        
2729        // Bring down all of the services.
2730
serviceLocator.dispose();
2731
2732        workbenchActivitySupport.dispose();
2733        WorkbenchHelpSystem.disposeIfNecessary();
2734
2735        // shutdown the rest of the workbench
2736
WorkbenchColors.shutdown();
2737        activityHelper.shutdown();
2738        uninitializeImages();
2739        if (WorkbenchPlugin.getDefault() != null) {
2740            WorkbenchPlugin.getDefault().reset();
2741        }
2742        WorkbenchThemeManager.getInstance().dispose();
2743        PropertyPageContributorManager.getManager().dispose();
2744        ObjectActionContributorManager.getManager().dispose();
2745        if (tracker != null) {
2746            tracker.close();
2747        }
2748    }
2749
2750    /**
2751     * Cancels the early startup job, if it's still running.
2752     */

2753    private void cancelEarlyStartup() {
2754        Platform.getJobManager().cancel(EARLY_STARTUP_FAMILY);
2755        // We do not currently wait for any plug-in currently being started to
2756
// complete
2757
// (e.g. by doing a join on EARLY_STARTUP_FAMILY), since they may do a
2758
// syncExec,
2759
// which would hang. See bug 94537 for rationale.
2760
}
2761
2762    /*
2763     * (non-Javadoc) Method declared on IWorkbench.
2764     */

2765    public IDecoratorManager getDecoratorManager() {
2766        return WorkbenchPlugin.getDefault().getDecoratorManager();
2767    }
2768
2769    /*
2770     * Returns the workbench window which was last known being the active one,
2771     * or <code> null </code> .
2772     */

2773    private WorkbenchWindow getActivatedWindow() {
2774        if (activatedWindow != null) {
2775            Shell shell = activatedWindow.getShell();
2776            if (shell != null && !shell.isDisposed()) {
2777                return activatedWindow;
2778            }
2779        }
2780
2781        return null;
2782    }
2783
2784    /*
2785     * Sets the workbench window which was last known being the active one, or
2786     * <code> null </code> .
2787     */

2788    /* package */
2789    void setActivatedWindow(WorkbenchWindow window) {
2790        activatedWindow = window;
2791    }
2792
2793    /**
2794     * Returns the unique object that applications use to configure the
2795     * workbench.
2796     * <p>
2797     * IMPORTANT This method is declared package-private to prevent regular
2798     * plug-ins from downcasting IWorkbench to Workbench and getting hold of the
2799     * workbench configurer that would allow them to tamper with the workbench.
2800     * The workbench configurer is available only to the application.
2801     * </p>
2802     */

2803    /* package */
2804    WorkbenchConfigurer getWorkbenchConfigurer() {
2805        if (workbenchConfigurer == null) {
2806            workbenchConfigurer = new WorkbenchConfigurer();
2807        }
2808        return workbenchConfigurer;
2809    }
2810
2811    /**
2812     * Returns the workbench advisor that created this workbench.
2813     * <p>
2814     * IMPORTANT This method is declared package-private to prevent regular
2815     * plug-ins from downcasting IWorkbench to Workbench and getting hold of the
2816     * workbench advisor that would allow them to tamper with the workbench. The
2817     * workbench advisor is internal to the application.
2818     * </p>
2819     */

2820    /* package */
2821    WorkbenchAdvisor getAdvisor() {
2822        return advisor;
2823    }
2824
2825    /*
2826     * (non-Javadoc) Method declared on IWorkbench.
2827     */

2828    public Display getDisplay() {
2829        return display;
2830    }
2831
2832    /**
2833     * Returns the default perspective id, which may be <code>null</code>.
2834     *
2835     * @return the default perspective id, or <code>null</code>
2836     */

2837    public String JavaDoc getDefaultPerspectiveId() {
2838        return getAdvisor().getInitialWindowPerspectiveId();
2839    }
2840
2841    /**
2842     * Returns the default workbench window page input.
2843     *
2844     * @return the default window page input or <code>null</code> if none
2845     */

2846    public IAdaptable getDefaultPageInput() {
2847        return getAdvisor().getDefaultPageInput();
2848    }
2849
2850    /**
2851     * Returns the id of the preference page that should be presented most
2852     * prominently.
2853     *
2854     * @return the id of the preference page, or <code>null</code> if none
2855     */

2856    public String JavaDoc getMainPreferencePageId() {
2857        String JavaDoc id = getAdvisor().getMainPreferencePageId();
2858        return id;
2859    }
2860
2861    /*
2862     * (non-Javadoc)
2863     *
2864     * @see org.eclipse.ui.IWorkbench
2865     * @since 3.0
2866     */

2867    public IElementFactory getElementFactory(String JavaDoc factoryId) {
2868        Assert.isNotNull(factoryId);
2869        return WorkbenchPlugin.getDefault().getElementFactory(factoryId);
2870    }
2871
2872    /*
2873     * (non-Javadoc)
2874     *
2875     * @see org.eclipse.ui.IWorkbench#getProgressService()
2876     */

2877    public IProgressService getProgressService() {
2878        return ProgressManager.getInstance();
2879    }
2880
2881    private WorkbenchActivitySupport workbenchActivitySupport;
2882
2883    private WorkbenchCommandSupport workbenchCommandSupport;
2884
2885    private WorkbenchContextSupport workbenchContextSupport;
2886
2887    /**
2888     * The single instance of the binding manager used by the workbench. This is
2889     * initialized in <code>Workbench.init(Display)</code> and then never
2890     * changed. This value will only be <code>null</code> if the
2891     * initialization call has not yet completed.
2892     *
2893     * @since 3.1
2894     */

2895    private BindingManager bindingManager;
2896
2897    /**
2898     * The single instance of the command manager used by the workbench. This is
2899     * initialized in <code>Workbench.init(Display)</code> and then never
2900     * changed. This value will only be <code>null</code> if the
2901     * initialization call has not yet completed.
2902     *
2903     * @since 3.1
2904     */

2905    private CommandManager commandManager;
2906
2907    /**
2908     * The single instance of the context manager used by the workbench. This is
2909     * initialized in <code>Workbench.init(Display)</code> and then never
2910     * changed. This value will only be <code>null</code> if the
2911     * initialization call has not yet completed.
2912     *
2913     * @since 3.1
2914     */

2915    private ContextManager contextManager;
2916
2917    public IWorkbenchActivitySupport getActivitySupport() {
2918        return workbenchActivitySupport;
2919    }
2920
2921    public IWorkbenchCommandSupport getCommandSupport() {
2922        return workbenchCommandSupport;
2923    }
2924
2925    public IWorkbenchContextSupport getContextSupport() {
2926        return workbenchContextSupport;
2927    }
2928
2929    private final IWindowListener windowListener = new IWindowListener() {
2930
2931        public void windowActivated(IWorkbenchWindow window) {
2932            updateActiveWorkbenchWindowMenuManager(true);
2933        }
2934
2935        public void windowClosed(IWorkbenchWindow window) {
2936            updateActiveWorkbenchWindowMenuManager(true);
2937        }
2938
2939        public void windowDeactivated(IWorkbenchWindow window) {
2940            updateActiveWorkbenchWindowMenuManager(true);
2941        }
2942
2943        public void windowOpened(IWorkbenchWindow window) {
2944            updateActiveWorkbenchWindowMenuManager(true);
2945        }
2946    };
2947
2948    private final IBindingManagerListener bindingManagerListener = new IBindingManagerListener() {
2949
2950        public void bindingManagerChanged(
2951                BindingManagerEvent bindingManagerEvent) {
2952            if (bindingManagerEvent.isActiveBindingsChanged()) {
2953                updateActiveWorkbenchWindowMenuManager(true);
2954            }
2955        }
2956    };
2957
2958    /**
2959     * The source provider that tracks the activation of action sets within the
2960     * workbench. This source provider is <code>null</code> until
2961     * {@link #initializeDefaultServices()} is called.
2962     */

2963    private ActionSetSourceProvider actionSetSourceProvider;
2964
2965    private WorkbenchWindow activeWorkbenchWindow = null;
2966
2967    private void updateActiveWorkbenchWindowMenuManager(boolean textOnly) {
2968        if (activeWorkbenchWindow != null) {
2969            activeWorkbenchWindow
2970                    .removeActionSetsListener(actionSetSourceProvider);
2971            activeWorkbenchWindow = null;
2972        }
2973        boolean actionSetsUpdated = false;
2974
2975        final IWorkbenchWindow workbenchWindow = getActiveWorkbenchWindow();
2976
2977        if (workbenchWindow instanceof WorkbenchWindow) {
2978            activeWorkbenchWindow = (WorkbenchWindow) workbenchWindow;
2979            if (activeWorkbenchWindow.isClosing()) {
2980                return;
2981            }
2982
2983            // Update the action sets.
2984
final Shell windowShell = activeWorkbenchWindow.getShell();
2985            final Shell activeShell = getDisplay().getActiveShell();
2986            final IContextService service = (IContextService) getService(IContextService.class);
2987            if (Util.equals(windowShell, activeShell)
2988                    || service.getShellType(activeShell) == IContextService.TYPE_WINDOW) {
2989                activeWorkbenchWindow
2990                        .addActionSetsListener(actionSetSourceProvider);
2991                final WorkbenchPage page = activeWorkbenchWindow
2992                        .getActiveWorkbenchPage();
2993                final IActionSetDescriptor[] newActionSets;
2994                if (page != null) {
2995                    newActionSets = page.getActionSets();
2996                    final ActionSetsEvent event = new ActionSetsEvent(
2997                            newActionSets);
2998                    actionSetSourceProvider.actionSetsChanged(event);
2999                    actionSetsUpdated = true;
3000                }
3001            }
3002
3003            final MenuManager menuManager = activeWorkbenchWindow
3004                    .getMenuManager();
3005
3006            if (textOnly) {
3007                menuManager.update(IAction.TEXT);
3008            } else {
3009                menuManager.updateAll(true);
3010            }
3011        }
3012
3013        if (!actionSetsUpdated) {
3014            final ActionSetsEvent event = new ActionSetsEvent(null);
3015            actionSetSourceProvider.actionSetsChanged(event);
3016        }
3017    }
3018
3019    private ActivityPersistanceHelper activityHelper;
3020
3021    /*
3022     * (non-Javadoc)
3023     *
3024     * @see org.eclipse.ui.IWorkbench#getIntroManager()
3025     */

3026    public IIntroManager getIntroManager() {
3027        return getWorkbenchIntroManager();
3028    }
3029
3030    /**
3031     * @return the workbench intro manager
3032     * @since 3.0
3033     */

3034    /* package */WorkbenchIntroManager getWorkbenchIntroManager() {
3035        if (introManager == null) {
3036            introManager = new WorkbenchIntroManager(this);
3037        }
3038        return introManager;
3039    }
3040
3041    private WorkbenchIntroManager introManager;
3042
3043    /**
3044     * @return the intro extension for this workbench.
3045     *
3046     * @since 3.0
3047     */

3048    public IntroDescriptor getIntroDescriptor() {
3049        return introDescriptor;
3050    }
3051
3052    /**
3053     * This method exists as a test hook. This method should <strong>NEVER</strong>
3054     * be called by clients.
3055     *
3056     * @param descriptor
3057     * The intro descriptor to use.
3058     * @since 3.0
3059     */

3060    public void setIntroDescriptor(IntroDescriptor descriptor) {
3061        if (getIntroManager().getIntro() != null) {
3062            getIntroManager().closeIntro(getIntroManager().getIntro());
3063        }
3064        introDescriptor = descriptor;
3065    }
3066
3067    /**
3068     * The descriptor for the intro extension that is valid for this workspace,
3069     * <code>null</code> if none.
3070     */

3071    private IntroDescriptor introDescriptor;
3072
3073    private IExtensionTracker tracker;
3074
3075    private IRegistryChangeListener startupRegistryListener = new IRegistryChangeListener() {
3076
3077        /*
3078         * (non-Javadoc)
3079         *
3080         * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
3081         */

3082        public void registryChanged(IRegistryChangeEvent event) {
3083            final IExtensionDelta[] deltas = event.getExtensionDeltas(
3084                    PlatformUI.PLUGIN_ID,
3085                    IWorkbenchRegistryConstants.PL_STARTUP);
3086            if (deltas.length == 0) {
3087                return;
3088            }
3089            final String JavaDoc disabledPlugins = PrefUtil
3090                    .getInternalPreferenceStore()
3091                    .getString(
3092                            IPreferenceConstants.PLUGINS_NOT_ACTIVATED_ON_STARTUP);
3093
3094            for (int i = 0; i < deltas.length; i++) {
3095                IExtension extension = deltas[i].getExtension();
3096                if (deltas[i].getKind() == IExtensionDelta.REMOVED) {
3097                    continue;
3098                }
3099
3100                // if the plugin is not in the set of disabled plugins,
3101
// then
3102
// execute the code to start it
3103
if (disabledPlugins.indexOf(extension.getNamespace()) == -1) {
3104                    SafeRunner.run(new EarlyStartupRunnable(extension));
3105                }
3106            }
3107
3108        }
3109    };
3110
3111    private String JavaDoc factoryID;
3112
3113    /*
3114     * (non-Javadoc)
3115     *
3116     * @see org.eclipse.ui.IWorkbench#getThemeManager()
3117     */

3118    public IThemeManager getThemeManager() {
3119        return WorkbenchThemeManager.getInstance();
3120    }
3121
3122    /**
3123     * Returns <code>true</code> if the workbench is running,
3124     * <code>false</code> if it has been terminated.
3125     *
3126     * @return <code>true</code> if the workbench is running,
3127     * <code>false</code> if it has been terminated.
3128     */

3129    public boolean isRunning() {
3130        return runEventLoop;
3131    }
3132
3133    /**
3134     * Return the presentation ID specified by the preference or the default ID
3135     * if undefined.
3136     *
3137     * @return the presentation ID
3138     * @see IWorkbenchPreferenceConstants#PRESENTATION_FACTORY_ID
3139     */

3140    public String JavaDoc getPresentationId() {
3141        if (factoryID != null) {
3142            return factoryID;
3143        }
3144
3145        factoryID = PrefUtil.getAPIPreferenceStore().getString(
3146                IWorkbenchPreferenceConstants.PRESENTATION_FACTORY_ID);
3147
3148        // Workaround for bug 58975 - New preference mechanism does not properly
3149
// initialize defaults
3150
// Ensure that the UI plugin has started too.
3151
if (factoryID == null || factoryID.equals("")) { //$NON-NLS-1$
3152
factoryID = IWorkbenchConstants.DEFAULT_PRESENTATION_ID;
3153        }
3154        return factoryID;
3155    }
3156
3157    /**
3158     * <p>
3159     * Indicates the start of a large update within the workbench. This is used
3160     * to disable CPU-intensive, change-sensitive services that were temporarily
3161     * disabled in the midst of large changes. This method should always be
3162     * called in tandem with <code>largeUpdateEnd</code>, and the event loop
3163     * should not be allowed to spin before that method is called.
3164     * </p>
3165     * <p>
3166     * Important: always use with <code>largeUpdateEnd</code>!
3167     * </p>
3168     */

3169    public final void largeUpdateStart() {
3170        if (largeUpdates++ == 0) {
3171            // TODO Consider whether these lines still need to be here.
3172
// workbenchCommandSupport.setProcessing(false);
3173
// workbenchContextSupport.setProcessing(false);
3174

3175            final IWorkbenchWindow[] windows = getWorkbenchWindows();
3176            for (int i = 0; i < windows.length; i++) {
3177                IWorkbenchWindow window = windows[i];
3178                if (window instanceof WorkbenchWindow) {
3179                    ((WorkbenchWindow) window).largeUpdateStart();
3180                }
3181            }
3182        }
3183    }
3184
3185    /**
3186     * <p>
3187     * Indicates the end of a large update within the workbench. This is used to
3188     * re-enable services that were temporarily disabled in the midst of large
3189     * changes. This method should always be called in tandem with
3190     * <code>largeUpdateStart</code>, and the event loop should not be
3191     * allowed to spin before this method is called.
3192     * </p>
3193     * <p>
3194     * Important: always protect this call by using <code>finally</code>!
3195     * </p>
3196     */

3197    public final void largeUpdateEnd() {
3198        if (--largeUpdates == 0) {
3199            // TODO Consider whether these lines still need to be here.
3200
// workbenchCommandSupport.setProcessing(true);
3201
// workbenchContextSupport.setProcessing(true);
3202

3203            // Perform window-specific blocking.
3204
final IWorkbenchWindow[] windows = getWorkbenchWindows();
3205            for (int i = 0; i < windows.length; i++) {
3206                IWorkbenchWindow window = windows[i];
3207                if (window instanceof WorkbenchWindow) {
3208                    ((WorkbenchWindow) window).largeUpdateEnd();
3209                }
3210            }
3211        }
3212    }
3213
3214    /*
3215     * (non-Javadoc)
3216     *
3217     * @see org.eclipse.ui.IWorkbench#getExtensionTracker()
3218     */

3219    public IExtensionTracker getExtensionTracker() {
3220        if (tracker == null) {
3221            tracker = new UIExtensionTracker(getDisplay());
3222        }
3223        return tracker;
3224    }
3225
3226    /**
3227     * Adds the listener that handles startup plugins
3228     *
3229     * @since 3.1
3230     */

3231    private void addStartupRegistryListener() {
3232        IExtensionRegistry registry = Platform.getExtensionRegistry();
3233        registry.addRegistryChangeListener(startupRegistryListener);
3234    }
3235
3236    /*
3237     * (non-Javadoc)
3238     *
3239     * @see org.eclipse.ui.IWorkbench#getHelpSystem()
3240     */

3241    public IWorkbenchHelpSystem getHelpSystem() {
3242        return WorkbenchHelpSystem.getInstance();
3243    }
3244
3245    /*
3246     * (non-Javadoc)
3247     *
3248     * @see org.eclipse.ui.IWorkbench#getHelpSystem()
3249     */

3250    public IWorkbenchBrowserSupport getBrowserSupport() {
3251        return WorkbenchBrowserSupport.getInstance();
3252    }
3253
3254    /*
3255     * (non-Javadoc)
3256     *
3257     * @see org.eclipse.ui.IWorkbench#getViewRegistry()
3258     */

3259    public IViewRegistry getViewRegistry() {
3260        return WorkbenchPlugin.getDefault().getViewRegistry();
3261    }
3262
3263    /*
3264     * (non-Javadoc)
3265     *
3266     * @see org.eclipse.ui.IWorkbench#getNewWizardRegistry()
3267     */

3268    public IWizardRegistry getNewWizardRegistry() {
3269        return WorkbenchPlugin.getDefault().getNewWizardRegistry();
3270    }
3271
3272    /*
3273     * (non-Javadoc)
3274     *
3275     * @see org.eclipse.ui.IWorkbench#getImportWizardRegistry()
3276     */

3277    public IWizardRegistry getImportWizardRegistry() {
3278        return WorkbenchPlugin.getDefault().getImportWizardRegistry();
3279    }
3280
3281    /*
3282     * (non-Javadoc)
3283     *
3284     * @see org.eclipse.ui.IWorkbench#getExportWizardRegistry()
3285     */

3286    public IWizardRegistry getExportWizardRegistry() {
3287        return WorkbenchPlugin.getDefault().getExportWizardRegistry();
3288    }
3289
3290    public final Object JavaDoc getAdapter(final Class JavaDoc key) {
3291        return serviceLocator.getService(key);
3292    }
3293
3294    private void doRestoreState(final IMemento memento, final MultiStatus status) {
3295        IMemento childMem;
3296        try {
3297            UIStats.start(UIStats.RESTORE_WORKBENCH, "MRUList"); //$NON-NLS-1$
3298
IMemento mruMemento = memento
3299                    .getChild(IWorkbenchConstants.TAG_MRU_LIST);
3300            if (mruMemento != null) {
3301                status.add(getEditorHistory().restoreState(mruMemento));
3302            }
3303        } finally {
3304            UIStats.end(UIStats.RESTORE_WORKBENCH, this, "MRUList"); //$NON-NLS-1$
3305
}
3306
3307        // Restore advisor state.
3308
IMemento advisorState = memento
3309                .getChild(IWorkbenchConstants.TAG_WORKBENCH_ADVISOR);
3310        if (advisorState != null) {
3311            status.add(getAdvisor().restoreState(advisorState));
3312        }
3313
3314        // Get the child windows.
3315
IMemento[] children = memento
3316                .getChildren(IWorkbenchConstants.TAG_WINDOW);
3317
3318        createdWindows = new WorkbenchWindow[children.length];
3319
3320        // Read the workbench windows.
3321
for (int i = 0; i < children.length; i++) {
3322            childMem = children[i];
3323            final WorkbenchWindow [] newWindow = new WorkbenchWindow[1];
3324            
3325            StartupThreading.runWithoutExceptions(new StartupRunnable() {
3326
3327                public void runWithException() {
3328                    newWindow[0] = newWorkbenchWindow();
3329                    newWindow[0].create();
3330                }});
3331            createdWindows[i] = newWindow[0];
3332
3333            // allow the application to specify an initial perspective to open
3334
// @issue temporary workaround for ignoring initial perspective
3335
// String initialPerspectiveId =
3336
// getAdvisor().getInitialWindowPerspectiveId();
3337
// if (initialPerspectiveId != null) {
3338
// IPerspectiveDescriptor desc =
3339
// getPerspectiveRegistry().findPerspectiveWithId(initialPerspectiveId);
3340
// result.merge(newWindow.restoreState(childMem, desc));
3341
// }
3342
// add the window so that any work done in newWindow.restoreState
3343
// that relies on Workbench methods has windows to work with
3344
windowManager.add(newWindow[0]);
3345
3346            // now that we've added it to the window manager we need to listen
3347
// for any exception that might hose us before we get a chance to
3348
// open it. If one occurs, remove the new window from the manager.
3349
// Assume that the new window is a phantom for now
3350
boolean restored = false;
3351            try {
3352                status.merge(newWindow[0].restoreState(childMem, null));
3353                try {
3354                    newWindow[0].fireWindowRestored();
3355                } catch (WorkbenchException e) {
3356                    status.add(e.getStatus());
3357                }
3358                // everything worked so far, don't close now
3359
restored = true;
3360            } finally {
3361                if (!restored) {
3362                    // null the window in newWindowHolder so that it won't be
3363
// opened later on
3364
createdWindows[i] = null;
3365                    StartupThreading.runWithoutExceptions(new StartupRunnable() {
3366
3367                        public void runWithException() throws Throwable JavaDoc {
3368                            newWindow[0].close();
3369                        }});
3370                }
3371            }
3372        }
3373    }
3374
3375    private void openWindowsAfterRestore() {
3376        if (createdWindows == null) {
3377            return;
3378        }
3379        // now open the windows (except the ones that were nulled because we
3380
// closed them above)
3381
for (int i = 0; i < createdWindows.length; i++) {
3382            if (createdWindows[i] != null) {
3383                final WorkbenchWindow myWindow = createdWindows[i];
3384                StartupThreading.runWithoutExceptions(new StartupRunnable() {
3385
3386                    public void runWithException() throws Throwable JavaDoc {
3387                        boolean opened = false;
3388                        try {
3389                            myWindow.open();
3390                            opened = true;
3391                        } finally {
3392                            if (!opened) {
3393                                myWindow.close();
3394                            }
3395                        }
3396                    }});
3397            }
3398        }
3399        createdWindows = null;
3400    }
3401
3402    /*
3403     * (non-Javadoc)
3404     *
3405     * @see org.eclipse.ui.services.IServiceLocator#getService(java.lang.Object)
3406     */

3407    public final Object JavaDoc getService(final Class JavaDoc key) {
3408        return serviceLocator.getService(key);
3409    }
3410
3411    /*
3412     * (non-Javadoc)
3413     *
3414     * @see org.eclipse.ui.services.IServiceLocator#hasService(java.lang.Object)
3415     */

3416    public final boolean hasService(final Class JavaDoc key) {
3417        return serviceLocator.hasService(key);
3418    }
3419
3420    /**
3421     * Registers a service with this locator. If there is an existing service
3422     * matching the same <code>api</code> and it implements
3423     * {@link IDisposable}, it will be disposed.
3424     *
3425     * @param api
3426     * This is the interface that the service implements. Must not be
3427     * <code>null</code>.
3428     * @param service
3429     * The service to register. This must be some implementation of
3430     * <code>api</code>. This value must not be <code>null</code>.
3431     */

3432    public final void registerService(final Class JavaDoc api, final Object JavaDoc service) {
3433        serviceLocator.registerService(api, service);
3434    }
3435
3436    /**
3437     * The source provider that tracks which context menus (i.e., menus with
3438     * target identifiers) are now showing. This value is <code>null</code>
3439     * until {@link #initializeDefaultServices()} is called.
3440     */

3441    private MenuSourceProvider menuSourceProvider;
3442
3443
3444    /**
3445     * Adds the ids of a menu that is now showing to the menu source provider.
3446     * This is used for legacy action-based handlers which need to become active
3447     * only for the duration of a menu being visible.
3448     *
3449     * @param menuIds
3450     * The identifiers of the menu that is now showing; must not be
3451     * <code>null</code>.
3452     */

3453    public final void addShowingMenus(final Set JavaDoc menuIds,
3454            final ISelection localSelection, final ISelection localEditorInput) {
3455        menuSourceProvider.addShowingMenus(menuIds, localSelection,
3456                localEditorInput);
3457    }
3458
3459    /**
3460     * Removes the ids of a menu that is now hidden from the menu source
3461     * provider. This is used for legacy action-based handlers which need to
3462     * become active only for the duration of a menu being visible.
3463     *
3464     * @param menuIds
3465     * The identifiers of the menu that is now hidden; must not be
3466     * <code>null</code>.
3467     */

3468    public final void removeShowingMenus(final Set JavaDoc menuIds,
3469            final ISelection localSelection, final ISelection localEditorInput) {
3470        menuSourceProvider.removeShowingMenus(menuIds, localSelection,
3471                localEditorInput);
3472    }
3473
3474    /* (non-Javadoc)
3475     * @see org.eclipse.ui.IWorkbench#saveAll(org.eclipse.jface.window.IShellProvider, org.eclipse.jface.operation.IRunnableContext, org.eclipse.ui.ISaveableFilter, boolean)
3476     */

3477    public boolean saveAll(IShellProvider shellProvider,
3478            IRunnableContext runnableContext, ISaveableFilter filter,
3479            boolean confirm) {
3480        SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench()
3481                .getService(ISaveablesLifecycleListener.class);
3482        Saveable[] saveables = saveablesList.getOpenModels();
3483        List JavaDoc toSave = getFilteredSaveables(filter, saveables);
3484        if (toSave.isEmpty())
3485            return true;
3486        
3487        if (!confirm) {
3488            return !saveablesList.saveModels(toSave, shellProvider, runnableContext);
3489        }
3490        
3491        // We must negate the result since false is cancel saveAll
3492
return !saveablesList.promptForSaving(toSave, shellProvider, runnableContext, true, false);
3493    }
3494
3495    /*
3496     * Apply the given filter to the list of saveables
3497     */

3498    private List JavaDoc getFilteredSaveables(ISaveableFilter filter, Saveable[] saveables) {
3499        List JavaDoc toSave = new ArrayList JavaDoc();
3500        if (filter == null) {
3501            for (int i = 0; i < saveables.length; i++) {
3502                Saveable saveable = saveables[i];
3503                if (saveable.isDirty())
3504                    toSave.add(saveable);
3505            }
3506        } else {
3507            SaveablesList saveablesList = (SaveablesList)getService(ISaveablesLifecycleListener.class);
3508            for (int i = 0; i < saveables.length; i++) {
3509                Saveable saveable = saveables[i];
3510                if (saveable.isDirty()) {
3511                    IWorkbenchPart[] parts = saveablesList.getPartsForSaveable(saveable);
3512                    if (matchesFilter(filter, saveable, parts))
3513                        toSave.add(saveable);
3514                }
3515            }
3516        }
3517        return toSave;
3518    }
3519    
3520    /*
3521     * Test whether the given filter matches the saveable
3522     */

3523    private boolean matchesFilter(ISaveableFilter filter, Saveable saveable,
3524            IWorkbenchPart[] parts) {
3525        return filter == null || filter.select(saveable, parts);
3526    }
3527}
3528
Popular Tags