1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.workbench.internal;
14 import java.io.IOException;
15 import java.lang.reflect.InvocationTargetException;
17 import java.text.Collator;
18 import java.util.ArrayList;
19 import java.util.Iterator;
21 import java.util.TreeMap;
23 import org.eclipse.core.internal.resources.Workspace;
24 import org.eclipse.core.net.proxy.IProxyService;
25 import org.eclipse.core.resources.IContainer;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.resources.WorkspaceJob;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.FileLocator;
31 import org.eclipse.core.runtime.IAdaptable;
32 import org.eclipse.core.runtime.IBundleGroup;
33 import org.eclipse.core.runtime.IBundleGroupProvider;
34 import org.eclipse.core.runtime.ILog;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.MultiStatus;
38 import org.eclipse.core.runtime.Path;
39 import org.eclipse.core.runtime.Platform;
40 import org.eclipse.core.runtime.ProgressMonitorWrapper;
41 import org.eclipse.core.runtime.Status;
42 import org.eclipse.core.runtime.SubMonitor;
43 import org.eclipse.core.runtime.jobs.Job;
44 import org.eclipse.e4.core.contexts.IEclipseContext;
45 import org.eclipse.e4.ui.internal.workbench.E4Workbench;
46 import org.eclipse.jface.dialogs.ErrorDialog;
47 import org.eclipse.jface.dialogs.IDialogSettings;
48 import org.eclipse.jface.dialogs.MessageDialog;
49 import org.eclipse.jface.dialogs.TrayDialog;
50 import org.eclipse.jface.operation.IRunnableWithProgress;
51 import org.eclipse.jface.preference.IPreferenceStore;
52 import org.eclipse.jface.resource.ImageDescriptor;
53 import org.eclipse.jface.util.Policy;
54 import org.eclipse.jface.window.Window;
55 import org.eclipse.swt.SWT;
56 import org.eclipse.swt.events.SelectionAdapter;
57 import org.eclipse.swt.events.SelectionEvent;
58 import org.eclipse.swt.widgets.Composite;
59 import org.eclipse.swt.widgets.Display;
60 import org.eclipse.swt.widgets.Event;
61 import org.eclipse.swt.widgets.Listener;
62 import org.eclipse.swt.widgets.Shell;
63 import org.eclipse.ui.IPerspectiveDescriptor;
64 import org.eclipse.ui.PlatformUI;
65 import org.eclipse.ui.application.IWorkbenchConfigurer;
66 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
67 import org.eclipse.ui.application.WorkbenchAdvisor;
68 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
69 import org.eclipse.ui.ide.IDE;
70 import org.eclipse.ui.internal.ISelectionConversionService;
71 import org.eclipse.ui.internal.Workbench;
72 import org.eclipse.ui.internal.ide.AboutInfo;
73 import org.eclipse.ui.internal.ide.IDEInternalPreferences;
74 import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
75 import org.eclipse.ui.internal.ide.IDESelectionConversionService;
76 import org.eclipse.ui.internal.ide.IDEWorkbenchActivityHelper;
77 import org.eclipse.ui.internal.ide.IDEWorkbenchErrorHandler;
78 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
79 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
80 import org.eclipse.ui.internal.ide.undo.WorkspaceUndoMonitor;
81 import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
82 import org.eclipse.ui.keys.IBindingService;
83 import org.eclipse.ui.progress.IProgressService;
84 import org.eclipse.ui.statushandlers.AbstractStatusHandler;
85 import org.osgi.framework.Bundle;
86 import org.osgi.framework.ServiceReference;
87 import org.osgi.framework.Version;
88 import org.simantics.CancelStartupException;
89 import org.simantics.PlatformException;
90 import org.simantics.Simantics;
91 import org.simantics.SimanticsPlatform;
92 import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;
93 import org.simantics.SimanticsPlatform.RecoveryPolicy;
94 import org.simantics.application.arguments.IArguments;
95 import org.simantics.application.arguments.SimanticsArguments;
96 import org.simantics.db.common.Indexing;
97 import org.simantics.db.indexing.DatabaseIndexing;
98 import org.simantics.db.procore.server.environment.RebootRequiredException;
99 import org.simantics.db.procore.server.environment.windows.Product;
100 import org.simantics.internal.TimedSessionCache;
101 import org.simantics.project.IProject;
102 import org.simantics.project.ProjectKeys;
103 import org.simantics.ui.SimanticsUI;
104 import org.simantics.ui.jobs.SessionGarbageCollectorJob;
105 import org.simantics.ui.workbench.PerspectiveBarsActivator;
106 import org.simantics.ui.workbench.PerspectiveContextActivator;
107 import org.simantics.utils.logging.TimeLogger;
108 import org.simantics.utils.threads.ExecutorWorker;
109 import org.simantics.utils.threads.ThreadUtils;
110 import org.simantics.utils.ui.dialogs.ShowError;
111 import org.simantics.utils.ui.dialogs.ShowMessage;
112 import org.slf4j.Logger;
113 import org.slf4j.LoggerFactory;
117 * @author Tuukka Lehtonen
119 public class SimanticsWorkbenchAdvisor extends WorkbenchAdvisor {
121 private static final Logger LOGGER = LoggerFactory.getLogger(SimanticsWorkbenchAdvisor.class);
123 private static final boolean PROFILE_PLATFORM_STARTUP = false;
125 private static final String SHUT_DOWN_TASK = "Shutting down...";
127 private static final String SHUT_DOWN_PLATFORM_TASK = "Shutting down platform...";
129 private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$
132 * The dialog setting key to access the known installed features since the
133 * last time the workbench was run.
135 private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$
138 * The arguments received by the application.
140 protected final IArguments args;
142 protected final boolean restoredPreviousSession = false;
145 * Only true while opening the initial windows during {@link #openWindows()}.
146 * Used by {@link SimanticsWorkbenchWindowAdvisor#postWindowOpen()} to
147 * recognize when to skip all one-time initialization.
149 protected boolean workbenchWindowsInitialized = false;
152 * Whether or not to save unsaved database changes before exiting the
155 protected boolean saveAtExit = false;
158 * Ordered map of versioned feature ids -> info that are new for this
159 * session; <code>null</code> if uninitialized. Key type:
160 * <code>String</code>, Value type: <code>AboutInfo</code>.
162 private Map<String, AboutInfo> newlyAddedBundleGroups;
165 * Array of <code>AboutInfo</code> for all new installed features that
166 * specify a welcome perspective.
168 private AboutInfo[] welcomePerspectiveInfos = null;
171 * Helper for managing activites in response to workspace changes.
173 private IDEWorkbenchActivityHelper activityHelper = null;
176 * Helper for managing work that is performed when the system is otherwise
179 private IDEIdleHelper idleHelper;
181 private Listener settingsChangeListener;
184 * Support class for monitoring workspace changes and periodically
185 * validating the undo history
187 private WorkspaceUndoMonitor workspaceUndoMonitor;
190 * The IDE workbench error handler.
192 private AbstractStatusHandler ideWorkbenchErrorHandler;
195 * Helper class used to process delayed events.
197 private DelayedEventsProcessor delayedEventsProcessor;
200 * Creates a new workbench advisor instance.
203 public SimanticsWorkbenchAdvisor(IArguments args, DelayedEventsProcessor processor) {
206 this.delayedEventsProcessor = processor;
208 Listener closeListener = new Listener() {
209 public void handleEvent(Event event) {
210 boolean doExit = SimanticsWorkbenchWindowAdvisor.promptOnExit(null);
213 event.type = SWT.None;
216 Display.getDefault().addListener(SWT.Close, closeListener);
219 public IArguments getArguments() {
223 public boolean workbenchInitialized() {
224 return workbenchWindowsInitialized;
227 public boolean restoredPreviousSession() {
228 return restoredPreviousSession;
231 boolean saveAtExit() {
235 void setSaveAtExit(boolean saveAtExit) {
236 this.saveAtExit = saveAtExit;
242 * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize
245 public void initialize(IWorkbenchConfigurer configurer) {
246 // By default, we always save and restore the workbench state.
247 configurer.setSaveAndRestore(true);
249 checkWorkspaceDatabaseIndexes();
251 // Start tracking the active perspective to activate contexts based on it.
252 new PerspectiveContextActivator();
253 new PerspectiveBarsActivator();
255 // register workspace adapters
256 IDE.registerAdapters();
258 // register shared images
259 declareWorkbenchImages();
261 // initialize the activity helper
262 activityHelper = IDEWorkbenchActivityHelper.getInstance();
264 // initialize idle handler
265 idleHelper = new IDEIdleHelper(configurer);
267 // initialize the workspace undo monitor
268 workspaceUndoMonitor = WorkspaceUndoMonitor.getInstance();
270 // show Help button in JFace dialogs
271 TrayDialog.setDialogHelpAvailable(true);
273 Policy.setComparator(Collator.getInstance());
276 private void checkWorkspaceDatabaseIndexes() {
278 DatabaseIndexing.validateIndexes();
279 } catch (IOException e) {
280 Activator.logError("Problems encountered while checking database indexes, see exception for details.", e);
284 public WorkbenchWindowAdvisor createWorkbenchWindowAdvisorClass(SimanticsWorkbenchAdvisor advisor, IWorkbenchWindowConfigurer configurer) {
285 return new SimanticsWorkbenchWindowAdvisor(this, configurer);
289 public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
290 // Attach database session watchdog.
291 new SessionWatchdog().attach( Simantics.getSessionContextProvider() );
293 return createWorkbenchWindowAdvisorClass(this, configurer);
297 * For gaining direct access to super.openWindows() in implementations
298 * inheriting this one.
300 public boolean openWindowsSuper() {
301 return super.openWindows();
305 * Sadly we do not know why key bindings are lost and why this helps. But it
306 * does. Visiting the <code>Keys</code> preference page and pressing OK uses
307 * this the same call and it seems to salvage the bindings that have been in
308 * some cases destroyed by <code>BindingToModelProcessor</code>.
312 * https://techblog.ralph-schuster.eu/2013/10/13/eclipsee4-problem-with-key-bindings/comment-page-1/
313 * https://www.eclipse.org/forums/index.php/t/550175/
314 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=461037
316 * @see platform issue #6353
318 private void fixBindings() {
320 IBindingService bs = PlatformUI.getWorkbench().getAdapter(IBindingService.class);
321 bs.savePreferences(bs.getActiveScheme(), bs.getBindings());
322 } catch (IOException e) {
323 Activator.logError(getClass().getSimpleName() + ".fixBindings failed", e);
328 public boolean openWindows() {
329 boolean platformOk = startPlatform();
330 LOGGER.info("startPlatform finished");
331 TimeLogger.log("SimanticsWorkbenchAdvisor.startPlatform finished");
334 // At this point workbenchConfigurer.getSaveAndRestore()
335 // returns false iff something has gone terribly wrong
336 // before this. Currently saveAndRestore is always true.
337 boolean windowsOpened = super.openWindows();
338 TimeLogger.log("Opened windows");
340 workbenchWindowsInitialized = true;
342 // Start the database garbage collector after a short while.
343 SessionGarbageCollectorJob.getInstance().scheduleAfterQuietTime();
345 // Discard database session undo history at this point to prevent
346 // the user from undoing any initialization operations performed
347 // by the platform startup.
348 SimanticsPlatform.INSTANCE.discardSessionUndoHistory();
349 TimeLogger.log("Discarded session undo history");
351 // #6353: Workaround for
358 // Make sure platform shutdown is ran if window opening fails.
360 platformShutdownRunnable.run(null);
361 } catch (InvocationTargetException e) {
362 Activator.logError(getClass().getSimpleName() + ".openWindows failed", e.getCause());
363 } catch (InterruptedException e) {
364 Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);
369 protected boolean startPlatform() {
370 // Verify selected perspective
371 if (args.contains(SimanticsArguments.PERSPECTIVE)) {
372 String perspectiveId = args.get(SimanticsArguments.PERSPECTIVE);
373 IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
374 if (perspective == null) {
375 StringBuilder msg = new StringBuilder();
376 msg.append("Requested perspective not found: '" + perspectiveId + "'\n");
377 msg.append("Valid alternatives are:\n");
378 for (IPerspectiveDescriptor pd : PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives()) {
379 msg.append(" " + pd.getId() + "\n");
382 ShowMessage.syncShowError("Invalid Perspective", msg.toString());
387 ILog log = Platform.getLog(Activator.getDefault().getBundle());
392 // Create Simantics Platform Helper.
394 // If Simantics is started from Eclipse IDE or with -fixerrors option,
395 // there is an attempt to fix errors.
397 // On ontology mismatch, there is an attempt to merge new ontology to the
398 // existing database. With -reinstall, the database is cleaned and
403 RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;
404 OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;
406 if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {
407 workspacePolicy = RecoveryPolicy.FixError;
408 ontologyPolicy = OntologyRecoveryPolicy.Merge;
411 boolean requireSynchronize = true;
413 if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
414 ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
417 if (args.contains(SimanticsArguments.DO_NOT_SYNCHRONIZE_ONTOLOGIES)) {
418 requireSynchronize = false;
421 if (args.contains(SimanticsArguments.DISABLE_INDEX)) {
422 Indexing.setDefaultDependenciesIndexingEnabled(false);
425 if (args.contains(SimanticsArguments.SERVER)) {
426 String serverAddress = args.get(SimanticsArguments.SERVER);
427 throw new PlatformException("Argument not supported: " + SimanticsArguments.SERVER + " " + serverAddress);
430 String databaseDriverId = Simantics.getDefaultDatabaseDriver();
431 if (args.contains(SimanticsArguments.DATABASE_ID)) {
432 databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);
433 Simantics.setDefaultDatabaseDriver(databaseDriverId);
436 IProgressMonitor mon = null;
437 if (PROFILE_PLATFORM_STARTUP)
438 mon = new TimingProgressMonitor();
439 SimanticsPlatform.INSTANCE.startUp(databaseDriverId, mon, workspacePolicy, ontologyPolicy, requireSynchronize, new JFaceUserAgent());
441 // Make sure that the default perspective comes from the project if
442 // the project has set ProjectKeys#DEFAULT_PERSPECTIVE.
443 // This might go wrong if project features interact with
444 // PerspectiveRegistry while configuring themselves, since that will
445 // cause an invocation to #getInitialWindowPerspectiveId() while
446 // the project has not yet been properly initialized.
447 getWorkbenchConfigurer().getWorkbench().getPerspectiveRegistry().setDefaultPerspective(getInitialWindowPerspectiveId());
448 TimeLogger.log("Completed setting default perspective");
451 } catch (CancelStartupException e) {
453 } catch (PlatformException e) {
454 boolean hasStackTrace = e.getStackTrace().length > 0;
456 while (ee.getCause() != null) {
458 hasStackTrace = ee.getStackTrace().length > 0;
461 log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), hasStackTrace ? e : null));
463 new ShowError("Platform Initialization Failed", "Simantics Platform initialization failed:\n\n" + e.getMessage(), e, true);
465 StringBuilder sb = new StringBuilder(256);
466 sb.append(e.getMessage());
467 for (Throwable c=e.getCause(); null != c && null != c.getMessage(); c=c.getCause())
468 sb.append("\ncause: ").append(c.getMessage());
469 new ShowError("Startup Failed", sb.toString(), (Exception) null, true);
473 } catch (Exception e) {
474 log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
476 Throwable cause = e.getCause();
477 if (cause instanceof RebootRequiredException) {
478 RebootRequiredException rre = (RebootRequiredException) cause;
479 StringBuilder msg = new StringBuilder();
480 msg.append("The application must be restarted after installing the following products:\n");
481 for (Product product : rre.products)
482 msg.append("\t" + product + "\n");
483 msg.append("\nThe application will now close.");
484 MessageDialog.openInformation(null, "Restart Required", msg.toString());
486 new ShowError("Platform Startup Failed", "Simantics Platform startup failed:\n\n" + e.getMessage(), e, true);
496 * @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()
499 public void preStartup() {
501 // Suspend background jobs while we startup
502 Job.getJobManager().suspend();
504 // Register the build actions
505 IProgressService service = PlatformUI.getWorkbench()
506 .getProgressService();
507 ImageDescriptor newImage = IDEInternalWorkbenchImages
508 .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
509 service.registerIconForFamily(newImage,
510 ResourcesPlugin.FAMILY_MANUAL_BUILD);
511 service.registerIconForFamily(newImage,
512 ResourcesPlugin.FAMILY_AUTO_BUILD);
518 * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
521 public void postStartup() {
524 activateProxyService();
525 ((Workbench) PlatformUI.getWorkbench()).registerService(
526 ISelectionConversionService.class,
527 new IDESelectionConversionService());
529 initializeSettingsChangeListener();
530 Display.getCurrent().addListener(SWT.Settings,
531 settingsChangeListener);
532 } finally {// Resume background jobs after we startup
533 Job.getJobManager().resume();
538 * Activate the proxy service by obtaining it.
540 private void activateProxyService() {
541 Bundle bundle = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$
542 Object proxyService = null;
543 if (bundle != null) {
544 ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(IProxyService.class.getName());
546 proxyService = bundle.getBundleContext().getService(ref);
548 if (proxyService == null) {
549 IDEWorkbenchPlugin.log("Proxy service could not be found."); //$NON-NLS-1$
554 * Initialize the listener for settings changes.
556 private void initializeSettingsChangeListener() {
557 settingsChangeListener = new Listener() {
559 boolean currentHighContrast = Display.getCurrent()
563 public void handleEvent(org.eclipse.swt.widgets.Event event) {
564 if (Display.getCurrent().getHighContrast() == currentHighContrast)
567 currentHighContrast = !currentHighContrast;
569 // make sure they really want to do this
570 if (new MessageDialog(null,
571 IDEWorkbenchMessages.SystemSettingsChange_title, null,
572 IDEWorkbenchMessages.SystemSettingsChange_message,
573 MessageDialog.QUESTION, new String[] {
574 IDEWorkbenchMessages.SystemSettingsChange_yes,
575 IDEWorkbenchMessages.SystemSettingsChange_no },
576 1).open() == Window.OK) {
577 PlatformUI.getWorkbench().restart();
587 * @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown
590 public void postShutdown() {
591 if (activityHelper != null) {
592 activityHelper.shutdown();
593 activityHelper = null;
595 if (idleHelper != null) {
596 idleHelper.shutdown();
599 if (workspaceUndoMonitor != null) {
600 workspaceUndoMonitor.shutdown();
601 workspaceUndoMonitor = null;
603 if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {
604 disconnectFromWorkspace();
611 * @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()
614 public boolean preShutdown() {
615 Display.getCurrent().removeListener(SWT.Settings,
616 settingsChangeListener);
617 return super.preShutdown();
621 * Return true if the intro plugin is present and false otherwise.
625 public boolean hasIntro() {
626 return getWorkbenchConfigurer().getWorkbench().getIntroManager()
630 private void refreshFromLocal() {
631 String[] commandLineArgs = Platform.getCommandLineArgs();
632 IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
633 .getPreferenceStore();
634 boolean refresh = store
635 .getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);
640 // Do not refresh if it was already done by core on startup.
641 for (int i = 0; i < commandLineArgs.length; i++) {
642 if (commandLineArgs[i].equalsIgnoreCase("-refresh")) { //$NON-NLS-1$
647 final IContainer root = ResourcesPlugin.getWorkspace().getRoot();
648 Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {
650 public IStatus runInWorkspace(IProgressMonitor monitor)
651 throws CoreException {
652 root.refreshLocal(IResource.DEPTH_INFINITE, monitor);
653 return Status.OK_STATUS;
660 private static class CancelableProgressMonitorWrapper extends ProgressMonitorWrapper {
661 private double total = 0;
662 private ProgressMonitorJobsDialog dialog;
664 CancelableProgressMonitorWrapper(IProgressMonitor monitor,
665 ProgressMonitorJobsDialog dialog) {
667 this.dialog = dialog;
672 * @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double)
674 public void internalWorked(double work) {
675 super.internalWorked(work);
677 updateProgressDetails();
682 * @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int)
684 public void worked(int work) {
687 updateProgressDetails();
690 public void beginTask(String name, int totalWork) {
691 super.beginTask(name, totalWork);
692 subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_preHistoryCompaction);
695 private void updateProgressDetails() {
696 if (!isCanceled() && Math.abs(total - 4.0) < 0.0001 /* right before history compacting */) {
697 subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_cancelHistoryPruning);
698 dialog.setCancelable(true);
700 if (Math.abs(total - 5.0) < 0.0001 /* history compacting finished */) {
701 subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_postHistoryCompaction);
702 dialog.setCancelable(false);
707 private static class CancelableProgressMonitorJobsDialog extends ProgressMonitorJobsDialog {
709 public CancelableProgressMonitorJobsDialog(Shell parent) {
715 * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDetailsButton(org.eclipse.swt.widgets.Composite)
717 protected void createButtonsForButtonBar(Composite parent) {
718 super.createButtonsForButtonBar(parent);
719 registerCancelButtonListener();
722 public void registerCancelButtonListener() {
723 cancel.addSelectionListener(new SelectionAdapter() {
724 public void widgetSelected(SelectionEvent e) {
725 subTaskLabel.setText(""); //$NON-NLS-1$
732 final IRunnableWithProgress platformShutdownRunnable = new IRunnableWithProgress() {
735 * the progress monitor to use for reporting progress to the
736 * user, or <code>null</code> indicating that no progress
737 * should be reported and the operation cannot be cancelled.
740 public void run(IProgressMonitor monitor) {
741 SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_PLATFORM_TASK, 100);
744 progress.subTask("Platform");
745 SimanticsPlatform.INSTANCE.shutdown(progress.newChild(50));
746 } catch (PlatformException e) {
747 Activator.logError("Problems encountered while shutting down Simantics platform, see exception for details.", e);
750 progress.subTask("Remaining database connections");
751 SimanticsUI.closeSessions();
753 TimedSessionCache.close();
756 progress.subTask("Thread pools");
757 ThreadUtils.shutdown();
758 ExecutorWorker.shutdown();
761 progress.subTask("Clear index status");
763 // Everything ok, clear index dirty state.
764 DatabaseIndexing.clearAllDirty();
765 } catch (IOException e) {
766 Activator.logError("Problems encountered while refreshing database index states, see exception for details.", e);
770 progress.setWorkRemaining(0);
772 if (monitor != null) {
780 * Disconnect from the workspace and close ProCore sessions.
782 private void disconnectFromWorkspace() {
783 // save the workspace
784 final MultiStatus status = new MultiStatus(
785 IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
786 IDEWorkbenchMessages.ProblemSavingWorkbench, null);
788 final ProgressMonitorJobsDialog p = new CancelableProgressMonitorJobsDialog(
791 final boolean applyPolicy = ResourcesPlugin.getWorkspace()
792 .getDescription().isApplyFileStatePolicy();
794 final IRunnableWithProgress workspaceShutdownRunnable = new IRunnableWithProgress() {
796 public void run(IProgressMonitor monitor) {
798 status.merge(((Workspace) ResourcesPlugin.getWorkspace()).save(true, true, monitor));
799 } catch (CoreException e) {
800 status.merge(e.getStatus());
805 IRunnableWithProgress shutdownRunnable = new IRunnableWithProgress() {
807 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
809 monitor = new CancelableProgressMonitorWrapper(
812 SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_TASK, 2);
814 workspaceShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));
815 platformShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));
823 new ProgressMonitorJobsDialog(null).run(true, false, shutdownRunnable);
824 } catch (InvocationTargetException e) {
825 status.merge(new Status(IStatus.ERROR,
826 IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
827 IDEWorkbenchMessages.InternalError, e.getTargetException()));
828 } catch (InterruptedException e) {
829 status.merge(new Status(IStatus.ERROR,
830 IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
831 IDEWorkbenchMessages.InternalError, e));
833 ErrorDialog.openError(null,
834 IDEWorkbenchMessages.ProblemsSavingWorkspace, null, status,
835 IStatus.ERROR | IStatus.WARNING);
836 if (!status.isOK()) {
837 IDEWorkbenchPlugin.log(
838 IDEWorkbenchMessages.ProblemsSavingWorkspace, status);
845 * @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput
848 public IAdaptable getDefaultPageInput() {
849 return ResourcesPlugin.getWorkspace().getRoot();
855 * @see org.eclipse.ui.application.WorkbenchAdvisor
858 public String getInitialWindowPerspectiveId() {
859 int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;
861 String perspectiveId = null;
862 AboutInfo[] welcomeInfos = getWelcomePerspectiveInfos();
863 if (index >= 0 && welcomeInfos != null && index < welcomeInfos.length) {
864 perspectiveId = welcomeInfos[index].getWelcomePerspectiveId();
867 if (perspectiveId == null && args.contains(SimanticsArguments.PERSPECTIVE)) {
868 String id = args.get(SimanticsArguments.PERSPECTIVE);
869 IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(id);
870 if (perspective != null)
874 if (perspectiveId == null) {
875 IProject project = SimanticsUI.peekProject();
877 perspectiveId = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);
880 //System.out.println("Initial perspective: " + perspectiveId);
882 return perspectiveId;
886 * Returns the map of versioned feature ids -> info object for all installed
887 * features. The format of the versioned feature id (the key of the map) is
888 * featureId + ":" + versionId.
890 * @return map of versioned feature ids -> info object (key type:
891 * <code>String</code>, value type: <code>AboutInfo</code>)
894 private Map<String, AboutInfo> computeBundleGroupMap() {
895 // use tree map to get predicable order
896 Map<String, AboutInfo> ids = new TreeMap<String, AboutInfo>();
898 IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
899 for (int i = 0; i < providers.length; ++i) {
900 IBundleGroup[] groups = providers[i].getBundleGroups();
901 for (int j = 0; j < groups.length; ++j) {
902 IBundleGroup group = groups[j];
903 AboutInfo info = new AboutInfo(group);
905 String version = info.getVersionId();
906 version = version == null ? "0.0.0" //$NON-NLS-1$
907 : new Version(version).toString();
908 String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$
910 ids.put(versionedFeature, info);
918 * Returns the ordered map of versioned feature ids -> AboutInfo that are
919 * new for this session.
921 * @return ordered map of versioned feature ids (key type:
922 * <code>String</code>) -> infos (value type:
923 * <code>AboutInfo</code>).
925 public Map<String, AboutInfo> getNewlyAddedBundleGroups() {
926 if (newlyAddedBundleGroups == null) {
927 newlyAddedBundleGroups = createNewBundleGroupsMap();
929 return newlyAddedBundleGroups;
933 * Updates the old features setting and returns a map of new features.
935 private Map<String, AboutInfo> createNewBundleGroupsMap() {
936 // retrieve list of installed bundle groups from last session
937 IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
938 .getDialogSettings();
939 String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);
941 // get a map of currently installed bundle groups and store it for next
943 Map<String, AboutInfo> bundleGroups = computeBundleGroupMap();
944 String[] currentFeaturesArray = new String[bundleGroups.size()];
945 bundleGroups.keySet().toArray(currentFeaturesArray);
946 settings.put(INSTALLED_FEATURES, currentFeaturesArray);
948 // remove the previously known from the current set
949 if (previousFeaturesArray != null) {
950 for (int i = 0; i < previousFeaturesArray.length; ++i) {
951 bundleGroups.remove(previousFeaturesArray[i]);
959 * Declares all IDE-specific workbench images. This includes both "shared"
960 * images (named in {@link IDE.SharedImages}) and internal images (named in
961 * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).
963 * @see IWorkbenchConfigurer#declareImage
965 private void declareWorkbenchImages() {
967 final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$
968 final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; // Enabled //$NON-NLS-1$
972 final String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; // Disabled //$NON-NLS-1$
976 final String PATH_ETOOL = ICONS_PATH + "etool16/"; // Enabled toolbar //$NON-NLS-1$
979 final String PATH_DTOOL = ICONS_PATH + "dtool16/"; // Disabled toolbar //$NON-NLS-1$
982 final String PATH_OBJECT = ICONS_PATH + "obj16/"; // Model object //$NON-NLS-1$
985 final String PATH_WIZBAN = ICONS_PATH + "wizban/"; // Wizard //$NON-NLS-1$
989 Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
991 declareWorkbenchImage(ideBundle,
992 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL
993 + "build_exec.gif", false); //$NON-NLS-1$
994 declareWorkbenchImage(ideBundle,
995 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,
996 PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$
997 declareWorkbenchImage(ideBundle,
998 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,
999 PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$
1001 declareWorkbenchImage(ideBundle,
1002 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL
1003 + "search_src.gif", false); //$NON-NLS-1$
1004 declareWorkbenchImage(ideBundle,
1005 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,
1006 PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$
1007 declareWorkbenchImage(ideBundle,
1008 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,
1009 PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$
1011 declareWorkbenchImage(ideBundle,
1012 IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL
1013 + "next_nav.gif", false); //$NON-NLS-1$
1015 declareWorkbenchImage(ideBundle,
1016 IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL
1017 + "prev_nav.gif", false); //$NON-NLS-1$
1019 declareWorkbenchImage(ideBundle,
1020 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN
1021 + "newprj_wiz.png", false); //$NON-NLS-1$
1022 declareWorkbenchImage(ideBundle,
1023 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,
1024 PATH_WIZBAN + "newfolder_wiz.png", false); //$NON-NLS-1$
1025 declareWorkbenchImage(ideBundle,
1026 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN
1027 + "newfile_wiz.png", false); //$NON-NLS-1$
1029 declareWorkbenchImage(ideBundle,
1030 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,
1031 PATH_WIZBAN + "importdir_wiz.png", false); //$NON-NLS-1$
1032 declareWorkbenchImage(ideBundle,
1033 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,
1034 PATH_WIZBAN + "importzip_wiz.png", false); //$NON-NLS-1$
1036 declareWorkbenchImage(ideBundle,
1037 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,
1038 PATH_WIZBAN + "exportdir_wiz.png", false); //$NON-NLS-1$
1039 declareWorkbenchImage(ideBundle,
1040 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,
1041 PATH_WIZBAN + "exportzip_wiz.png", false); //$NON-NLS-1$
1043 declareWorkbenchImage(ideBundle,
1044 IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,
1045 PATH_WIZBAN + "workset_wiz.png", false); //$NON-NLS-1$
1047 declareWorkbenchImage(ideBundle,
1048 IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG, PATH_WIZBAN
1049 + "saveas_wiz.png", false); //$NON-NLS-1$
1051 declareWorkbenchImage(ideBundle,
1052 IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG, PATH_WIZBAN
1053 + "quick_fix.png", false); //$NON-NLS-1$
1055 declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,
1056 PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$
1057 declareWorkbenchImage(ideBundle,
1058 IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT
1059 + "cprj_obj.gif", true); //$NON-NLS-1$
1060 declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,
1061 PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$
1063 declareWorkbenchImage(ideBundle,
1064 IDEInternalWorkbenchImages.IMG_ELCL_QUICK_FIX_ENABLED,
1065 PATH_ELOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$
1067 declareWorkbenchImage(ideBundle,
1068 IDEInternalWorkbenchImages.IMG_DLCL_QUICK_FIX_DISABLED,
1069 PATH_DLOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$
1072 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK,
1073 // PATH_OBJECT+"hprio_tsk.gif");
1074 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK,
1075 // PATH_OBJECT+"mprio_tsk.gif");
1076 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK,
1077 // PATH_OBJECT+"lprio_tsk.gif");
1079 declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,
1080 PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$
1081 declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,
1082 PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$
1084 declareWorkbenchImage(ideBundle,
1085 IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT
1086 + "complete_tsk.gif", true); //$NON-NLS-1$
1087 declareWorkbenchImage(ideBundle,
1088 IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT
1089 + "incomplete_tsk.gif", true); //$NON-NLS-1$
1090 declareWorkbenchImage(ideBundle,
1091 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT
1092 + "welcome_item.gif", true); //$NON-NLS-1$
1093 declareWorkbenchImage(ideBundle,
1094 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT
1095 + "welcome_banner.gif", true); //$NON-NLS-1$
1096 declareWorkbenchImage(ideBundle,
1097 IDEInternalWorkbenchImages.IMG_OBJS_ERROR_PATH, PATH_OBJECT
1098 + "error_tsk.gif", true); //$NON-NLS-1$
1099 declareWorkbenchImage(ideBundle,
1100 IDEInternalWorkbenchImages.IMG_OBJS_WARNING_PATH, PATH_OBJECT
1101 + "warn_tsk.gif", true); //$NON-NLS-1$
1102 declareWorkbenchImage(ideBundle,
1103 IDEInternalWorkbenchImages.IMG_OBJS_INFO_PATH, PATH_OBJECT
1104 + "info_tsk.gif", true); //$NON-NLS-1$
1106 declareWorkbenchImage(ideBundle,
1107 IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL
1108 + "flatLayout.gif", true); //$NON-NLS-1$
1109 declareWorkbenchImage(ideBundle,
1110 IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT,
1111 PATH_ELOCALTOOL + "hierarchicalLayout.gif", true); //$NON-NLS-1$
1112 declareWorkbenchImage(ideBundle,
1113 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY,
1114 PATH_ETOOL + "problem_category.gif", true); //$NON-NLS-1$
1116 declareWorkbenchImage(ideBundle,
1117 IDEInternalWorkbenchImages.IMG_LCL_LINKTO_HELP, PATH_ELOCALTOOL
1118 + "linkto_help.gif", false); //$NON-NLS-1$
1121 // synchronization indicator objects
1122 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT,
1123 // PATH_OVERLAY+"wbet_stat.gif");
1124 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT,
1125 // PATH_OVERLAY+"sbet_stat.gif");
1126 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT,
1127 // PATH_OVERLAY+"conflict_stat.gif");
1129 // content locality indicator objects
1130 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT,
1131 // PATH_STAT+"notlocal_stat.gif");
1132 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT,
1133 // PATH_STAT+"local_stat.gif");
1134 // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT,
1135 // PATH_STAT+"filllocal_stat.gif");
1139 * Declares an IDE-specific workbench image.
1141 * @param symbolicName
1142 * the symbolic name of the image
1144 * the path of the image file; this path is relative to the base
1145 * of the IDE plug-in
1147 * <code>true</code> if this is a shared image, and
1148 * <code>false</code> if this is not a shared image
1149 * @see IWorkbenchConfigurer#declareImage
1151 private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,
1152 String path, boolean shared) {
1153 URL url = FileLocator.find(ideBundle, new Path(path), null);
1154 ImageDescriptor desc = ImageDescriptor.createFromURL(url);
1155 getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);
1161 * @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId
1164 public String getMainPreferencePageId() {
1165 // indicate that we want the Workench preference page to be prominent
1166 return WORKBENCH_PREFERENCE_CATEGORY_ID;
1170 * @return the workspace location string, or <code>null</code> if the
1171 * location is not being shown
1173 public String getWorkspaceLocation() {
1174 // read command line, which has priority
1175 IEclipseContext context = getWorkbenchConfigurer().getWorkbench().getService(IEclipseContext.class);
1176 String location = context != null ? (String) context.get(E4Workbench.FORCED_SHOW_LOCATION) : null;
1177 if (location != null) {
1180 // read the preference
1181 if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(IDEInternalPreferences.SHOW_LOCATION)) {
1182 return Platform.getLocation().toOSString();
1188 * @return the welcome perspective infos, or <code>null</code> if none or
1189 * if they should be ignored due to the new intro being present
1191 public AboutInfo[] getWelcomePerspectiveInfos() {
1192 if (welcomePerspectiveInfos == null) {
1193 // support old welcome perspectives if intro plugin is not present
1195 Map<String, AboutInfo> m = getNewlyAddedBundleGroups();
1196 ArrayList<AboutInfo> list = new ArrayList<AboutInfo>(m.size());
1197 for (Iterator<AboutInfo> i = m.values().iterator(); i.hasNext();) {
1198 AboutInfo info = i.next();
1199 if (info != null && info.getWelcomePerspectiveId() != null
1200 && info.getWelcomePageURL() != null) {
1204 welcomePerspectiveInfos = new AboutInfo[list.size()];
1205 list.toArray(welcomePerspectiveInfos);
1208 return welcomePerspectiveInfos;
1214 * @see org.eclipse.ui.application.WorkbenchAdvisor#getWorkbenchErrorHandler()
1217 public AbstractStatusHandler getWorkbenchErrorHandler() {
1218 if (ideWorkbenchErrorHandler == null) {
1219 ideWorkbenchErrorHandler = new IDEWorkbenchErrorHandler(
1220 getWorkbenchConfigurer());
1222 return ideWorkbenchErrorHandler;
1226 * @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopIdle(org.eclipse.swt.widgets.Display)
1229 public void eventLoopIdle(Display display) {
1230 if (delayedEventsProcessor != null)
1231 delayedEventsProcessor.catchUp(display);
1232 super.eventLoopIdle(display);