67a8101cf7a87ff7e0a8e9d8e2b68bde52279bef
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / internal / SimanticsWorkbenchAdvisor.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.workbench.internal;\r
13 \r
14 import java.io.IOException;\r
15 import java.lang.reflect.InvocationTargetException;\r
16 import java.net.URL;\r
17 import java.text.Collator;\r
18 import java.util.ArrayList;\r
19 import java.util.Iterator;\r
20 import java.util.Map;\r
21 import java.util.TreeMap;\r
22 \r
23 import org.eclipse.core.internal.resources.Workspace;\r
24 import org.eclipse.core.net.proxy.IProxyService;\r
25 import org.eclipse.core.resources.IContainer;\r
26 import org.eclipse.core.resources.IResource;\r
27 import org.eclipse.core.resources.ResourcesPlugin;\r
28 import org.eclipse.core.resources.WorkspaceJob;\r
29 import org.eclipse.core.runtime.CoreException;\r
30 import org.eclipse.core.runtime.FileLocator;\r
31 import org.eclipse.core.runtime.IAdaptable;\r
32 import org.eclipse.core.runtime.IBundleGroup;\r
33 import org.eclipse.core.runtime.IBundleGroupProvider;\r
34 import org.eclipse.core.runtime.ILog;\r
35 import org.eclipse.core.runtime.IProgressMonitor;\r
36 import org.eclipse.core.runtime.IStatus;\r
37 import org.eclipse.core.runtime.MultiStatus;\r
38 import org.eclipse.core.runtime.Path;\r
39 import org.eclipse.core.runtime.Platform;\r
40 import org.eclipse.core.runtime.ProgressMonitorWrapper;\r
41 import org.eclipse.core.runtime.Status;\r
42 import org.eclipse.core.runtime.SubMonitor;\r
43 import org.eclipse.core.runtime.jobs.Job;\r
44 import org.eclipse.e4.core.contexts.IEclipseContext;\r
45 import org.eclipse.e4.ui.internal.workbench.E4Workbench;\r
46 import org.eclipse.jface.dialogs.ErrorDialog;\r
47 import org.eclipse.jface.dialogs.IDialogSettings;\r
48 import org.eclipse.jface.dialogs.MessageDialog;\r
49 import org.eclipse.jface.dialogs.TrayDialog;\r
50 import org.eclipse.jface.operation.IRunnableWithProgress;\r
51 import org.eclipse.jface.preference.IPreferenceStore;\r
52 import org.eclipse.jface.resource.ImageDescriptor;\r
53 import org.eclipse.jface.util.Policy;\r
54 import org.eclipse.jface.window.Window;\r
55 import org.eclipse.swt.SWT;\r
56 import org.eclipse.swt.events.SelectionAdapter;\r
57 import org.eclipse.swt.events.SelectionEvent;\r
58 import org.eclipse.swt.widgets.Composite;\r
59 import org.eclipse.swt.widgets.Display;\r
60 import org.eclipse.swt.widgets.Event;\r
61 import org.eclipse.swt.widgets.Listener;\r
62 import org.eclipse.swt.widgets.Shell;\r
63 import org.eclipse.ui.IPerspectiveDescriptor;\r
64 import org.eclipse.ui.PlatformUI;\r
65 import org.eclipse.ui.application.IWorkbenchConfigurer;\r
66 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;\r
67 import org.eclipse.ui.application.WorkbenchAdvisor;\r
68 import org.eclipse.ui.application.WorkbenchWindowAdvisor;\r
69 import org.eclipse.ui.ide.IDE;\r
70 import org.eclipse.ui.internal.ISelectionConversionService;\r
71 import org.eclipse.ui.internal.Workbench;\r
72 import org.eclipse.ui.internal.ide.AboutInfo;\r
73 import org.eclipse.ui.internal.ide.IDEInternalPreferences;\r
74 import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;\r
75 import org.eclipse.ui.internal.ide.IDESelectionConversionService;\r
76 import org.eclipse.ui.internal.ide.IDEWorkbenchActivityHelper;\r
77 import org.eclipse.ui.internal.ide.IDEWorkbenchErrorHandler;\r
78 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;\r
79 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;\r
80 import org.eclipse.ui.internal.ide.undo.WorkspaceUndoMonitor;\r
81 import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;\r
82 import org.eclipse.ui.keys.IBindingService;\r
83 import org.eclipse.ui.progress.IProgressService;\r
84 import org.eclipse.ui.statushandlers.AbstractStatusHandler;\r
85 import org.osgi.framework.Bundle;\r
86 import org.osgi.framework.ServiceReference;\r
87 import org.osgi.framework.Version;\r
88 import org.simantics.CancelStartupException;\r
89 import org.simantics.PlatformException;\r
90 import org.simantics.Simantics;\r
91 import org.simantics.SimanticsPlatform;\r
92 import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;\r
93 import org.simantics.SimanticsPlatform.RecoveryPolicy;\r
94 import org.simantics.application.arguments.IArguments;\r
95 import org.simantics.application.arguments.SimanticsArguments;\r
96 import org.simantics.db.common.Indexing;\r
97 import org.simantics.db.indexing.DatabaseIndexing;\r
98 import org.simantics.db.procore.server.environment.RebootRequiredException;\r
99 import org.simantics.db.procore.server.environment.windows.Product;\r
100 import org.simantics.internal.TimedSessionCache;\r
101 import org.simantics.project.IProject;\r
102 import org.simantics.project.ProjectKeys;\r
103 import org.simantics.ui.SimanticsUI;\r
104 import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
105 import org.simantics.ui.workbench.PerspectiveBarsActivator;\r
106 import org.simantics.ui.workbench.PerspectiveContextActivator;\r
107 import org.simantics.utils.logging.TimeLogger;\r
108 import org.simantics.utils.threads.ThreadUtils;\r
109 import org.simantics.utils.ui.dialogs.ShowError;\r
110 import org.simantics.utils.ui.dialogs.ShowMessage;\r
111 \r
112 \r
113 /**\r
114  * @author Tuukka Lehtonen\r
115  */\r
116 public class SimanticsWorkbenchAdvisor extends WorkbenchAdvisor {\r
117 \r
118     private static final boolean PROFILE_PLATFORM_STARTUP = false;\r
119 \r
120     private static final String SHUT_DOWN_TASK = "Shutting down...";\r
121 \r
122     private static final String SHUT_DOWN_PLATFORM_TASK = "Shutting down platform...";\r
123 \r
124     private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$\r
125 \r
126     /**\r
127      * The dialog setting key to access the known installed features since the\r
128      * last time the workbench was run.\r
129      */\r
130     private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$\r
131 \r
132     /**\r
133      * The arguments received by the application.\r
134      */\r
135     protected final IArguments args;\r
136 \r
137     protected final boolean restoredPreviousSession = false;\r
138 \r
139     /**\r
140      * Only true while opening the initial windows during {@link #openWindows()}.\r
141      * Used by {@link SimanticsWorkbenchWindowAdvisor#postWindowOpen()} to\r
142      * recognize when to skip all one-time initialization.\r
143      */\r
144     protected boolean workbenchWindowsInitialized = false;\r
145 \r
146     /**\r
147      * Whether or not to save unsaved database changes before exiting the\r
148      * workbench.\r
149      */\r
150     protected boolean saveAtExit = false;\r
151 \r
152     /**\r
153      * Ordered map of versioned feature ids -> info that are new for this\r
154      * session; <code>null</code> if uninitialized. Key type:\r
155      * <code>String</code>, Value type: <code>AboutInfo</code>.\r
156      */\r
157     private Map<String, AboutInfo> newlyAddedBundleGroups;\r
158 \r
159     /**\r
160      * Array of <code>AboutInfo</code> for all new installed features that\r
161      * specify a welcome perspective.\r
162      */\r
163     private AboutInfo[] welcomePerspectiveInfos = null;\r
164 \r
165     /**\r
166      * Helper for managing activites in response to workspace changes.\r
167      */\r
168     private IDEWorkbenchActivityHelper activityHelper = null;\r
169 \r
170     /**\r
171      * Helper for managing work that is performed when the system is otherwise\r
172      * idle.\r
173      */\r
174     private IDEIdleHelper idleHelper;\r
175 \r
176     private Listener settingsChangeListener;\r
177 \r
178     /**\r
179      * Support class for monitoring workspace changes and periodically\r
180      * validating the undo history\r
181      */\r
182     private WorkspaceUndoMonitor workspaceUndoMonitor;\r
183 \r
184     /**\r
185      * The IDE workbench error handler.\r
186      */\r
187     private AbstractStatusHandler ideWorkbenchErrorHandler;\r
188 \r
189     /**\r
190      * Helper class used to process delayed events.\r
191      */\r
192     private DelayedEventsProcessor delayedEventsProcessor;\r
193     \r
194     /**\r
195      * Creates a new workbench advisor instance.\r
196      * @param processor\r
197      */\r
198     public SimanticsWorkbenchAdvisor(IArguments args, DelayedEventsProcessor processor) {\r
199         super();\r
200         this.args = args;\r
201         this.delayedEventsProcessor = processor;\r
202 \r
203         Listener closeListener = new Listener() {\r
204             public void handleEvent(Event event) {\r
205                 boolean doExit = SimanticsWorkbenchWindowAdvisor.promptOnExit(null);\r
206                 event.doit = doExit;\r
207                 if (!doExit)\r
208                     event.type = SWT.None;\r
209             }\r
210         };\r
211         Display.getDefault().addListener(SWT.Close, closeListener);\r
212     }\r
213 \r
214     public IArguments getArguments() {\r
215         return args;\r
216     }\r
217 \r
218     public boolean workbenchInitialized() {\r
219         return workbenchWindowsInitialized;\r
220     }\r
221 \r
222     public boolean restoredPreviousSession() {\r
223         return restoredPreviousSession;\r
224     }\r
225 \r
226     boolean saveAtExit() {\r
227         return saveAtExit;\r
228     }\r
229 \r
230     void setSaveAtExit(boolean saveAtExit) {\r
231         this.saveAtExit = saveAtExit;\r
232     }\r
233 \r
234     /*\r
235      * (non-Javadoc)\r
236      *\r
237      * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize\r
238      */\r
239     @Override\r
240     public void initialize(IWorkbenchConfigurer configurer) {\r
241         // By default, we always save and restore the workbench state.\r
242         configurer.setSaveAndRestore(true);\r
243 \r
244         checkWorkspaceDatabaseIndexes();\r
245 \r
246         // Start tracking the active perspective to activate contexts based on it.\r
247         new PerspectiveContextActivator();\r
248         new PerspectiveBarsActivator();\r
249 \r
250         // register workspace adapters\r
251         IDE.registerAdapters();\r
252 \r
253         // register shared images\r
254         declareWorkbenchImages();\r
255 \r
256         // initialize the activity helper\r
257         activityHelper = IDEWorkbenchActivityHelper.getInstance();\r
258 \r
259         // initialize idle handler\r
260         idleHelper = new IDEIdleHelper(configurer);\r
261 \r
262         // initialize the workspace undo monitor\r
263         workspaceUndoMonitor = WorkspaceUndoMonitor.getInstance();\r
264 \r
265         // show Help button in JFace dialogs\r
266         TrayDialog.setDialogHelpAvailable(true);\r
267 \r
268         Policy.setComparator(Collator.getInstance());\r
269     }\r
270 \r
271     private void checkWorkspaceDatabaseIndexes() {\r
272         try {\r
273             DatabaseIndexing.validateIndexes();\r
274         } catch (IOException e) {\r
275             Activator.logError("Problems encountered while checking database indexes, see exception for details.", e);\r
276         }\r
277     }\r
278 \r
279     public WorkbenchWindowAdvisor createWorkbenchWindowAdvisorClass(SimanticsWorkbenchAdvisor advisor, IWorkbenchWindowConfigurer configurer) {\r
280         return new SimanticsWorkbenchWindowAdvisor(this, configurer);\r
281     }\r
282 \r
283     @Override\r
284     public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {\r
285         // Attach database session watchdog.\r
286         new SessionWatchdog().attach( Simantics.getSessionContextProvider() );\r
287 \r
288         return createWorkbenchWindowAdvisorClass(this, configurer);\r
289     }\r
290 \r
291     /**\r
292      * For gaining direct access to super.openWindows() in implementations\r
293      * inheriting this one.\r
294      */\r
295     public boolean openWindowsSuper() {\r
296         return super.openWindows();\r
297     }\r
298 \r
299     /**\r
300      * Sadly we do not know why key bindings are lost and why this helps. But it\r
301      * does. Visiting the <code>Keys</code> preference page and pressing OK uses\r
302      * this the same call and it seems to salvage the bindings that have been in\r
303      * some cases destroyed by <code>BindingToModelProcessor</code>.\r
304      * \r
305      * <p>\r
306      * Related links:\r
307      * https://techblog.ralph-schuster.eu/2013/10/13/eclipsee4-problem-with-key-bindings/comment-page-1/\r
308      * https://www.eclipse.org/forums/index.php/t/550175/\r
309      * https://bugs.eclipse.org/bugs/show_bug.cgi?id=461037\r
310      * \r
311      * @see platform issue #6353\r
312      */\r
313     private void fixBindings() {\r
314         try {\r
315             IBindingService bs = PlatformUI.getWorkbench().getAdapter(IBindingService.class);\r
316             bs.savePreferences(bs.getActiveScheme(), bs.getBindings());\r
317         } catch (IOException e) {\r
318             Activator.logError(getClass().getSimpleName() + ".fixBindings failed", e);\r
319         }\r
320     }\r
321 \r
322     @Override\r
323     public boolean openWindows() {\r
324         boolean platformOk = startPlatform();\r
325         TimeLogger.log("SimanticsWorkbenchAdvisor.startPlatform finished");\r
326 \r
327         if (platformOk) {\r
328             // At this point workbenchConfigurer.getSaveAndRestore()\r
329             // returns false iff something has gone terribly wrong\r
330             // before this. Currently saveAndRestore is always true.\r
331             boolean windowsOpened = super.openWindows();\r
332             TimeLogger.log("Opened windows");\r
333             if (windowsOpened) {\r
334                 workbenchWindowsInitialized = true;\r
335 \r
336                 // Start the database garbage collector after a short while.\r
337                 SessionGarbageCollectorJob.getInstance().scheduleAfterQuietTime();\r
338 \r
339                 // Discard database session undo history at this point to prevent\r
340                 // the user from undoing any initialization operations performed\r
341                 // by the platform startup.\r
342                 SimanticsPlatform.INSTANCE.discardSessionUndoHistory();\r
343                 TimeLogger.log("Discarded session undo history");\r
344 \r
345                 // #6353: Workaround for  \r
346                 fixBindings();\r
347 \r
348                 return true;\r
349             }\r
350         }\r
351 \r
352         // Make sure platform shutdown is ran if window opening fails.\r
353         try {\r
354             platformShutdownRunnable.run(null);\r
355         } catch (InvocationTargetException e) {\r
356             Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);\r
357         } catch (InterruptedException e) {\r
358             Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);\r
359         }\r
360         return false;\r
361     }\r
362 \r
363     protected boolean startPlatform() {\r
364         // Verify selected perspective\r
365         if (args.contains(SimanticsArguments.PERSPECTIVE)) {\r
366             String perspectiveId = args.get(SimanticsArguments.PERSPECTIVE);\r
367             IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);\r
368             if (perspective == null) {\r
369                 StringBuilder msg = new StringBuilder();\r
370                 msg.append("Requested perspective not found: '" + perspectiveId + "'\n");\r
371                 msg.append("Valid alternatives are:\n");\r
372                 for (IPerspectiveDescriptor pd : PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives()) {\r
373                     msg.append("    " + pd.getId() + "\n");\r
374                 }\r
375 \r
376                 ShowMessage.syncShowError("Invalid Perspective", msg.toString());\r
377                 return false;\r
378             }\r
379         }\r
380 \r
381         ILog log = Platform.getLog(Activator.getDefault().getBundle());\r
382 \r
383         try {\r
384             //\r
385             //\r
386             // Create Simantics Platform Helper.\r
387             //\r
388             // If Simantics is started from Eclipse IDE or with -fixerrors option,\r
389             // there is an attempt to fix errors.\r
390             //\r
391             // On ontology mismatch, there is an attempt to merge new ontology to the\r
392             // existing database. With -reinstall, the database is cleaned and\r
393             // reinstalled.\r
394             //\r
395             //\r
396 \r
397             RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;\r
398             OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;\r
399 \r
400             if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {\r
401                 workspacePolicy = RecoveryPolicy.FixError;\r
402                 ontologyPolicy = OntologyRecoveryPolicy.Merge;\r
403             }\r
404 \r
405             boolean requireSynchronize = true;\r
406 \r
407             if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {\r
408                 ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;\r
409             }\r
410 \r
411             if (args.contains(SimanticsArguments.DO_NOT_SYNCHRONIZE_ONTOLOGIES)) {\r
412                 requireSynchronize = false;\r
413             }\r
414             \r
415             if (args.contains(SimanticsArguments.DISABLE_INDEX)) {\r
416                 Indexing.setDefaultDependenciesIndexingEnabled(false);\r
417             }\r
418 \r
419             if (args.contains(SimanticsArguments.SERVER)) {\r
420                 String serverAddress = args.get(SimanticsArguments.SERVER);\r
421                 throw new PlatformException("Argument not supported: " + SimanticsArguments.SERVER + " " + serverAddress);\r
422             }\r
423 \r
424             String databaseDriverId = Simantics.getDefaultDatabaseDriver();\r
425             if (args.contains(SimanticsArguments.DATABASE_ID)) {\r
426                 databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);\r
427                 Simantics.setDefaultDatabaseDriver(databaseDriverId);\r
428             }\r
429             \r
430             IProgressMonitor mon = null;\r
431             if (PROFILE_PLATFORM_STARTUP)\r
432                 mon = new TimingProgressMonitor();\r
433             SimanticsPlatform.INSTANCE.startUp(databaseDriverId, mon, workspacePolicy, ontologyPolicy, requireSynchronize, new JFaceUserAgent());\r
434 \r
435             // Make sure that the default perspective comes from the project if\r
436             // the project has set ProjectKeys#DEFAULT_PERSPECTIVE.\r
437             // This might go wrong if project features interact with\r
438             // PerspectiveRegistry while configuring themselves, since that will\r
439             // cause an invocation to #getInitialWindowPerspectiveId() while\r
440             // the project has not yet been properly initialized.\r
441             getWorkbenchConfigurer().getWorkbench().getPerspectiveRegistry().setDefaultPerspective(getInitialWindowPerspectiveId());\r
442             TimeLogger.log("Completed setting default perspective");\r
443 \r
444             return true;\r
445         } catch (CancelStartupException e) {\r
446             return false;\r
447         } catch (PlatformException e) {\r
448             boolean hasStackTrace = e.getStackTrace().length > 0;\r
449             Throwable ee = e;\r
450             while (ee.getCause() != null) {\r
451                 ee = ee.getCause();\r
452                 hasStackTrace = ee.getStackTrace().length > 0;\r
453             }\r
454 \r
455             log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), hasStackTrace ? e : null));\r
456             if (hasStackTrace) {\r
457                 new ShowError("Platform Initialization Failed", "Simantics Platform initialization failed:\n\n" + e.getMessage(), e, true);\r
458             } else {\r
459                 StringBuilder sb = new StringBuilder(256);\r
460                 sb.append(e.getMessage());\r
461                 for (Throwable c=e.getCause(); null != c && null != c.getMessage(); c=c.getCause())\r
462                     sb.append("\ncause: ").append(c.getMessage());\r
463                 new ShowError("Startup Failed", sb.toString(), (Exception) null, true);\r
464             }\r
465 \r
466             return false;\r
467         } catch (Exception e) {\r
468             log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));\r
469 \r
470             Throwable cause = e.getCause();\r
471             if (cause instanceof RebootRequiredException) {\r
472                 RebootRequiredException rre = (RebootRequiredException) cause;\r
473                 StringBuilder msg = new StringBuilder();\r
474                 msg.append("The application must be restarted after installing the following products:\n");\r
475                 for (Product product : rre.products)\r
476                     msg.append("\t" + product + "\n");\r
477                 msg.append("\nThe application will now close.");\r
478                 MessageDialog.openInformation(null, "Restart Required", msg.toString());\r
479             } else {\r
480                 new ShowError("Platform Startup Failed", "Simantics Platform startup failed:\n\n" + e.getMessage(), e, true);\r
481             }\r
482             return false;\r
483         }\r
484 \r
485     }\r
486 \r
487     /*\r
488      * (non-Javadoc)\r
489      *\r
490      * @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()\r
491      */\r
492     @Override\r
493     public void preStartup() {\r
494 \r
495         // Suspend background jobs while we startup\r
496         Job.getJobManager().suspend();\r
497 \r
498         // Register the build actions\r
499         IProgressService service = PlatformUI.getWorkbench()\r
500         .getProgressService();\r
501         ImageDescriptor newImage = IDEInternalWorkbenchImages\r
502         .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);\r
503         service.registerIconForFamily(newImage,\r
504                 ResourcesPlugin.FAMILY_MANUAL_BUILD);\r
505         service.registerIconForFamily(newImage,\r
506                 ResourcesPlugin.FAMILY_AUTO_BUILD);\r
507     }\r
508 \r
509     /*\r
510      * (non-Javadoc)\r
511      *\r
512      * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()\r
513      */\r
514     @Override\r
515     public void postStartup() {\r
516         try {\r
517             refreshFromLocal();\r
518             activateProxyService();\r
519             ((Workbench) PlatformUI.getWorkbench()).registerService(\r
520                     ISelectionConversionService.class,\r
521                     new IDESelectionConversionService());\r
522 \r
523             initializeSettingsChangeListener();\r
524             Display.getCurrent().addListener(SWT.Settings,\r
525                     settingsChangeListener);\r
526         } finally {// Resume background jobs after we startup\r
527             Job.getJobManager().resume();\r
528         }\r
529     }\r
530 \r
531     /**\r
532      * Activate the proxy service by obtaining it.\r
533      */\r
534     private void activateProxyService() {\r
535         Bundle bundle = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$\r
536         Object proxyService = null;\r
537         if (bundle != null) {\r
538             ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(IProxyService.class.getName());\r
539             if (ref != null)\r
540                 proxyService = bundle.getBundleContext().getService(ref);\r
541         }\r
542         if (proxyService == null) {\r
543             IDEWorkbenchPlugin.log("Proxy service could not be found."); //$NON-NLS-1$\r
544         }\r
545     }\r
546 \r
547     /**\r
548      * Initialize the listener for settings changes.\r
549      */\r
550     private void initializeSettingsChangeListener() {\r
551         settingsChangeListener = new Listener() {\r
552 \r
553             boolean currentHighContrast = Display.getCurrent()\r
554             .getHighContrast();\r
555 \r
556             @Override\r
557             public void handleEvent(org.eclipse.swt.widgets.Event event) {\r
558                 if (Display.getCurrent().getHighContrast() == currentHighContrast)\r
559                     return;\r
560 \r
561                 currentHighContrast = !currentHighContrast;\r
562 \r
563                 // make sure they really want to do this\r
564                 if (new MessageDialog(null,\r
565                         IDEWorkbenchMessages.SystemSettingsChange_title, null,\r
566                         IDEWorkbenchMessages.SystemSettingsChange_message,\r
567                         MessageDialog.QUESTION, new String[] {\r
568                         IDEWorkbenchMessages.SystemSettingsChange_yes,\r
569                         IDEWorkbenchMessages.SystemSettingsChange_no },\r
570                         1).open() == Window.OK) {\r
571                     PlatformUI.getWorkbench().restart();\r
572                 }\r
573             }\r
574         };\r
575 \r
576     }\r
577 \r
578     /*\r
579      * (non-Javadoc)\r
580      *\r
581      * @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown\r
582      */\r
583     @Override\r
584     public void postShutdown() {\r
585         if (activityHelper != null) {\r
586             activityHelper.shutdown();\r
587             activityHelper = null;\r
588         }\r
589         if (idleHelper != null) {\r
590             idleHelper.shutdown();\r
591             idleHelper = null;\r
592         }\r
593         if (workspaceUndoMonitor != null) {\r
594             workspaceUndoMonitor.shutdown();\r
595             workspaceUndoMonitor = null;\r
596         }\r
597         if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {\r
598             disconnectFromWorkspace();\r
599         }\r
600     }\r
601 \r
602     /*\r
603      * (non-Javadoc)\r
604      *\r
605      * @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()\r
606      */\r
607     @Override\r
608     public boolean preShutdown() {\r
609         Display.getCurrent().removeListener(SWT.Settings,\r
610                 settingsChangeListener);\r
611         return super.preShutdown();\r
612     }\r
613 \r
614     /**\r
615      * Return true if the intro plugin is present and false otherwise.\r
616      *\r
617      * @return boolean\r
618      */\r
619     public boolean hasIntro() {\r
620         return getWorkbenchConfigurer().getWorkbench().getIntroManager()\r
621                 .hasIntro();\r
622     }\r
623 \r
624     private void refreshFromLocal() {\r
625         String[] commandLineArgs = Platform.getCommandLineArgs();\r
626         IPreferenceStore store = IDEWorkbenchPlugin.getDefault()\r
627                 .getPreferenceStore();\r
628         boolean refresh = store\r
629                 .getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);\r
630         if (!refresh) {\r
631             return;\r
632         }\r
633 \r
634         // Do not refresh if it was already done by core on startup.\r
635         for (int i = 0; i < commandLineArgs.length; i++) {\r
636             if (commandLineArgs[i].equalsIgnoreCase("-refresh")) { //$NON-NLS-1$\r
637                 return;\r
638             }\r
639         }\r
640 \r
641         final IContainer root = ResourcesPlugin.getWorkspace().getRoot();\r
642         Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {\r
643             @Override\r
644             public IStatus runInWorkspace(IProgressMonitor monitor)\r
645                     throws CoreException {\r
646                 root.refreshLocal(IResource.DEPTH_INFINITE, monitor);\r
647                 return Status.OK_STATUS;\r
648             }\r
649         };\r
650         job.setRule(root);\r
651         job.schedule();\r
652     }\r
653 \r
654     private static class CancelableProgressMonitorWrapper extends ProgressMonitorWrapper {\r
655         private double total = 0;\r
656         private ProgressMonitorJobsDialog dialog;\r
657 \r
658         CancelableProgressMonitorWrapper(IProgressMonitor monitor,\r
659                 ProgressMonitorJobsDialog dialog) {\r
660             super(monitor);\r
661             this.dialog = dialog;\r
662         }\r
663 \r
664         /*\r
665          * (non-Javadoc)\r
666          * @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double)\r
667          */\r
668         public void internalWorked(double work) {\r
669             super.internalWorked(work);\r
670             total += work;\r
671             updateProgressDetails();\r
672         }\r
673 \r
674         /*\r
675          * (non-Javadoc)\r
676          * @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int)\r
677          */\r
678         public void worked(int work) {\r
679             super.worked(work);\r
680             total += work;\r
681             updateProgressDetails();\r
682         }\r
683 \r
684         public void beginTask(String name, int totalWork) {\r
685             super.beginTask(name, totalWork);\r
686             subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_preHistoryCompaction);\r
687         }\r
688 \r
689         private void updateProgressDetails() {\r
690             if (!isCanceled() && Math.abs(total - 4.0) < 0.0001 /* right before history compacting */) {\r
691                 subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_cancelHistoryPruning);\r
692                 dialog.setCancelable(true);\r
693             }\r
694             if (Math.abs(total - 5.0) < 0.0001 /* history compacting finished */) {\r
695                 subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_postHistoryCompaction);\r
696                 dialog.setCancelable(false);\r
697             }\r
698         }\r
699     }\r
700 \r
701     private static class CancelableProgressMonitorJobsDialog extends ProgressMonitorJobsDialog {\r
702 \r
703         public CancelableProgressMonitorJobsDialog(Shell parent) {\r
704             super(parent);\r
705         }\r
706 \r
707         /*\r
708          * (non-Javadoc)\r
709          * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDetailsButton(org.eclipse.swt.widgets.Composite)\r
710          */\r
711         protected void createButtonsForButtonBar(Composite parent) {\r
712             super.createButtonsForButtonBar(parent);\r
713             registerCancelButtonListener();\r
714         }\r
715 \r
716         public void registerCancelButtonListener() {\r
717             cancel.addSelectionListener(new SelectionAdapter() {\r
718                 public void widgetSelected(SelectionEvent e) {\r
719                     subTaskLabel.setText(""); //$NON-NLS-1$\r
720                 }\r
721             });\r
722         }\r
723     }\r
724 \r
725 \r
726     final IRunnableWithProgress platformShutdownRunnable = new IRunnableWithProgress() {\r
727         /**\r
728          * @param monitor\r
729          *            the progress monitor to use for reporting progress to the\r
730          *            user, or <code>null</code> indicating that no progress\r
731          *            should be reported and the operation cannot be cancelled.\r
732          */\r
733         @Override\r
734         public void run(IProgressMonitor monitor) {\r
735             SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_PLATFORM_TASK, 100);\r
736             try {\r
737                 try {\r
738                     progress.subTask("Platform");\r
739                     SimanticsPlatform.INSTANCE.shutdown(progress.newChild(50));\r
740                 } catch (PlatformException e) {\r
741                     Activator.logError("Problems encountered while shutting down Simantics platform, see exception for details.", e);\r
742                 }\r
743 \r
744                 progress.subTask("Remaining database connections");\r
745                 SimanticsUI.closeSessions();\r
746                 progress.worked(20);\r
747                 TimedSessionCache.close();\r
748                 progress.worked(20);\r
749 \r
750                 progress.subTask("Thread pools");\r
751                 ThreadUtils.shutdown();\r
752                 progress.worked(5);\r
753 \r
754                 progress.subTask("Clear index status");\r
755                 try {\r
756                     // Everything ok, clear index dirty state.\r
757                     DatabaseIndexing.clearAllDirty();\r
758                 } catch (IOException e) {\r
759                     Activator.logError("Problems encountered while refreshing database index states, see exception for details.", e);\r
760                 }\r
761                 progress.worked(5);\r
762 \r
763                 progress.setWorkRemaining(0);\r
764             } finally {\r
765                 if (monitor != null) {\r
766                     monitor.done();\r
767                 }\r
768             }\r
769         }\r
770     };\r
771 \r
772     /**\r
773      * Disconnect from the workspace and close ProCore sessions.\r
774      */\r
775     private void disconnectFromWorkspace() {\r
776         // save the workspace\r
777         final MultiStatus status = new MultiStatus(\r
778                 IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
779                 IDEWorkbenchMessages.ProblemSavingWorkbench, null);\r
780 \r
781         final ProgressMonitorJobsDialog p = new CancelableProgressMonitorJobsDialog(\r
782                 null);\r
783 \r
784         final boolean applyPolicy = ResourcesPlugin.getWorkspace()\r
785                 .getDescription().isApplyFileStatePolicy();\r
786 \r
787         final IRunnableWithProgress workspaceShutdownRunnable = new IRunnableWithProgress() {\r
788             @Override\r
789             public void run(IProgressMonitor monitor) {\r
790                 try {\r
791                     status.merge(((Workspace) ResourcesPlugin.getWorkspace()).save(true, true, monitor));\r
792                 } catch (CoreException e) {\r
793                     status.merge(e.getStatus());\r
794                 }\r
795             }\r
796         };\r
797 \r
798         IRunnableWithProgress shutdownRunnable = new IRunnableWithProgress() {\r
799             @Override\r
800             public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
801                 if (applyPolicy)\r
802                     monitor = new CancelableProgressMonitorWrapper(\r
803                             monitor, p);\r
804 \r
805                 SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_TASK, 2);\r
806                 try {\r
807                     workspaceShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));\r
808                     platformShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));\r
809                 } finally {\r
810                     monitor.done();\r
811                 }\r
812             }\r
813         };\r
814 \r
815         try {\r
816             new ProgressMonitorJobsDialog(null).run(true, false, shutdownRunnable);\r
817         } catch (InvocationTargetException e) {\r
818             status.merge(new Status(IStatus.ERROR,\r
819                     IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
820                     IDEWorkbenchMessages.InternalError, e.getTargetException()));\r
821         } catch (InterruptedException e) {\r
822             status.merge(new Status(IStatus.ERROR,\r
823                     IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
824                     IDEWorkbenchMessages.InternalError, e));\r
825         }\r
826         ErrorDialog.openError(null,\r
827                 IDEWorkbenchMessages.ProblemsSavingWorkspace, null, status,\r
828                 IStatus.ERROR | IStatus.WARNING);\r
829         if (!status.isOK()) {\r
830             IDEWorkbenchPlugin.log(\r
831                     IDEWorkbenchMessages.ProblemsSavingWorkspace, status);\r
832         }\r
833     }\r
834 \r
835     /*\r
836      * (non-Javadoc)\r
837      *\r
838      * @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput\r
839      */\r
840     @Override\r
841     public IAdaptable getDefaultPageInput() {\r
842         return ResourcesPlugin.getWorkspace().getRoot();\r
843     }\r
844 \r
845     /*\r
846      * (non-Javadoc)\r
847      *\r
848      * @see org.eclipse.ui.application.WorkbenchAdvisor\r
849      */\r
850     @Override\r
851     public String getInitialWindowPerspectiveId() {\r
852         int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;\r
853 \r
854         String perspectiveId = null;\r
855         AboutInfo[] welcomeInfos = getWelcomePerspectiveInfos();\r
856         if (index >= 0 && welcomeInfos != null && index < welcomeInfos.length) {\r
857             perspectiveId = welcomeInfos[index].getWelcomePerspectiveId();\r
858         }\r
859 \r
860         if (perspectiveId == null && args.contains(SimanticsArguments.PERSPECTIVE)) {\r
861             String id = args.get(SimanticsArguments.PERSPECTIVE);\r
862             IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(id);\r
863             if (perspective != null)\r
864                 perspectiveId = id;\r
865         }\r
866 \r
867         if (perspectiveId == null) {\r
868             IProject project = SimanticsUI.peekProject();\r
869             if (project != null)\r
870                 perspectiveId = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);\r
871         }\r
872 \r
873         //System.out.println("Initial perspective: " + perspectiveId);\r
874 \r
875         return perspectiveId;\r
876     }\r
877 \r
878     /**\r
879      * Returns the map of versioned feature ids -> info object for all installed\r
880      * features. The format of the versioned feature id (the key of the map) is\r
881      * featureId + ":" + versionId.\r
882      *\r
883      * @return map of versioned feature ids -> info object (key type:\r
884      *         <code>String</code>, value type: <code>AboutInfo</code>)\r
885      * @since 3.0\r
886      */\r
887     private Map<String, AboutInfo> computeBundleGroupMap() {\r
888         // use tree map to get predicable order\r
889         Map<String, AboutInfo> ids = new TreeMap<String, AboutInfo>();\r
890 \r
891         IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();\r
892         for (int i = 0; i < providers.length; ++i) {\r
893             IBundleGroup[] groups = providers[i].getBundleGroups();\r
894             for (int j = 0; j < groups.length; ++j) {\r
895                 IBundleGroup group = groups[j];\r
896                 AboutInfo info = new AboutInfo(group);\r
897 \r
898                 String version = info.getVersionId();\r
899                 version = version == null ? "0.0.0" //$NON-NLS-1$\r
900                         : new Version(version).toString();\r
901                 String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$\r
902 \r
903                 ids.put(versionedFeature, info);\r
904             }\r
905         }\r
906 \r
907         return ids;\r
908     }\r
909 \r
910     /**\r
911      * Returns the ordered map of versioned feature ids -> AboutInfo that are\r
912      * new for this session.\r
913      *\r
914      * @return ordered map of versioned feature ids (key type:\r
915      *         <code>String</code>) -> infos (value type:\r
916      *         <code>AboutInfo</code>).\r
917      */\r
918     public Map<String, AboutInfo> getNewlyAddedBundleGroups() {\r
919         if (newlyAddedBundleGroups == null) {\r
920             newlyAddedBundleGroups = createNewBundleGroupsMap();\r
921         }\r
922         return newlyAddedBundleGroups;\r
923     }\r
924 \r
925     /**\r
926      * Updates the old features setting and returns a map of new features.\r
927      */\r
928     private Map<String, AboutInfo> createNewBundleGroupsMap() {\r
929         // retrieve list of installed bundle groups from last session\r
930         IDialogSettings settings = IDEWorkbenchPlugin.getDefault()\r
931                 .getDialogSettings();\r
932         String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);\r
933 \r
934         // get a map of currently installed bundle groups and store it for next\r
935         // session\r
936         Map<String, AboutInfo> bundleGroups = computeBundleGroupMap();\r
937         String[] currentFeaturesArray = new String[bundleGroups.size()];\r
938         bundleGroups.keySet().toArray(currentFeaturesArray);\r
939         settings.put(INSTALLED_FEATURES, currentFeaturesArray);\r
940 \r
941         // remove the previously known from the current set\r
942         if (previousFeaturesArray != null) {\r
943             for (int i = 0; i < previousFeaturesArray.length; ++i) {\r
944                 bundleGroups.remove(previousFeaturesArray[i]);\r
945             }\r
946         }\r
947 \r
948         return bundleGroups;\r
949     }\r
950 \r
951     /**\r
952      * Declares all IDE-specific workbench images. This includes both "shared"\r
953      * images (named in {@link IDE.SharedImages}) and internal images (named in\r
954      * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).\r
955      *\r
956      * @see IWorkbenchConfigurer#declareImage\r
957      */\r
958     private void declareWorkbenchImages() {\r
959 \r
960         final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$\r
961         final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; // Enabled //$NON-NLS-1$\r
962 \r
963         // toolbar\r
964         // icons.\r
965         final String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; // Disabled //$NON-NLS-1$\r
966         // //$NON-NLS-1$\r
967         // toolbar\r
968         // icons.\r
969         final String PATH_ETOOL = ICONS_PATH + "etool16/"; // Enabled toolbar //$NON-NLS-1$\r
970         // //$NON-NLS-1$\r
971         // icons.\r
972         final String PATH_DTOOL = ICONS_PATH + "dtool16/"; // Disabled toolbar //$NON-NLS-1$\r
973         // //$NON-NLS-1$\r
974         // icons.\r
975         final String PATH_OBJECT = ICONS_PATH + "obj16/"; // Model object //$NON-NLS-1$\r
976         // //$NON-NLS-1$\r
977         // icons\r
978         final String PATH_WIZBAN = ICONS_PATH + "wizban/"; // Wizard //$NON-NLS-1$\r
979         // //$NON-NLS-1$\r
980         // icons\r
981 \r
982         Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);\r
983 \r
984         declareWorkbenchImage(ideBundle,\r
985                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL\r
986                 + "build_exec.gif", false); //$NON-NLS-1$\r
987         declareWorkbenchImage(ideBundle,\r
988                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,\r
989                 PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$\r
990         declareWorkbenchImage(ideBundle,\r
991                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,\r
992                 PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$\r
993 \r
994         declareWorkbenchImage(ideBundle,\r
995                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL\r
996                 + "search_src.gif", false); //$NON-NLS-1$\r
997         declareWorkbenchImage(ideBundle,\r
998                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,\r
999                 PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$\r
1000         declareWorkbenchImage(ideBundle,\r
1001                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,\r
1002                 PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$\r
1003 \r
1004         declareWorkbenchImage(ideBundle,\r
1005                 IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL\r
1006                 + "next_nav.gif", false); //$NON-NLS-1$\r
1007 \r
1008         declareWorkbenchImage(ideBundle,\r
1009                 IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL\r
1010                 + "prev_nav.gif", false); //$NON-NLS-1$\r
1011 \r
1012         declareWorkbenchImage(ideBundle,\r
1013                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN\r
1014                 + "newprj_wiz.png", false); //$NON-NLS-1$\r
1015         declareWorkbenchImage(ideBundle,\r
1016                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,\r
1017                 PATH_WIZBAN + "newfolder_wiz.png", false); //$NON-NLS-1$\r
1018         declareWorkbenchImage(ideBundle,\r
1019                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN\r
1020                 + "newfile_wiz.png", false); //$NON-NLS-1$\r
1021 \r
1022         declareWorkbenchImage(ideBundle,\r
1023                 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,\r
1024                 PATH_WIZBAN + "importdir_wiz.png", false); //$NON-NLS-1$\r
1025         declareWorkbenchImage(ideBundle,\r
1026                 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,\r
1027                 PATH_WIZBAN + "importzip_wiz.png", false); //$NON-NLS-1$\r
1028 \r
1029         declareWorkbenchImage(ideBundle,\r
1030                 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,\r
1031                 PATH_WIZBAN + "exportdir_wiz.png", false); //$NON-NLS-1$\r
1032         declareWorkbenchImage(ideBundle,\r
1033                 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,\r
1034                 PATH_WIZBAN + "exportzip_wiz.png", false); //$NON-NLS-1$\r
1035 \r
1036         declareWorkbenchImage(ideBundle,\r
1037                 IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,\r
1038                 PATH_WIZBAN + "workset_wiz.png", false); //$NON-NLS-1$\r
1039 \r
1040         declareWorkbenchImage(ideBundle,\r
1041                 IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG, PATH_WIZBAN\r
1042                 + "saveas_wiz.png", false); //$NON-NLS-1$\r
1043 \r
1044         declareWorkbenchImage(ideBundle,\r
1045                 IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG, PATH_WIZBAN\r
1046                 + "quick_fix.png", false); //$NON-NLS-1$\r
1047 \r
1048         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,\r
1049                 PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$\r
1050         declareWorkbenchImage(ideBundle,\r
1051                 IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT\r
1052                 + "cprj_obj.gif", true); //$NON-NLS-1$\r
1053         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,\r
1054                 PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$\r
1055 \r
1056         declareWorkbenchImage(ideBundle,\r
1057                 IDEInternalWorkbenchImages.IMG_ELCL_QUICK_FIX_ENABLED,\r
1058                 PATH_ELOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$\r
1059 \r
1060         declareWorkbenchImage(ideBundle,\r
1061                 IDEInternalWorkbenchImages.IMG_DLCL_QUICK_FIX_DISABLED,\r
1062                 PATH_DLOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$\r
1063 \r
1064         // task objects\r
1065         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK,\r
1066         // PATH_OBJECT+"hprio_tsk.gif");\r
1067         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK,\r
1068         // PATH_OBJECT+"mprio_tsk.gif");\r
1069         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK,\r
1070         // PATH_OBJECT+"lprio_tsk.gif");\r
1071 \r
1072         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,\r
1073                 PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$\r
1074         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,\r
1075                 PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$\r
1076 \r
1077         declareWorkbenchImage(ideBundle,\r
1078                 IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT\r
1079                 + "complete_tsk.gif", true); //$NON-NLS-1$\r
1080         declareWorkbenchImage(ideBundle,\r
1081                 IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT\r
1082                 + "incomplete_tsk.gif", true); //$NON-NLS-1$\r
1083         declareWorkbenchImage(ideBundle,\r
1084                 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT\r
1085                 + "welcome_item.gif", true); //$NON-NLS-1$\r
1086         declareWorkbenchImage(ideBundle,\r
1087                 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT\r
1088                 + "welcome_banner.gif", true); //$NON-NLS-1$\r
1089         declareWorkbenchImage(ideBundle,\r
1090                 IDEInternalWorkbenchImages.IMG_OBJS_ERROR_PATH, PATH_OBJECT\r
1091                 + "error_tsk.gif", true); //$NON-NLS-1$\r
1092         declareWorkbenchImage(ideBundle,\r
1093                 IDEInternalWorkbenchImages.IMG_OBJS_WARNING_PATH, PATH_OBJECT\r
1094                 + "warn_tsk.gif", true); //$NON-NLS-1$\r
1095         declareWorkbenchImage(ideBundle,\r
1096                 IDEInternalWorkbenchImages.IMG_OBJS_INFO_PATH, PATH_OBJECT\r
1097                 + "info_tsk.gif", true); //$NON-NLS-1$\r
1098 \r
1099         declareWorkbenchImage(ideBundle,\r
1100                 IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL\r
1101                 + "flatLayout.gif", true); //$NON-NLS-1$\r
1102         declareWorkbenchImage(ideBundle,\r
1103                 IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT,\r
1104                 PATH_ELOCALTOOL + "hierarchicalLayout.gif", true); //$NON-NLS-1$\r
1105         declareWorkbenchImage(ideBundle,\r
1106                 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY,\r
1107                 PATH_ETOOL + "problem_category.gif", true); //$NON-NLS-1$\r
1108         /*\r
1109         declareWorkbenchImage(ideBundle,\r
1110                 IDEInternalWorkbenchImages.IMG_LCL_LINKTO_HELP, PATH_ELOCALTOOL\r
1111                         + "linkto_help.gif", false); //$NON-NLS-1$\r
1112          */\r
1113 \r
1114         // synchronization indicator objects\r
1115         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT,\r
1116         // PATH_OVERLAY+"wbet_stat.gif");\r
1117         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT,\r
1118         // PATH_OVERLAY+"sbet_stat.gif");\r
1119         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT,\r
1120         // PATH_OVERLAY+"conflict_stat.gif");\r
1121 \r
1122         // content locality indicator objects\r
1123         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT,\r
1124         // PATH_STAT+"notlocal_stat.gif");\r
1125         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT,\r
1126         // PATH_STAT+"local_stat.gif");\r
1127         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT,\r
1128         // PATH_STAT+"filllocal_stat.gif");\r
1129     }\r
1130 \r
1131     /**\r
1132      * Declares an IDE-specific workbench image.\r
1133      *\r
1134      * @param symbolicName\r
1135      *            the symbolic name of the image\r
1136      * @param path\r
1137      *            the path of the image file; this path is relative to the base\r
1138      *            of the IDE plug-in\r
1139      * @param shared\r
1140      *            <code>true</code> if this is a shared image, and\r
1141      *            <code>false</code> if this is not a shared image\r
1142      * @see IWorkbenchConfigurer#declareImage\r
1143      */\r
1144     private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,\r
1145             String path, boolean shared) {\r
1146         URL url = FileLocator.find(ideBundle, new Path(path), null);\r
1147         ImageDescriptor desc = ImageDescriptor.createFromURL(url);\r
1148         getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);\r
1149     }\r
1150 \r
1151     /*\r
1152      * (non-Javadoc)\r
1153      *\r
1154      * @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId\r
1155      */\r
1156     @Override\r
1157     public String getMainPreferencePageId() {\r
1158         // indicate that we want the Workench preference page to be prominent\r
1159         return WORKBENCH_PREFERENCE_CATEGORY_ID;\r
1160     }\r
1161 \r
1162     /**\r
1163      * @return the workspace location string, or <code>null</code> if the\r
1164      *         location is not being shown\r
1165      */\r
1166     public String getWorkspaceLocation() {\r
1167                 // read command line, which has priority\r
1168                 IEclipseContext context = getWorkbenchConfigurer().getWorkbench().getService(IEclipseContext.class);\r
1169                 String location = context != null ? (String) context.get(E4Workbench.FORCED_SHOW_LOCATION) : null;\r
1170                 if (location != null) {\r
1171                         return location;\r
1172                 }\r
1173                 // read the preference\r
1174                 if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(IDEInternalPreferences.SHOW_LOCATION)) {\r
1175                         return Platform.getLocation().toOSString();\r
1176                 }\r
1177                 return null;\r
1178     }\r
1179 \r
1180     /**\r
1181      * @return the welcome perspective infos, or <code>null</code> if none or\r
1182      *         if they should be ignored due to the new intro being present\r
1183      */\r
1184     public AboutInfo[] getWelcomePerspectiveInfos() {\r
1185         if (welcomePerspectiveInfos == null) {\r
1186             // support old welcome perspectives if intro plugin is not present\r
1187             if (!hasIntro()) {\r
1188                 Map<String, AboutInfo> m = getNewlyAddedBundleGroups();\r
1189                 ArrayList<AboutInfo> list = new ArrayList<AboutInfo>(m.size());\r
1190                 for (Iterator<AboutInfo> i = m.values().iterator(); i.hasNext();) {\r
1191                     AboutInfo info = i.next();\r
1192                     if (info != null && info.getWelcomePerspectiveId() != null\r
1193                             && info.getWelcomePageURL() != null) {\r
1194                         list.add(info);\r
1195                     }\r
1196                 }\r
1197                 welcomePerspectiveInfos = new AboutInfo[list.size()];\r
1198                 list.toArray(welcomePerspectiveInfos);\r
1199             }\r
1200         }\r
1201         return welcomePerspectiveInfos;\r
1202     }\r
1203 \r
1204     /*\r
1205      * (non-Javadoc)\r
1206      *\r
1207      * @see org.eclipse.ui.application.WorkbenchAdvisor#getWorkbenchErrorHandler()\r
1208      */\r
1209     @Override\r
1210     public AbstractStatusHandler getWorkbenchErrorHandler() {\r
1211         if (ideWorkbenchErrorHandler == null) {\r
1212             ideWorkbenchErrorHandler = new IDEWorkbenchErrorHandler(\r
1213                     getWorkbenchConfigurer());\r
1214         }\r
1215         return ideWorkbenchErrorHandler;\r
1216     }\r
1217 \r
1218     /* (non-Javadoc)\r
1219      * @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopIdle(org.eclipse.swt.widgets.Display)\r
1220      */\r
1221     @Override\r
1222     public void eventLoopIdle(Display display) {\r
1223         if (delayedEventsProcessor != null)\r
1224             delayedEventsProcessor.catchUp(display);\r
1225         super.eventLoopIdle(display);\r
1226     }\r
1227 \r
1228 }\r