Merge commit 'ffdf837'
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / internal / SimanticsWorkbenchAdvisor.java
index d75f1e47672941e9f81eaabf8f7efd8b8d8833d6..bce220c9c3ae24fb64f8248766f0dce4956c1f8f 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.workbench.internal;\r
-\r
-import java.io.IOException;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.net.URL;\r
-import java.text.Collator;\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import org.eclipse.core.internal.resources.Workspace;\r
-import org.eclipse.core.net.proxy.IProxyService;\r
-import org.eclipse.core.resources.IContainer;\r
-import org.eclipse.core.resources.IResource;\r
-import org.eclipse.core.resources.ResourcesPlugin;\r
-import org.eclipse.core.resources.WorkspaceJob;\r
-import org.eclipse.core.runtime.CoreException;\r
-import org.eclipse.core.runtime.FileLocator;\r
-import org.eclipse.core.runtime.IAdaptable;\r
-import org.eclipse.core.runtime.IBundleGroup;\r
-import org.eclipse.core.runtime.IBundleGroupProvider;\r
-import org.eclipse.core.runtime.ILog;\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.MultiStatus;\r
-import org.eclipse.core.runtime.Path;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.ProgressMonitorWrapper;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.eclipse.core.runtime.jobs.Job;\r
-import org.eclipse.e4.core.contexts.IEclipseContext;\r
-import org.eclipse.e4.ui.internal.workbench.E4Workbench;\r
-import org.eclipse.jface.dialogs.ErrorDialog;\r
-import org.eclipse.jface.dialogs.IDialogSettings;\r
-import org.eclipse.jface.dialogs.MessageDialog;\r
-import org.eclipse.jface.dialogs.TrayDialog;\r
-import org.eclipse.jface.operation.IRunnableWithProgress;\r
-import org.eclipse.jface.preference.IPreferenceStore;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.jface.util.Policy;\r
-import org.eclipse.jface.window.Window;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Listener;\r
-import org.eclipse.swt.widgets.Shell;\r
-import org.eclipse.ui.IPerspectiveDescriptor;\r
-import org.eclipse.ui.PlatformUI;\r
-import org.eclipse.ui.application.IWorkbenchConfigurer;\r
-import org.eclipse.ui.application.IWorkbenchWindowConfigurer;\r
-import org.eclipse.ui.application.WorkbenchAdvisor;\r
-import org.eclipse.ui.application.WorkbenchWindowAdvisor;\r
-import org.eclipse.ui.ide.IDE;\r
-import org.eclipse.ui.internal.ISelectionConversionService;\r
-import org.eclipse.ui.internal.Workbench;\r
-import org.eclipse.ui.internal.ide.AboutInfo;\r
-import org.eclipse.ui.internal.ide.IDEInternalPreferences;\r
-import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;\r
-import org.eclipse.ui.internal.ide.IDESelectionConversionService;\r
-import org.eclipse.ui.internal.ide.IDEWorkbenchActivityHelper;\r
-import org.eclipse.ui.internal.ide.IDEWorkbenchErrorHandler;\r
-import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;\r
-import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;\r
-import org.eclipse.ui.internal.ide.undo.WorkspaceUndoMonitor;\r
-import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;\r
-import org.eclipse.ui.keys.IBindingService;\r
-import org.eclipse.ui.progress.IProgressService;\r
-import org.eclipse.ui.statushandlers.AbstractStatusHandler;\r
-import org.osgi.framework.Bundle;\r
-import org.osgi.framework.ServiceReference;\r
-import org.osgi.framework.Version;\r
-import org.simantics.CancelStartupException;\r
-import org.simantics.PlatformException;\r
-import org.simantics.Simantics;\r
-import org.simantics.SimanticsPlatform;\r
-import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;\r
-import org.simantics.SimanticsPlatform.RecoveryPolicy;\r
-import org.simantics.application.arguments.IArguments;\r
-import org.simantics.application.arguments.SimanticsArguments;\r
-import org.simantics.db.common.Indexing;\r
-import org.simantics.db.indexing.DatabaseIndexing;\r
-import org.simantics.db.procore.server.environment.RebootRequiredException;\r
-import org.simantics.db.procore.server.environment.windows.Product;\r
-import org.simantics.internal.TimedSessionCache;\r
-import org.simantics.project.IProject;\r
-import org.simantics.project.ProjectKeys;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
-import org.simantics.ui.workbench.PerspectiveBarsActivator;\r
-import org.simantics.ui.workbench.PerspectiveContextActivator;\r
-import org.simantics.utils.logging.TimeLogger;\r
-import org.simantics.utils.threads.ThreadUtils;\r
-import org.simantics.utils.ui.dialogs.ShowError;\r
-import org.simantics.utils.ui.dialogs.ShowMessage;\r
-\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class SimanticsWorkbenchAdvisor extends WorkbenchAdvisor {\r
-\r
-    private static final boolean PROFILE_PLATFORM_STARTUP = false;\r
-\r
-    private static final String SHUT_DOWN_TASK = "Shutting down...";\r
-\r
-    private static final String SHUT_DOWN_PLATFORM_TASK = "Shutting down platform...";\r
-\r
-    private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$\r
-\r
-    /**\r
-     * The dialog setting key to access the known installed features since the\r
-     * last time the workbench was run.\r
-     */\r
-    private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$\r
-\r
-    /**\r
-     * The arguments received by the application.\r
-     */\r
-    protected final IArguments args;\r
-\r
-    protected final boolean restoredPreviousSession = false;\r
-\r
-    /**\r
-     * Only true while opening the initial windows during {@link #openWindows()}.\r
-     * Used by {@link SimanticsWorkbenchWindowAdvisor#postWindowOpen()} to\r
-     * recognize when to skip all one-time initialization.\r
-     */\r
-    protected boolean workbenchWindowsInitialized = false;\r
-\r
-    /**\r
-     * Whether or not to save unsaved database changes before exiting the\r
-     * workbench.\r
-     */\r
-    protected boolean saveAtExit = false;\r
-\r
-    /**\r
-     * Ordered map of versioned feature ids -> info that are new for this\r
-     * session; <code>null</code> if uninitialized. Key type:\r
-     * <code>String</code>, Value type: <code>AboutInfo</code>.\r
-     */\r
-    private Map<String, AboutInfo> newlyAddedBundleGroups;\r
-\r
-    /**\r
-     * Array of <code>AboutInfo</code> for all new installed features that\r
-     * specify a welcome perspective.\r
-     */\r
-    private AboutInfo[] welcomePerspectiveInfos = null;\r
-\r
-    /**\r
-     * Helper for managing activites in response to workspace changes.\r
-     */\r
-    private IDEWorkbenchActivityHelper activityHelper = null;\r
-\r
-    /**\r
-     * Helper for managing work that is performed when the system is otherwise\r
-     * idle.\r
-     */\r
-    private IDEIdleHelper idleHelper;\r
-\r
-    private Listener settingsChangeListener;\r
-\r
-    /**\r
-     * Support class for monitoring workspace changes and periodically\r
-     * validating the undo history\r
-     */\r
-    private WorkspaceUndoMonitor workspaceUndoMonitor;\r
-\r
-    /**\r
-     * The IDE workbench error handler.\r
-     */\r
-    private AbstractStatusHandler ideWorkbenchErrorHandler;\r
-\r
-    /**\r
-     * Helper class used to process delayed events.\r
-     */\r
-    private DelayedEventsProcessor delayedEventsProcessor;\r
-    \r
-    /**\r
-     * Creates a new workbench advisor instance.\r
-     * @param processor\r
-     */\r
-    public SimanticsWorkbenchAdvisor(IArguments args, DelayedEventsProcessor processor) {\r
-        super();\r
-        this.args = args;\r
-        this.delayedEventsProcessor = processor;\r
-\r
-        Listener closeListener = new Listener() {\r
-            public void handleEvent(Event event) {\r
-                boolean doExit = SimanticsWorkbenchWindowAdvisor.promptOnExit(null);\r
-                event.doit = doExit;\r
-                if (!doExit)\r
-                    event.type = SWT.None;\r
-            }\r
-        };\r
-        Display.getDefault().addListener(SWT.Close, closeListener);\r
-    }\r
-\r
-    public IArguments getArguments() {\r
-        return args;\r
-    }\r
-\r
-    public boolean workbenchInitialized() {\r
-        return workbenchWindowsInitialized;\r
-    }\r
-\r
-    public boolean restoredPreviousSession() {\r
-        return restoredPreviousSession;\r
-    }\r
-\r
-    boolean saveAtExit() {\r
-        return saveAtExit;\r
-    }\r
-\r
-    void setSaveAtExit(boolean saveAtExit) {\r
-        this.saveAtExit = saveAtExit;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize\r
-     */\r
-    @Override\r
-    public void initialize(IWorkbenchConfigurer configurer) {\r
-        // By default, we always save and restore the workbench state.\r
-        configurer.setSaveAndRestore(true);\r
-\r
-        checkWorkspaceDatabaseIndexes();\r
-\r
-        // Start tracking the active perspective to activate contexts based on it.\r
-        new PerspectiveContextActivator();\r
-        new PerspectiveBarsActivator();\r
-\r
-        // register workspace adapters\r
-        IDE.registerAdapters();\r
-\r
-        // register shared images\r
-        declareWorkbenchImages();\r
-\r
-        // initialize the activity helper\r
-        activityHelper = IDEWorkbenchActivityHelper.getInstance();\r
-\r
-        // initialize idle handler\r
-        idleHelper = new IDEIdleHelper(configurer);\r
-\r
-        // initialize the workspace undo monitor\r
-        workspaceUndoMonitor = WorkspaceUndoMonitor.getInstance();\r
-\r
-        // show Help button in JFace dialogs\r
-        TrayDialog.setDialogHelpAvailable(true);\r
-\r
-        Policy.setComparator(Collator.getInstance());\r
-    }\r
-\r
-    private void checkWorkspaceDatabaseIndexes() {\r
-        try {\r
-            DatabaseIndexing.validateIndexes();\r
-        } catch (IOException e) {\r
-            Activator.logError("Problems encountered while checking database indexes, see exception for details.", e);\r
-        }\r
-    }\r
-\r
-    public WorkbenchWindowAdvisor createWorkbenchWindowAdvisorClass(SimanticsWorkbenchAdvisor advisor, IWorkbenchWindowConfigurer configurer) {\r
-        return new SimanticsWorkbenchWindowAdvisor(this, configurer);\r
-    }\r
-\r
-    @Override\r
-    public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {\r
-        // Attach database session watchdog.\r
-        new SessionWatchdog().attach( Simantics.getSessionContextProvider() );\r
-\r
-        return createWorkbenchWindowAdvisorClass(this, configurer);\r
-    }\r
-\r
-    /**\r
-     * For gaining direct access to super.openWindows() in implementations\r
-     * inheriting this one.\r
-     */\r
-    public boolean openWindowsSuper() {\r
-        return super.openWindows();\r
-    }\r
-\r
-    /**\r
-     * Sadly we do not know why key bindings are lost and why this helps. But it\r
-     * does. Visiting the <code>Keys</code> preference page and pressing OK uses\r
-     * this the same call and it seems to salvage the bindings that have been in\r
-     * some cases destroyed by <code>BindingToModelProcessor</code>.\r
-     * \r
-     * <p>\r
-     * Related links:\r
-     * https://techblog.ralph-schuster.eu/2013/10/13/eclipsee4-problem-with-key-bindings/comment-page-1/\r
-     * https://www.eclipse.org/forums/index.php/t/550175/\r
-     * https://bugs.eclipse.org/bugs/show_bug.cgi?id=461037\r
-     * \r
-     * @see platform issue #6353\r
-     */\r
-    private void fixBindings() {\r
-        try {\r
-            IBindingService bs = PlatformUI.getWorkbench().getAdapter(IBindingService.class);\r
-            bs.savePreferences(bs.getActiveScheme(), bs.getBindings());\r
-        } catch (IOException e) {\r
-            Activator.logError(getClass().getSimpleName() + ".fixBindings failed", e);\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public boolean openWindows() {\r
-        boolean platformOk = startPlatform();\r
-        TimeLogger.log("SimanticsWorkbenchAdvisor.startPlatform finished");\r
-\r
-        if (platformOk) {\r
-            // At this point workbenchConfigurer.getSaveAndRestore()\r
-            // returns false iff something has gone terribly wrong\r
-            // before this. Currently saveAndRestore is always true.\r
-            boolean windowsOpened = super.openWindows();\r
-            TimeLogger.log("Opened windows");\r
-            if (windowsOpened) {\r
-                workbenchWindowsInitialized = true;\r
-\r
-                // Start the database garbage collector after a short while.\r
-                SessionGarbageCollectorJob.getInstance().scheduleAfterQuietTime();\r
-\r
-                // Discard database session undo history at this point to prevent\r
-                // the user from undoing any initialization operations performed\r
-                // by the platform startup.\r
-                SimanticsPlatform.INSTANCE.discardSessionUndoHistory();\r
-                TimeLogger.log("Discarded session undo history");\r
-\r
-                // #6353: Workaround for  \r
-                fixBindings();\r
-\r
-                return true;\r
-            }\r
-        }\r
-\r
-        // Make sure platform shutdown is ran if window opening fails.\r
-        try {\r
-            platformShutdownRunnable.run(null);\r
-        } catch (InvocationTargetException e) {\r
-            Activator.logError(getClass().getSimpleName() + ".openWindows failed", e.getCause());\r
-        } catch (InterruptedException e) {\r
-            Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);\r
-        }\r
-        return false;\r
-    }\r
-\r
-    protected boolean startPlatform() {\r
-        // Verify selected perspective\r
-        if (args.contains(SimanticsArguments.PERSPECTIVE)) {\r
-            String perspectiveId = args.get(SimanticsArguments.PERSPECTIVE);\r
-            IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);\r
-            if (perspective == null) {\r
-                StringBuilder msg = new StringBuilder();\r
-                msg.append("Requested perspective not found: '" + perspectiveId + "'\n");\r
-                msg.append("Valid alternatives are:\n");\r
-                for (IPerspectiveDescriptor pd : PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives()) {\r
-                    msg.append("    " + pd.getId() + "\n");\r
-                }\r
-\r
-                ShowMessage.syncShowError("Invalid Perspective", msg.toString());\r
-                return false;\r
-            }\r
-        }\r
-\r
-        ILog log = Platform.getLog(Activator.getDefault().getBundle());\r
-\r
-        try {\r
-            //\r
-            //\r
-            // Create Simantics Platform Helper.\r
-            //\r
-            // If Simantics is started from Eclipse IDE or with -fixerrors option,\r
-            // there is an attempt to fix errors.\r
-            //\r
-            // On ontology mismatch, there is an attempt to merge new ontology to the\r
-            // existing database. With -reinstall, the database is cleaned and\r
-            // reinstalled.\r
-            //\r
-            //\r
-\r
-            RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;\r
-            OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;\r
-\r
-            if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {\r
-                workspacePolicy = RecoveryPolicy.FixError;\r
-                ontologyPolicy = OntologyRecoveryPolicy.Merge;\r
-            }\r
-\r
-            boolean requireSynchronize = true;\r
-\r
-            if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {\r
-                ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;\r
-            }\r
-\r
-            if (args.contains(SimanticsArguments.DO_NOT_SYNCHRONIZE_ONTOLOGIES)) {\r
-                requireSynchronize = false;\r
-            }\r
-            \r
-            if (args.contains(SimanticsArguments.DISABLE_INDEX)) {\r
-               Indexing.setDefaultDependenciesIndexingEnabled(false);\r
-            }\r
-\r
-            if (args.contains(SimanticsArguments.SERVER)) {\r
-                String serverAddress = args.get(SimanticsArguments.SERVER);\r
-                throw new PlatformException("Argument not supported: " + SimanticsArguments.SERVER + " " + serverAddress);\r
-            }\r
-\r
-            String databaseDriverId = Simantics.getDefaultDatabaseDriver();\r
-            if (args.contains(SimanticsArguments.DATABASE_ID)) {\r
-                databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);\r
-                Simantics.setDefaultDatabaseDriver(databaseDriverId);\r
-            }\r
-            \r
-            IProgressMonitor mon = null;\r
-            if (PROFILE_PLATFORM_STARTUP)\r
-                mon = new TimingProgressMonitor();\r
-            SimanticsPlatform.INSTANCE.startUp(databaseDriverId, mon, workspacePolicy, ontologyPolicy, requireSynchronize, new JFaceUserAgent());\r
-\r
-            // Make sure that the default perspective comes from the project if\r
-            // the project has set ProjectKeys#DEFAULT_PERSPECTIVE.\r
-            // This might go wrong if project features interact with\r
-            // PerspectiveRegistry while configuring themselves, since that will\r
-            // cause an invocation to #getInitialWindowPerspectiveId() while\r
-            // the project has not yet been properly initialized.\r
-            getWorkbenchConfigurer().getWorkbench().getPerspectiveRegistry().setDefaultPerspective(getInitialWindowPerspectiveId());\r
-            TimeLogger.log("Completed setting default perspective");\r
-\r
-            return true;\r
-        } catch (CancelStartupException e) {\r
-            return false;\r
-        } catch (PlatformException e) {\r
-            boolean hasStackTrace = e.getStackTrace().length > 0;\r
-            Throwable ee = e;\r
-            while (ee.getCause() != null) {\r
-                ee = ee.getCause();\r
-                hasStackTrace = ee.getStackTrace().length > 0;\r
-            }\r
-\r
-            log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), hasStackTrace ? e : null));\r
-            if (hasStackTrace) {\r
-                new ShowError("Platform Initialization Failed", "Simantics Platform initialization failed:\n\n" + e.getMessage(), e, true);\r
-            } else {\r
-                StringBuilder sb = new StringBuilder(256);\r
-                sb.append(e.getMessage());\r
-                for (Throwable c=e.getCause(); null != c && null != c.getMessage(); c=c.getCause())\r
-                    sb.append("\ncause: ").append(c.getMessage());\r
-                new ShowError("Startup Failed", sb.toString(), (Exception) null, true);\r
-            }\r
-\r
-            return false;\r
-        } catch (Exception e) {\r
-            log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));\r
-\r
-            Throwable cause = e.getCause();\r
-            if (cause instanceof RebootRequiredException) {\r
-                RebootRequiredException rre = (RebootRequiredException) cause;\r
-                StringBuilder msg = new StringBuilder();\r
-                msg.append("The application must be restarted after installing the following products:\n");\r
-                for (Product product : rre.products)\r
-                    msg.append("\t" + product + "\n");\r
-                msg.append("\nThe application will now close.");\r
-                MessageDialog.openInformation(null, "Restart Required", msg.toString());\r
-            } else {\r
-                new ShowError("Platform Startup Failed", "Simantics Platform startup failed:\n\n" + e.getMessage(), e, true);\r
-            }\r
-            return false;\r
-        }\r
-\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()\r
-     */\r
-    @Override\r
-    public void preStartup() {\r
-\r
-        // Suspend background jobs while we startup\r
-        Job.getJobManager().suspend();\r
-\r
-        // Register the build actions\r
-        IProgressService service = PlatformUI.getWorkbench()\r
-        .getProgressService();\r
-        ImageDescriptor newImage = IDEInternalWorkbenchImages\r
-        .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);\r
-        service.registerIconForFamily(newImage,\r
-                ResourcesPlugin.FAMILY_MANUAL_BUILD);\r
-        service.registerIconForFamily(newImage,\r
-                ResourcesPlugin.FAMILY_AUTO_BUILD);\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()\r
-     */\r
-    @Override\r
-    public void postStartup() {\r
-        try {\r
-            refreshFromLocal();\r
-            activateProxyService();\r
-            ((Workbench) PlatformUI.getWorkbench()).registerService(\r
-                    ISelectionConversionService.class,\r
-                    new IDESelectionConversionService());\r
-\r
-            initializeSettingsChangeListener();\r
-            Display.getCurrent().addListener(SWT.Settings,\r
-                    settingsChangeListener);\r
-        } finally {// Resume background jobs after we startup\r
-            Job.getJobManager().resume();\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Activate the proxy service by obtaining it.\r
-     */\r
-    private void activateProxyService() {\r
-        Bundle bundle = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$\r
-        Object proxyService = null;\r
-        if (bundle != null) {\r
-            ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(IProxyService.class.getName());\r
-            if (ref != null)\r
-                proxyService = bundle.getBundleContext().getService(ref);\r
-        }\r
-        if (proxyService == null) {\r
-            IDEWorkbenchPlugin.log("Proxy service could not be found."); //$NON-NLS-1$\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Initialize the listener for settings changes.\r
-     */\r
-    private void initializeSettingsChangeListener() {\r
-        settingsChangeListener = new Listener() {\r
-\r
-            boolean currentHighContrast = Display.getCurrent()\r
-            .getHighContrast();\r
-\r
-            @Override\r
-            public void handleEvent(org.eclipse.swt.widgets.Event event) {\r
-                if (Display.getCurrent().getHighContrast() == currentHighContrast)\r
-                    return;\r
-\r
-                currentHighContrast = !currentHighContrast;\r
-\r
-                // make sure they really want to do this\r
-                if (new MessageDialog(null,\r
-                        IDEWorkbenchMessages.SystemSettingsChange_title, null,\r
-                        IDEWorkbenchMessages.SystemSettingsChange_message,\r
-                        MessageDialog.QUESTION, new String[] {\r
-                        IDEWorkbenchMessages.SystemSettingsChange_yes,\r
-                        IDEWorkbenchMessages.SystemSettingsChange_no },\r
-                        1).open() == Window.OK) {\r
-                    PlatformUI.getWorkbench().restart();\r
-                }\r
-            }\r
-        };\r
-\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown\r
-     */\r
-    @Override\r
-    public void postShutdown() {\r
-        if (activityHelper != null) {\r
-            activityHelper.shutdown();\r
-            activityHelper = null;\r
-        }\r
-        if (idleHelper != null) {\r
-            idleHelper.shutdown();\r
-            idleHelper = null;\r
-        }\r
-        if (workspaceUndoMonitor != null) {\r
-            workspaceUndoMonitor.shutdown();\r
-            workspaceUndoMonitor = null;\r
-        }\r
-        if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {\r
-            disconnectFromWorkspace();\r
-        }\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()\r
-     */\r
-    @Override\r
-    public boolean preShutdown() {\r
-        Display.getCurrent().removeListener(SWT.Settings,\r
-                settingsChangeListener);\r
-        return super.preShutdown();\r
-    }\r
-\r
-    /**\r
-     * Return true if the intro plugin is present and false otherwise.\r
-     *\r
-     * @return boolean\r
-     */\r
-    public boolean hasIntro() {\r
-        return getWorkbenchConfigurer().getWorkbench().getIntroManager()\r
-                .hasIntro();\r
-    }\r
-\r
-    private void refreshFromLocal() {\r
-        String[] commandLineArgs = Platform.getCommandLineArgs();\r
-        IPreferenceStore store = IDEWorkbenchPlugin.getDefault()\r
-                .getPreferenceStore();\r
-        boolean refresh = store\r
-                .getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);\r
-        if (!refresh) {\r
-            return;\r
-        }\r
-\r
-        // Do not refresh if it was already done by core on startup.\r
-        for (int i = 0; i < commandLineArgs.length; i++) {\r
-            if (commandLineArgs[i].equalsIgnoreCase("-refresh")) { //$NON-NLS-1$\r
-                return;\r
-            }\r
-        }\r
-\r
-        final IContainer root = ResourcesPlugin.getWorkspace().getRoot();\r
-        Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {\r
-            @Override\r
-            public IStatus runInWorkspace(IProgressMonitor monitor)\r
-                    throws CoreException {\r
-                root.refreshLocal(IResource.DEPTH_INFINITE, monitor);\r
-                return Status.OK_STATUS;\r
-            }\r
-        };\r
-        job.setRule(root);\r
-        job.schedule();\r
-    }\r
-\r
-    private static class CancelableProgressMonitorWrapper extends ProgressMonitorWrapper {\r
-        private double total = 0;\r
-        private ProgressMonitorJobsDialog dialog;\r
-\r
-        CancelableProgressMonitorWrapper(IProgressMonitor monitor,\r
-                ProgressMonitorJobsDialog dialog) {\r
-            super(monitor);\r
-            this.dialog = dialog;\r
-        }\r
-\r
-        /*\r
-         * (non-Javadoc)\r
-         * @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double)\r
-         */\r
-        public void internalWorked(double work) {\r
-            super.internalWorked(work);\r
-            total += work;\r
-            updateProgressDetails();\r
-        }\r
-\r
-        /*\r
-         * (non-Javadoc)\r
-         * @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int)\r
-         */\r
-        public void worked(int work) {\r
-            super.worked(work);\r
-            total += work;\r
-            updateProgressDetails();\r
-        }\r
-\r
-        public void beginTask(String name, int totalWork) {\r
-            super.beginTask(name, totalWork);\r
-            subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_preHistoryCompaction);\r
-        }\r
-\r
-        private void updateProgressDetails() {\r
-            if (!isCanceled() && Math.abs(total - 4.0) < 0.0001 /* right before history compacting */) {\r
-                subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_cancelHistoryPruning);\r
-                dialog.setCancelable(true);\r
-            }\r
-            if (Math.abs(total - 5.0) < 0.0001 /* history compacting finished */) {\r
-                subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_postHistoryCompaction);\r
-                dialog.setCancelable(false);\r
-            }\r
-        }\r
-    }\r
-\r
-    private static class CancelableProgressMonitorJobsDialog extends ProgressMonitorJobsDialog {\r
-\r
-        public CancelableProgressMonitorJobsDialog(Shell parent) {\r
-            super(parent);\r
-        }\r
-\r
-        /*\r
-         * (non-Javadoc)\r
-         * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDetailsButton(org.eclipse.swt.widgets.Composite)\r
-         */\r
-        protected void createButtonsForButtonBar(Composite parent) {\r
-            super.createButtonsForButtonBar(parent);\r
-            registerCancelButtonListener();\r
-        }\r
-\r
-        public void registerCancelButtonListener() {\r
-            cancel.addSelectionListener(new SelectionAdapter() {\r
-                public void widgetSelected(SelectionEvent e) {\r
-                    subTaskLabel.setText(""); //$NON-NLS-1$\r
-                }\r
-            });\r
-        }\r
-    }\r
-\r
-\r
-    final IRunnableWithProgress platformShutdownRunnable = new IRunnableWithProgress() {\r
-        /**\r
-         * @param monitor\r
-         *            the progress monitor to use for reporting progress to the\r
-         *            user, or <code>null</code> indicating that no progress\r
-         *            should be reported and the operation cannot be cancelled.\r
-         */\r
-        @Override\r
-        public void run(IProgressMonitor monitor) {\r
-            SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_PLATFORM_TASK, 100);\r
-            try {\r
-                try {\r
-                    progress.subTask("Platform");\r
-                    SimanticsPlatform.INSTANCE.shutdown(progress.newChild(50));\r
-                } catch (PlatformException e) {\r
-                    Activator.logError("Problems encountered while shutting down Simantics platform, see exception for details.", e);\r
-                }\r
-\r
-                progress.subTask("Remaining database connections");\r
-                SimanticsUI.closeSessions();\r
-                progress.worked(20);\r
-                TimedSessionCache.close();\r
-                progress.worked(20);\r
-\r
-                progress.subTask("Thread pools");\r
-                ThreadUtils.shutdown();\r
-                progress.worked(5);\r
-\r
-                progress.subTask("Clear index status");\r
-                try {\r
-                    // Everything ok, clear index dirty state.\r
-                    DatabaseIndexing.clearAllDirty();\r
-                } catch (IOException e) {\r
-                    Activator.logError("Problems encountered while refreshing database index states, see exception for details.", e);\r
-                }\r
-                progress.worked(5);\r
-\r
-                progress.setWorkRemaining(0);\r
-            } finally {\r
-                if (monitor != null) {\r
-                    monitor.done();\r
-                }\r
-            }\r
-        }\r
-    };\r
-\r
-    /**\r
-     * Disconnect from the workspace and close ProCore sessions.\r
-     */\r
-    private void disconnectFromWorkspace() {\r
-        // save the workspace\r
-        final MultiStatus status = new MultiStatus(\r
-                IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
-                IDEWorkbenchMessages.ProblemSavingWorkbench, null);\r
-\r
-        final ProgressMonitorJobsDialog p = new CancelableProgressMonitorJobsDialog(\r
-                null);\r
-\r
-        final boolean applyPolicy = ResourcesPlugin.getWorkspace()\r
-                .getDescription().isApplyFileStatePolicy();\r
-\r
-        final IRunnableWithProgress workspaceShutdownRunnable = new IRunnableWithProgress() {\r
-            @Override\r
-            public void run(IProgressMonitor monitor) {\r
-                try {\r
-                    status.merge(((Workspace) ResourcesPlugin.getWorkspace()).save(true, true, monitor));\r
-                } catch (CoreException e) {\r
-                    status.merge(e.getStatus());\r
-                }\r
-            }\r
-        };\r
-\r
-        IRunnableWithProgress shutdownRunnable = new IRunnableWithProgress() {\r
-            @Override\r
-            public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
-                if (applyPolicy)\r
-                    monitor = new CancelableProgressMonitorWrapper(\r
-                            monitor, p);\r
-\r
-                SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_TASK, 2);\r
-                try {\r
-                    workspaceShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));\r
-                    platformShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));\r
-                } finally {\r
-                    monitor.done();\r
-                }\r
-            }\r
-        };\r
-\r
-        try {\r
-            new ProgressMonitorJobsDialog(null).run(true, false, shutdownRunnable);\r
-        } catch (InvocationTargetException e) {\r
-            status.merge(new Status(IStatus.ERROR,\r
-                    IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
-                    IDEWorkbenchMessages.InternalError, e.getTargetException()));\r
-        } catch (InterruptedException e) {\r
-            status.merge(new Status(IStatus.ERROR,\r
-                    IDEWorkbenchPlugin.IDE_WORKBENCH, 1,\r
-                    IDEWorkbenchMessages.InternalError, e));\r
-        }\r
-        ErrorDialog.openError(null,\r
-                IDEWorkbenchMessages.ProblemsSavingWorkspace, null, status,\r
-                IStatus.ERROR | IStatus.WARNING);\r
-        if (!status.isOK()) {\r
-            IDEWorkbenchPlugin.log(\r
-                    IDEWorkbenchMessages.ProblemsSavingWorkspace, status);\r
-        }\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput\r
-     */\r
-    @Override\r
-    public IAdaptable getDefaultPageInput() {\r
-        return ResourcesPlugin.getWorkspace().getRoot();\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor\r
-     */\r
-    @Override\r
-    public String getInitialWindowPerspectiveId() {\r
-        int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;\r
-\r
-        String perspectiveId = null;\r
-        AboutInfo[] welcomeInfos = getWelcomePerspectiveInfos();\r
-        if (index >= 0 && welcomeInfos != null && index < welcomeInfos.length) {\r
-            perspectiveId = welcomeInfos[index].getWelcomePerspectiveId();\r
-        }\r
-\r
-        if (perspectiveId == null && args.contains(SimanticsArguments.PERSPECTIVE)) {\r
-            String id = args.get(SimanticsArguments.PERSPECTIVE);\r
-            IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(id);\r
-            if (perspective != null)\r
-                perspectiveId = id;\r
-        }\r
-\r
-        if (perspectiveId == null) {\r
-            IProject project = SimanticsUI.peekProject();\r
-            if (project != null)\r
-                perspectiveId = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);\r
-        }\r
-\r
-        //System.out.println("Initial perspective: " + perspectiveId);\r
-\r
-        return perspectiveId;\r
-    }\r
-\r
-    /**\r
-     * Returns the map of versioned feature ids -> info object for all installed\r
-     * features. The format of the versioned feature id (the key of the map) is\r
-     * featureId + ":" + versionId.\r
-     *\r
-     * @return map of versioned feature ids -> info object (key type:\r
-     *         <code>String</code>, value type: <code>AboutInfo</code>)\r
-     * @since 3.0\r
-     */\r
-    private Map<String, AboutInfo> computeBundleGroupMap() {\r
-        // use tree map to get predicable order\r
-        Map<String, AboutInfo> ids = new TreeMap<String, AboutInfo>();\r
-\r
-        IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();\r
-        for (int i = 0; i < providers.length; ++i) {\r
-            IBundleGroup[] groups = providers[i].getBundleGroups();\r
-            for (int j = 0; j < groups.length; ++j) {\r
-                IBundleGroup group = groups[j];\r
-                AboutInfo info = new AboutInfo(group);\r
-\r
-                String version = info.getVersionId();\r
-                version = version == null ? "0.0.0" //$NON-NLS-1$\r
-                        : new Version(version).toString();\r
-                String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$\r
-\r
-                ids.put(versionedFeature, info);\r
-            }\r
-        }\r
-\r
-        return ids;\r
-    }\r
-\r
-    /**\r
-     * Returns the ordered map of versioned feature ids -> AboutInfo that are\r
-     * new for this session.\r
-     *\r
-     * @return ordered map of versioned feature ids (key type:\r
-     *         <code>String</code>) -> infos (value type:\r
-     *         <code>AboutInfo</code>).\r
-     */\r
-    public Map<String, AboutInfo> getNewlyAddedBundleGroups() {\r
-        if (newlyAddedBundleGroups == null) {\r
-            newlyAddedBundleGroups = createNewBundleGroupsMap();\r
-        }\r
-        return newlyAddedBundleGroups;\r
-    }\r
-\r
-    /**\r
-     * Updates the old features setting and returns a map of new features.\r
-     */\r
-    private Map<String, AboutInfo> createNewBundleGroupsMap() {\r
-        // retrieve list of installed bundle groups from last session\r
-        IDialogSettings settings = IDEWorkbenchPlugin.getDefault()\r
-                .getDialogSettings();\r
-        String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);\r
-\r
-        // get a map of currently installed bundle groups and store it for next\r
-        // session\r
-        Map<String, AboutInfo> bundleGroups = computeBundleGroupMap();\r
-        String[] currentFeaturesArray = new String[bundleGroups.size()];\r
-        bundleGroups.keySet().toArray(currentFeaturesArray);\r
-        settings.put(INSTALLED_FEATURES, currentFeaturesArray);\r
-\r
-        // remove the previously known from the current set\r
-        if (previousFeaturesArray != null) {\r
-            for (int i = 0; i < previousFeaturesArray.length; ++i) {\r
-                bundleGroups.remove(previousFeaturesArray[i]);\r
-            }\r
-        }\r
-\r
-        return bundleGroups;\r
-    }\r
-\r
-    /**\r
-     * Declares all IDE-specific workbench images. This includes both "shared"\r
-     * images (named in {@link IDE.SharedImages}) and internal images (named in\r
-     * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).\r
-     *\r
-     * @see IWorkbenchConfigurer#declareImage\r
-     */\r
-    private void declareWorkbenchImages() {\r
-\r
-        final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$\r
-        final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; // Enabled //$NON-NLS-1$\r
-\r
-        // toolbar\r
-        // icons.\r
-        final String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; // Disabled //$NON-NLS-1$\r
-        // //$NON-NLS-1$\r
-        // toolbar\r
-        // icons.\r
-        final String PATH_ETOOL = ICONS_PATH + "etool16/"; // Enabled toolbar //$NON-NLS-1$\r
-        // //$NON-NLS-1$\r
-        // icons.\r
-        final String PATH_DTOOL = ICONS_PATH + "dtool16/"; // Disabled toolbar //$NON-NLS-1$\r
-        // //$NON-NLS-1$\r
-        // icons.\r
-        final String PATH_OBJECT = ICONS_PATH + "obj16/"; // Model object //$NON-NLS-1$\r
-        // //$NON-NLS-1$\r
-        // icons\r
-        final String PATH_WIZBAN = ICONS_PATH + "wizban/"; // Wizard //$NON-NLS-1$\r
-        // //$NON-NLS-1$\r
-        // icons\r
-\r
-        Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL\r
-                + "build_exec.gif", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,\r
-                PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,\r
-                PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL\r
-                + "search_src.gif", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,\r
-                PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,\r
-                PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL\r
-                + "next_nav.gif", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL\r
-                + "prev_nav.gif", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN\r
-                + "newprj_wiz.png", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,\r
-                PATH_WIZBAN + "newfolder_wiz.png", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN\r
-                + "newfile_wiz.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,\r
-                PATH_WIZBAN + "importdir_wiz.png", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,\r
-                PATH_WIZBAN + "importzip_wiz.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,\r
-                PATH_WIZBAN + "exportdir_wiz.png", false); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,\r
-                PATH_WIZBAN + "exportzip_wiz.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,\r
-                PATH_WIZBAN + "workset_wiz.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG, PATH_WIZBAN\r
-                + "saveas_wiz.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG, PATH_WIZBAN\r
-                + "quick_fix.png", false); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,\r
-                PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT\r
-                + "cprj_obj.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,\r
-                PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ELCL_QUICK_FIX_ENABLED,\r
-                PATH_ELOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_DLCL_QUICK_FIX_DISABLED,\r
-                PATH_DLOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$\r
-\r
-        // task objects\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK,\r
-        // PATH_OBJECT+"hprio_tsk.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK,\r
-        // PATH_OBJECT+"mprio_tsk.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK,\r
-        // PATH_OBJECT+"lprio_tsk.gif");\r
-\r
-        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,\r
-                PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,\r
-                PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT\r
-                + "complete_tsk.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT\r
-                + "incomplete_tsk.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT\r
-                + "welcome_item.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT\r
-                + "welcome_banner.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_ERROR_PATH, PATH_OBJECT\r
-                + "error_tsk.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_WARNING_PATH, PATH_OBJECT\r
-                + "warn_tsk.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_OBJS_INFO_PATH, PATH_OBJECT\r
-                + "info_tsk.gif", true); //$NON-NLS-1$\r
-\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL\r
-                + "flatLayout.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT,\r
-                PATH_ELOCALTOOL + "hierarchicalLayout.gif", true); //$NON-NLS-1$\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY,\r
-                PATH_ETOOL + "problem_category.gif", true); //$NON-NLS-1$\r
-        /*\r
-        declareWorkbenchImage(ideBundle,\r
-                IDEInternalWorkbenchImages.IMG_LCL_LINKTO_HELP, PATH_ELOCALTOOL\r
-                        + "linkto_help.gif", false); //$NON-NLS-1$\r
-         */\r
-\r
-        // synchronization indicator objects\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT,\r
-        // PATH_OVERLAY+"wbet_stat.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT,\r
-        // PATH_OVERLAY+"sbet_stat.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT,\r
-        // PATH_OVERLAY+"conflict_stat.gif");\r
-\r
-        // content locality indicator objects\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT,\r
-        // PATH_STAT+"notlocal_stat.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT,\r
-        // PATH_STAT+"local_stat.gif");\r
-        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT,\r
-        // PATH_STAT+"filllocal_stat.gif");\r
-    }\r
-\r
-    /**\r
-     * Declares an IDE-specific workbench image.\r
-     *\r
-     * @param symbolicName\r
-     *            the symbolic name of the image\r
-     * @param path\r
-     *            the path of the image file; this path is relative to the base\r
-     *            of the IDE plug-in\r
-     * @param shared\r
-     *            <code>true</code> if this is a shared image, and\r
-     *            <code>false</code> if this is not a shared image\r
-     * @see IWorkbenchConfigurer#declareImage\r
-     */\r
-    private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,\r
-            String path, boolean shared) {\r
-        URL url = FileLocator.find(ideBundle, new Path(path), null);\r
-        ImageDescriptor desc = ImageDescriptor.createFromURL(url);\r
-        getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId\r
-     */\r
-    @Override\r
-    public String getMainPreferencePageId() {\r
-        // indicate that we want the Workench preference page to be prominent\r
-        return WORKBENCH_PREFERENCE_CATEGORY_ID;\r
-    }\r
-\r
-    /**\r
-     * @return the workspace location string, or <code>null</code> if the\r
-     *         location is not being shown\r
-     */\r
-    public String getWorkspaceLocation() {\r
-               // read command line, which has priority\r
-               IEclipseContext context = getWorkbenchConfigurer().getWorkbench().getService(IEclipseContext.class);\r
-               String location = context != null ? (String) context.get(E4Workbench.FORCED_SHOW_LOCATION) : null;\r
-               if (location != null) {\r
-                       return location;\r
-               }\r
-               // read the preference\r
-               if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(IDEInternalPreferences.SHOW_LOCATION)) {\r
-                       return Platform.getLocation().toOSString();\r
-               }\r
-               return null;\r
-    }\r
-\r
-    /**\r
-     * @return the welcome perspective infos, or <code>null</code> if none or\r
-     *         if they should be ignored due to the new intro being present\r
-     */\r
-    public AboutInfo[] getWelcomePerspectiveInfos() {\r
-        if (welcomePerspectiveInfos == null) {\r
-            // support old welcome perspectives if intro plugin is not present\r
-            if (!hasIntro()) {\r
-                Map<String, AboutInfo> m = getNewlyAddedBundleGroups();\r
-                ArrayList<AboutInfo> list = new ArrayList<AboutInfo>(m.size());\r
-                for (Iterator<AboutInfo> i = m.values().iterator(); i.hasNext();) {\r
-                    AboutInfo info = i.next();\r
-                    if (info != null && info.getWelcomePerspectiveId() != null\r
-                            && info.getWelcomePageURL() != null) {\r
-                        list.add(info);\r
-                    }\r
-                }\r
-                welcomePerspectiveInfos = new AboutInfo[list.size()];\r
-                list.toArray(welcomePerspectiveInfos);\r
-            }\r
-        }\r
-        return welcomePerspectiveInfos;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#getWorkbenchErrorHandler()\r
-     */\r
-    @Override\r
-    public AbstractStatusHandler getWorkbenchErrorHandler() {\r
-        if (ideWorkbenchErrorHandler == null) {\r
-            ideWorkbenchErrorHandler = new IDEWorkbenchErrorHandler(\r
-                    getWorkbenchConfigurer());\r
-        }\r
-        return ideWorkbenchErrorHandler;\r
-    }\r
-\r
-    /* (non-Javadoc)\r
-     * @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopIdle(org.eclipse.swt.widgets.Display)\r
-     */\r
-    @Override\r
-    public void eventLoopIdle(Display display) {\r
-        if (delayedEventsProcessor != null)\r
-            delayedEventsProcessor.catchUp(display);\r
-        super.eventLoopIdle(display);\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.workbench.internal;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.core.internal.resources.Workspace;
+import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IBundleGroup;
+import org.eclipse.core.runtime.IBundleGroupProvider;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.ProgressMonitorWrapper;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.internal.workbench.E4Workbench;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.TrayDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.Policy;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.application.IWorkbenchConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.ISelectionConversionService;
+import org.eclipse.ui.internal.Workbench;
+import org.eclipse.ui.internal.ide.AboutInfo;
+import org.eclipse.ui.internal.ide.IDEInternalPreferences;
+import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
+import org.eclipse.ui.internal.ide.IDESelectionConversionService;
+import org.eclipse.ui.internal.ide.IDEWorkbenchActivityHelper;
+import org.eclipse.ui.internal.ide.IDEWorkbenchErrorHandler;
+import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.ide.undo.WorkspaceUndoMonitor;
+import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.progress.IProgressService;
+import org.eclipse.ui.statushandlers.AbstractStatusHandler;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.simantics.CancelStartupException;
+import org.simantics.PlatformException;
+import org.simantics.Simantics;
+import org.simantics.SimanticsPlatform;
+import org.simantics.SimanticsPlatform.OntologyRecoveryPolicy;
+import org.simantics.SimanticsPlatform.RecoveryPolicy;
+import org.simantics.application.arguments.IArguments;
+import org.simantics.application.arguments.SimanticsArguments;
+import org.simantics.db.common.Indexing;
+import org.simantics.db.indexing.DatabaseIndexing;
+import org.simantics.db.procore.server.environment.RebootRequiredException;
+import org.simantics.db.procore.server.environment.windows.Product;
+import org.simantics.internal.TimedSessionCache;
+import org.simantics.project.IProject;
+import org.simantics.project.ProjectKeys;
+import org.simantics.ui.SimanticsUI;
+import org.simantics.ui.jobs.SessionGarbageCollectorJob;
+import org.simantics.ui.workbench.PerspectiveBarsActivator;
+import org.simantics.ui.workbench.PerspectiveContextActivator;
+import org.simantics.utils.logging.TimeLogger;
+import org.simantics.utils.threads.ThreadUtils;
+import org.simantics.utils.ui.dialogs.ShowError;
+import org.simantics.utils.ui.dialogs.ShowMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class SimanticsWorkbenchAdvisor extends WorkbenchAdvisor {
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(SimanticsWorkbenchAdvisor.class);
+
+    private static final boolean PROFILE_PLATFORM_STARTUP = false;
+
+    private static final String SHUT_DOWN_TASK = "Shutting down...";
+
+    private static final String SHUT_DOWN_PLATFORM_TASK = "Shutting down platform...";
+
+    private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$
+
+    /**
+     * The dialog setting key to access the known installed features since the
+     * last time the workbench was run.
+     */
+    private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$
+
+    /**
+     * The arguments received by the application.
+     */
+    protected final IArguments args;
+
+    protected final boolean restoredPreviousSession = false;
+
+    /**
+     * Only true while opening the initial windows during {@link #openWindows()}.
+     * Used by {@link SimanticsWorkbenchWindowAdvisor#postWindowOpen()} to
+     * recognize when to skip all one-time initialization.
+     */
+    protected boolean workbenchWindowsInitialized = false;
+
+    /**
+     * Whether or not to save unsaved database changes before exiting the
+     * workbench.
+     */
+    protected boolean saveAtExit = false;
+
+    /**
+     * Ordered map of versioned feature ids -> info that are new for this
+     * session; <code>null</code> if uninitialized. Key type:
+     * <code>String</code>, Value type: <code>AboutInfo</code>.
+     */
+    private Map<String, AboutInfo> newlyAddedBundleGroups;
+
+    /**
+     * Array of <code>AboutInfo</code> for all new installed features that
+     * specify a welcome perspective.
+     */
+    private AboutInfo[] welcomePerspectiveInfos = null;
+
+    /**
+     * Helper for managing activites in response to workspace changes.
+     */
+    private IDEWorkbenchActivityHelper activityHelper = null;
+
+    /**
+     * Helper for managing work that is performed when the system is otherwise
+     * idle.
+     */
+    private IDEIdleHelper idleHelper;
+
+    private Listener settingsChangeListener;
+
+    /**
+     * Support class for monitoring workspace changes and periodically
+     * validating the undo history
+     */
+    private WorkspaceUndoMonitor workspaceUndoMonitor;
+
+    /**
+     * The IDE workbench error handler.
+     */
+    private AbstractStatusHandler ideWorkbenchErrorHandler;
+
+    /**
+     * Helper class used to process delayed events.
+     */
+    private DelayedEventsProcessor delayedEventsProcessor;
+    
+    /**
+     * Creates a new workbench advisor instance.
+     * @param processor
+     */
+    public SimanticsWorkbenchAdvisor(IArguments args, DelayedEventsProcessor processor) {
+        super();
+        this.args = args;
+        this.delayedEventsProcessor = processor;
+
+        Listener closeListener = new Listener() {
+            public void handleEvent(Event event) {
+                boolean doExit = SimanticsWorkbenchWindowAdvisor.promptOnExit(null);
+                event.doit = doExit;
+                if (!doExit)
+                    event.type = SWT.None;
+            }
+        };
+        Display.getDefault().addListener(SWT.Close, closeListener);
+    }
+
+    public IArguments getArguments() {
+        return args;
+    }
+
+    public boolean workbenchInitialized() {
+        return workbenchWindowsInitialized;
+    }
+
+    public boolean restoredPreviousSession() {
+        return restoredPreviousSession;
+    }
+
+    boolean saveAtExit() {
+        return saveAtExit;
+    }
+
+    void setSaveAtExit(boolean saveAtExit) {
+        this.saveAtExit = saveAtExit;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize
+     */
+    @Override
+    public void initialize(IWorkbenchConfigurer configurer) {
+        // By default, we always save and restore the workbench state.
+        configurer.setSaveAndRestore(true);
+
+        checkWorkspaceDatabaseIndexes();
+
+        // Start tracking the active perspective to activate contexts based on it.
+        new PerspectiveContextActivator();
+        new PerspectiveBarsActivator();
+
+        // register workspace adapters
+        IDE.registerAdapters();
+
+        // register shared images
+        declareWorkbenchImages();
+
+        // initialize the activity helper
+        activityHelper = IDEWorkbenchActivityHelper.getInstance();
+
+        // initialize idle handler
+        idleHelper = new IDEIdleHelper(configurer);
+
+        // initialize the workspace undo monitor
+        workspaceUndoMonitor = WorkspaceUndoMonitor.getInstance();
+
+        // show Help button in JFace dialogs
+        TrayDialog.setDialogHelpAvailable(true);
+
+        Policy.setComparator(Collator.getInstance());
+    }
+
+    private void checkWorkspaceDatabaseIndexes() {
+        try {
+            DatabaseIndexing.validateIndexes();
+        } catch (IOException e) {
+            Activator.logError("Problems encountered while checking database indexes, see exception for details.", e);
+        }
+    }
+
+    public WorkbenchWindowAdvisor createWorkbenchWindowAdvisorClass(SimanticsWorkbenchAdvisor advisor, IWorkbenchWindowConfigurer configurer) {
+        return new SimanticsWorkbenchWindowAdvisor(this, configurer);
+    }
+
+    @Override
+    public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
+        // Attach database session watchdog.
+        new SessionWatchdog().attach( Simantics.getSessionContextProvider() );
+
+        return createWorkbenchWindowAdvisorClass(this, configurer);
+    }
+
+    /**
+     * For gaining direct access to super.openWindows() in implementations
+     * inheriting this one.
+     */
+    public boolean openWindowsSuper() {
+        return super.openWindows();
+    }
+
+    /**
+     * Sadly we do not know why key bindings are lost and why this helps. But it
+     * does. Visiting the <code>Keys</code> preference page and pressing OK uses
+     * this the same call and it seems to salvage the bindings that have been in
+     * some cases destroyed by <code>BindingToModelProcessor</code>.
+     * 
+     * <p>
+     * Related links:
+     * https://techblog.ralph-schuster.eu/2013/10/13/eclipsee4-problem-with-key-bindings/comment-page-1/
+     * https://www.eclipse.org/forums/index.php/t/550175/
+     * https://bugs.eclipse.org/bugs/show_bug.cgi?id=461037
+     * 
+     * @see platform issue #6353
+     */
+    private void fixBindings() {
+        try {
+            IBindingService bs = PlatformUI.getWorkbench().getAdapter(IBindingService.class);
+            bs.savePreferences(bs.getActiveScheme(), bs.getBindings());
+        } catch (IOException e) {
+            Activator.logError(getClass().getSimpleName() + ".fixBindings failed", e);
+        }
+    }
+
+    @Override
+    public boolean openWindows() {
+        boolean platformOk = startPlatform();
+        LOGGER.info("startPlatform finished");
+        TimeLogger.log("SimanticsWorkbenchAdvisor.startPlatform finished");
+
+        if (platformOk) {
+            // At this point workbenchConfigurer.getSaveAndRestore()
+            // returns false iff something has gone terribly wrong
+            // before this. Currently saveAndRestore is always true.
+            boolean windowsOpened = super.openWindows();
+            TimeLogger.log("Opened windows");
+            if (windowsOpened) {
+                workbenchWindowsInitialized = true;
+
+                // Start the database garbage collector after a short while.
+                SessionGarbageCollectorJob.getInstance().scheduleAfterQuietTime();
+
+                // Discard database session undo history at this point to prevent
+                // the user from undoing any initialization operations performed
+                // by the platform startup.
+                SimanticsPlatform.INSTANCE.discardSessionUndoHistory();
+                TimeLogger.log("Discarded session undo history");
+
+                // #6353: Workaround for  
+                fixBindings();
+
+                return true;
+            }
+        }
+
+        // Make sure platform shutdown is ran if window opening fails.
+        try {
+            platformShutdownRunnable.run(null);
+        } catch (InvocationTargetException e) {
+            Activator.logError(getClass().getSimpleName() + ".openWindows failed", e.getCause());
+        } catch (InterruptedException e) {
+            Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);
+        }
+        return false;
+    }
+
+    protected boolean startPlatform() {
+        // Verify selected perspective
+        if (args.contains(SimanticsArguments.PERSPECTIVE)) {
+            String perspectiveId = args.get(SimanticsArguments.PERSPECTIVE);
+            IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
+            if (perspective == null) {
+                StringBuilder msg = new StringBuilder();
+                msg.append("Requested perspective not found: '" + perspectiveId + "'\n");
+                msg.append("Valid alternatives are:\n");
+                for (IPerspectiveDescriptor pd : PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives()) {
+                    msg.append("    " + pd.getId() + "\n");
+                }
+
+                ShowMessage.syncShowError("Invalid Perspective", msg.toString());
+                return false;
+            }
+        }
+
+        ILog log = Platform.getLog(Activator.getDefault().getBundle());
+
+        try {
+            //
+            //
+            // Create Simantics Platform Helper.
+            //
+            // If Simantics is started from Eclipse IDE or with -fixerrors option,
+            // there is an attempt to fix errors.
+            //
+            // On ontology mismatch, there is an attempt to merge new ontology to the
+            // existing database. With -reinstall, the database is cleaned and
+            // reinstalled.
+            //
+            //
+
+            RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;
+            OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;
+
+            if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {
+                workspacePolicy = RecoveryPolicy.FixError;
+                ontologyPolicy = OntologyRecoveryPolicy.Merge;
+            }
+
+            boolean requireSynchronize = true;
+
+            if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
+                ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
+            }
+
+            if (args.contains(SimanticsArguments.DO_NOT_SYNCHRONIZE_ONTOLOGIES)) {
+                requireSynchronize = false;
+            }
+            
+            if (args.contains(SimanticsArguments.DISABLE_INDEX)) {
+               Indexing.setDefaultDependenciesIndexingEnabled(false);
+            }
+
+            if (args.contains(SimanticsArguments.SERVER)) {
+                String serverAddress = args.get(SimanticsArguments.SERVER);
+                throw new PlatformException("Argument not supported: " + SimanticsArguments.SERVER + " " + serverAddress);
+            }
+
+            String databaseDriverId = Simantics.getDefaultDatabaseDriver();
+            if (args.contains(SimanticsArguments.DATABASE_ID)) {
+                databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);
+                Simantics.setDefaultDatabaseDriver(databaseDriverId);
+            }
+            
+            IProgressMonitor mon = null;
+            if (PROFILE_PLATFORM_STARTUP)
+                mon = new TimingProgressMonitor();
+            SimanticsPlatform.INSTANCE.startUp(databaseDriverId, mon, workspacePolicy, ontologyPolicy, requireSynchronize, new JFaceUserAgent());
+
+            // Make sure that the default perspective comes from the project if
+            // the project has set ProjectKeys#DEFAULT_PERSPECTIVE.
+            // This might go wrong if project features interact with
+            // PerspectiveRegistry while configuring themselves, since that will
+            // cause an invocation to #getInitialWindowPerspectiveId() while
+            // the project has not yet been properly initialized.
+            getWorkbenchConfigurer().getWorkbench().getPerspectiveRegistry().setDefaultPerspective(getInitialWindowPerspectiveId());
+            TimeLogger.log("Completed setting default perspective");
+
+            return true;
+        } catch (CancelStartupException e) {
+            return false;
+        } catch (PlatformException e) {
+            boolean hasStackTrace = e.getStackTrace().length > 0;
+            Throwable ee = e;
+            while (ee.getCause() != null) {
+                ee = ee.getCause();
+                hasStackTrace = ee.getStackTrace().length > 0;
+            }
+
+            log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), hasStackTrace ? e : null));
+            if (hasStackTrace) {
+                new ShowError("Platform Initialization Failed", "Simantics Platform initialization failed:\n\n" + e.getMessage(), e, true);
+            } else {
+                StringBuilder sb = new StringBuilder(256);
+                sb.append(e.getMessage());
+                for (Throwable c=e.getCause(); null != c && null != c.getMessage(); c=c.getCause())
+                    sb.append("\ncause: ").append(c.getMessage());
+                new ShowError("Startup Failed", sb.toString(), (Exception) null, true);
+            }
+
+            return false;
+        } catch (Exception e) {
+            log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
+
+            Throwable cause = e.getCause();
+            if (cause instanceof RebootRequiredException) {
+                RebootRequiredException rre = (RebootRequiredException) cause;
+                StringBuilder msg = new StringBuilder();
+                msg.append("The application must be restarted after installing the following products:\n");
+                for (Product product : rre.products)
+                    msg.append("\t" + product + "\n");
+                msg.append("\nThe application will now close.");
+                MessageDialog.openInformation(null, "Restart Required", msg.toString());
+            } else {
+                new ShowError("Platform Startup Failed", "Simantics Platform startup failed:\n\n" + e.getMessage(), e, true);
+            }
+            return false;
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()
+     */
+    @Override
+    public void preStartup() {
+
+        // Suspend background jobs while we startup
+        Job.getJobManager().suspend();
+
+        // Register the build actions
+        IProgressService service = PlatformUI.getWorkbench()
+        .getProgressService();
+        ImageDescriptor newImage = IDEInternalWorkbenchImages
+        .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
+        service.registerIconForFamily(newImage,
+                ResourcesPlugin.FAMILY_MANUAL_BUILD);
+        service.registerIconForFamily(newImage,
+                ResourcesPlugin.FAMILY_AUTO_BUILD);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
+     */
+    @Override
+    public void postStartup() {
+        try {
+            refreshFromLocal();
+            activateProxyService();
+            ((Workbench) PlatformUI.getWorkbench()).registerService(
+                    ISelectionConversionService.class,
+                    new IDESelectionConversionService());
+
+            initializeSettingsChangeListener();
+            Display.getCurrent().addListener(SWT.Settings,
+                    settingsChangeListener);
+        } finally {// Resume background jobs after we startup
+            Job.getJobManager().resume();
+        }
+    }
+
+    /**
+     * Activate the proxy service by obtaining it.
+     */
+    private void activateProxyService() {
+        Bundle bundle = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$
+        Object proxyService = null;
+        if (bundle != null) {
+            ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(IProxyService.class.getName());
+            if (ref != null)
+                proxyService = bundle.getBundleContext().getService(ref);
+        }
+        if (proxyService == null) {
+            IDEWorkbenchPlugin.log("Proxy service could not be found."); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Initialize the listener for settings changes.
+     */
+    private void initializeSettingsChangeListener() {
+        settingsChangeListener = new Listener() {
+
+            boolean currentHighContrast = Display.getCurrent()
+            .getHighContrast();
+
+            @Override
+            public void handleEvent(org.eclipse.swt.widgets.Event event) {
+                if (Display.getCurrent().getHighContrast() == currentHighContrast)
+                    return;
+
+                currentHighContrast = !currentHighContrast;
+
+                // make sure they really want to do this
+                if (new MessageDialog(null,
+                        IDEWorkbenchMessages.SystemSettingsChange_title, null,
+                        IDEWorkbenchMessages.SystemSettingsChange_message,
+                        MessageDialog.QUESTION, new String[] {
+                        IDEWorkbenchMessages.SystemSettingsChange_yes,
+                        IDEWorkbenchMessages.SystemSettingsChange_no },
+                        1).open() == Window.OK) {
+                    PlatformUI.getWorkbench().restart();
+                }
+            }
+        };
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown
+     */
+    @Override
+    public void postShutdown() {
+        if (activityHelper != null) {
+            activityHelper.shutdown();
+            activityHelper = null;
+        }
+        if (idleHelper != null) {
+            idleHelper.shutdown();
+            idleHelper = null;
+        }
+        if (workspaceUndoMonitor != null) {
+            workspaceUndoMonitor.shutdown();
+            workspaceUndoMonitor = null;
+        }
+        if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {
+            disconnectFromWorkspace();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()
+     */
+    @Override
+    public boolean preShutdown() {
+        Display.getCurrent().removeListener(SWT.Settings,
+                settingsChangeListener);
+        return super.preShutdown();
+    }
+
+    /**
+     * Return true if the intro plugin is present and false otherwise.
+     *
+     * @return boolean
+     */
+    public boolean hasIntro() {
+        return getWorkbenchConfigurer().getWorkbench().getIntroManager()
+                .hasIntro();
+    }
+
+    private void refreshFromLocal() {
+        String[] commandLineArgs = Platform.getCommandLineArgs();
+        IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
+                .getPreferenceStore();
+        boolean refresh = store
+                .getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);
+        if (!refresh) {
+            return;
+        }
+
+        // Do not refresh if it was already done by core on startup.
+        for (int i = 0; i < commandLineArgs.length; i++) {
+            if (commandLineArgs[i].equalsIgnoreCase("-refresh")) { //$NON-NLS-1$
+                return;
+            }
+        }
+
+        final IContainer root = ResourcesPlugin.getWorkspace().getRoot();
+        Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {
+            @Override
+            public IStatus runInWorkspace(IProgressMonitor monitor)
+                    throws CoreException {
+                root.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+                return Status.OK_STATUS;
+            }
+        };
+        job.setRule(root);
+        job.schedule();
+    }
+
+    private static class CancelableProgressMonitorWrapper extends ProgressMonitorWrapper {
+        private double total = 0;
+        private ProgressMonitorJobsDialog dialog;
+
+        CancelableProgressMonitorWrapper(IProgressMonitor monitor,
+                ProgressMonitorJobsDialog dialog) {
+            super(monitor);
+            this.dialog = dialog;
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double)
+         */
+        public void internalWorked(double work) {
+            super.internalWorked(work);
+            total += work;
+            updateProgressDetails();
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int)
+         */
+        public void worked(int work) {
+            super.worked(work);
+            total += work;
+            updateProgressDetails();
+        }
+
+        public void beginTask(String name, int totalWork) {
+            super.beginTask(name, totalWork);
+            subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_preHistoryCompaction);
+        }
+
+        private void updateProgressDetails() {
+            if (!isCanceled() && Math.abs(total - 4.0) < 0.0001 /* right before history compacting */) {
+                subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_cancelHistoryPruning);
+                dialog.setCancelable(true);
+            }
+            if (Math.abs(total - 5.0) < 0.0001 /* history compacting finished */) {
+                subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_postHistoryCompaction);
+                dialog.setCancelable(false);
+            }
+        }
+    }
+
+    private static class CancelableProgressMonitorJobsDialog extends ProgressMonitorJobsDialog {
+
+        public CancelableProgressMonitorJobsDialog(Shell parent) {
+            super(parent);
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDetailsButton(org.eclipse.swt.widgets.Composite)
+         */
+        protected void createButtonsForButtonBar(Composite parent) {
+            super.createButtonsForButtonBar(parent);
+            registerCancelButtonListener();
+        }
+
+        public void registerCancelButtonListener() {
+            cancel.addSelectionListener(new SelectionAdapter() {
+                public void widgetSelected(SelectionEvent e) {
+                    subTaskLabel.setText(""); //$NON-NLS-1$
+                }
+            });
+        }
+    }
+
+
+    final IRunnableWithProgress platformShutdownRunnable = new IRunnableWithProgress() {
+        /**
+         * @param monitor
+         *            the progress monitor to use for reporting progress to the
+         *            user, or <code>null</code> indicating that no progress
+         *            should be reported and the operation cannot be cancelled.
+         */
+        @Override
+        public void run(IProgressMonitor monitor) {
+            SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_PLATFORM_TASK, 100);
+            try {
+                try {
+                    progress.subTask("Platform");
+                    SimanticsPlatform.INSTANCE.shutdown(progress.newChild(50));
+                } catch (PlatformException e) {
+                    Activator.logError("Problems encountered while shutting down Simantics platform, see exception for details.", e);
+                }
+
+                progress.subTask("Remaining database connections");
+                SimanticsUI.closeSessions();
+                progress.worked(20);
+                TimedSessionCache.close();
+                progress.worked(20);
+
+                progress.subTask("Thread pools");
+                ThreadUtils.shutdown();
+                progress.worked(5);
+
+                progress.subTask("Clear index status");
+                try {
+                    // Everything ok, clear index dirty state.
+                    DatabaseIndexing.clearAllDirty();
+                } catch (IOException e) {
+                    Activator.logError("Problems encountered while refreshing database index states, see exception for details.", e);
+                }
+                progress.worked(5);
+
+                progress.setWorkRemaining(0);
+            } finally {
+                if (monitor != null) {
+                    monitor.done();
+                }
+            }
+        }
+    };
+
+    /**
+     * Disconnect from the workspace and close ProCore sessions.
+     */
+    private void disconnectFromWorkspace() {
+        // save the workspace
+        final MultiStatus status = new MultiStatus(
+                IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
+                IDEWorkbenchMessages.ProblemSavingWorkbench, null);
+
+        final ProgressMonitorJobsDialog p = new CancelableProgressMonitorJobsDialog(
+                null);
+
+        final boolean applyPolicy = ResourcesPlugin.getWorkspace()
+                .getDescription().isApplyFileStatePolicy();
+
+        final IRunnableWithProgress workspaceShutdownRunnable = new IRunnableWithProgress() {
+            @Override
+            public void run(IProgressMonitor monitor) {
+                try {
+                    status.merge(((Workspace) ResourcesPlugin.getWorkspace()).save(true, true, monitor));
+                } catch (CoreException e) {
+                    status.merge(e.getStatus());
+                }
+            }
+        };
+
+        IRunnableWithProgress shutdownRunnable = new IRunnableWithProgress() {
+            @Override
+            public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+                if (applyPolicy)
+                    monitor = new CancelableProgressMonitorWrapper(
+                            monitor, p);
+
+                SubMonitor progress = SubMonitor.convert(monitor, SHUT_DOWN_TASK, 2);
+                try {
+                    workspaceShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));
+                    platformShutdownRunnable.run(progress.newChild(1, SubMonitor.SUPPRESS_NONE));
+                } finally {
+                    monitor.done();
+                }
+            }
+        };
+
+        try {
+            new ProgressMonitorJobsDialog(null).run(true, false, shutdownRunnable);
+        } catch (InvocationTargetException e) {
+            status.merge(new Status(IStatus.ERROR,
+                    IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
+                    IDEWorkbenchMessages.InternalError, e.getTargetException()));
+        } catch (InterruptedException e) {
+            status.merge(new Status(IStatus.ERROR,
+                    IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
+                    IDEWorkbenchMessages.InternalError, e));
+        }
+        ErrorDialog.openError(null,
+                IDEWorkbenchMessages.ProblemsSavingWorkspace, null, status,
+                IStatus.ERROR | IStatus.WARNING);
+        if (!status.isOK()) {
+            IDEWorkbenchPlugin.log(
+                    IDEWorkbenchMessages.ProblemsSavingWorkspace, status);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput
+     */
+    @Override
+    public IAdaptable getDefaultPageInput() {
+        return ResourcesPlugin.getWorkspace().getRoot();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor
+     */
+    @Override
+    public String getInitialWindowPerspectiveId() {
+        int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;
+
+        String perspectiveId = null;
+        AboutInfo[] welcomeInfos = getWelcomePerspectiveInfos();
+        if (index >= 0 && welcomeInfos != null && index < welcomeInfos.length) {
+            perspectiveId = welcomeInfos[index].getWelcomePerspectiveId();
+        }
+
+        if (perspectiveId == null && args.contains(SimanticsArguments.PERSPECTIVE)) {
+            String id = args.get(SimanticsArguments.PERSPECTIVE);
+            IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(id);
+            if (perspective != null)
+                perspectiveId = id;
+        }
+
+        if (perspectiveId == null) {
+            IProject project = SimanticsUI.peekProject();
+            if (project != null)
+                perspectiveId = project.getHint(ProjectKeys.DEFAULT_PERSPECTIVE);
+        }
+
+        //System.out.println("Initial perspective: " + perspectiveId);
+
+        return perspectiveId;
+    }
+
+    /**
+     * Returns the map of versioned feature ids -> info object for all installed
+     * features. The format of the versioned feature id (the key of the map) is
+     * featureId + ":" + versionId.
+     *
+     * @return map of versioned feature ids -> info object (key type:
+     *         <code>String</code>, value type: <code>AboutInfo</code>)
+     * @since 3.0
+     */
+    private Map<String, AboutInfo> computeBundleGroupMap() {
+        // use tree map to get predicable order
+        Map<String, AboutInfo> ids = new TreeMap<String, AboutInfo>();
+
+        IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
+        for (int i = 0; i < providers.length; ++i) {
+            IBundleGroup[] groups = providers[i].getBundleGroups();
+            for (int j = 0; j < groups.length; ++j) {
+                IBundleGroup group = groups[j];
+                AboutInfo info = new AboutInfo(group);
+
+                String version = info.getVersionId();
+                version = version == null ? "0.0.0" //$NON-NLS-1$
+                        : new Version(version).toString();
+                String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$
+
+                ids.put(versionedFeature, info);
+            }
+        }
+
+        return ids;
+    }
+
+    /**
+     * Returns the ordered map of versioned feature ids -> AboutInfo that are
+     * new for this session.
+     *
+     * @return ordered map of versioned feature ids (key type:
+     *         <code>String</code>) -> infos (value type:
+     *         <code>AboutInfo</code>).
+     */
+    public Map<String, AboutInfo> getNewlyAddedBundleGroups() {
+        if (newlyAddedBundleGroups == null) {
+            newlyAddedBundleGroups = createNewBundleGroupsMap();
+        }
+        return newlyAddedBundleGroups;
+    }
+
+    /**
+     * Updates the old features setting and returns a map of new features.
+     */
+    private Map<String, AboutInfo> createNewBundleGroupsMap() {
+        // retrieve list of installed bundle groups from last session
+        IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
+                .getDialogSettings();
+        String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);
+
+        // get a map of currently installed bundle groups and store it for next
+        // session
+        Map<String, AboutInfo> bundleGroups = computeBundleGroupMap();
+        String[] currentFeaturesArray = new String[bundleGroups.size()];
+        bundleGroups.keySet().toArray(currentFeaturesArray);
+        settings.put(INSTALLED_FEATURES, currentFeaturesArray);
+
+        // remove the previously known from the current set
+        if (previousFeaturesArray != null) {
+            for (int i = 0; i < previousFeaturesArray.length; ++i) {
+                bundleGroups.remove(previousFeaturesArray[i]);
+            }
+        }
+
+        return bundleGroups;
+    }
+
+    /**
+     * Declares all IDE-specific workbench images. This includes both "shared"
+     * images (named in {@link IDE.SharedImages}) and internal images (named in
+     * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).
+     *
+     * @see IWorkbenchConfigurer#declareImage
+     */
+    private void declareWorkbenchImages() {
+
+        final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$
+        final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; // Enabled //$NON-NLS-1$
+
+        // toolbar
+        // icons.
+        final String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; // Disabled //$NON-NLS-1$
+        // //$NON-NLS-1$
+        // toolbar
+        // icons.
+        final String PATH_ETOOL = ICONS_PATH + "etool16/"; // Enabled toolbar //$NON-NLS-1$
+        // //$NON-NLS-1$
+        // icons.
+        final String PATH_DTOOL = ICONS_PATH + "dtool16/"; // Disabled toolbar //$NON-NLS-1$
+        // //$NON-NLS-1$
+        // icons.
+        final String PATH_OBJECT = ICONS_PATH + "obj16/"; // Model object //$NON-NLS-1$
+        // //$NON-NLS-1$
+        // icons
+        final String PATH_WIZBAN = ICONS_PATH + "wizban/"; // Wizard //$NON-NLS-1$
+        // //$NON-NLS-1$
+        // icons
+
+        Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL
+                + "build_exec.gif", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,
+                PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,
+                PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL
+                + "search_src.gif", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,
+                PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,
+                PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL
+                + "next_nav.gif", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL
+                + "prev_nav.gif", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN
+                + "newprj_wiz.png", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,
+                PATH_WIZBAN + "newfolder_wiz.png", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN
+                + "newfile_wiz.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,
+                PATH_WIZBAN + "importdir_wiz.png", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,
+                PATH_WIZBAN + "importzip_wiz.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,
+                PATH_WIZBAN + "exportdir_wiz.png", false); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,
+                PATH_WIZBAN + "exportzip_wiz.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,
+                PATH_WIZBAN + "workset_wiz.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG, PATH_WIZBAN
+                + "saveas_wiz.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG, PATH_WIZBAN
+                + "quick_fix.png", false); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,
+                PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT
+                + "cprj_obj.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,
+                PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ELCL_QUICK_FIX_ENABLED,
+                PATH_ELOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_DLCL_QUICK_FIX_DISABLED,
+                PATH_DLOCALTOOL + "smartmode_co.gif", true); //$NON-NLS-1$
+
+        // task objects
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK,
+        // PATH_OBJECT+"hprio_tsk.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK,
+        // PATH_OBJECT+"mprio_tsk.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK,
+        // PATH_OBJECT+"lprio_tsk.gif");
+
+        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,
+                PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,
+                PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT
+                + "complete_tsk.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT
+                + "incomplete_tsk.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT
+                + "welcome_item.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT
+                + "welcome_banner.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_ERROR_PATH, PATH_OBJECT
+                + "error_tsk.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_WARNING_PATH, PATH_OBJECT
+                + "warn_tsk.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_OBJS_INFO_PATH, PATH_OBJECT
+                + "info_tsk.gif", true); //$NON-NLS-1$
+
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL
+                + "flatLayout.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT,
+                PATH_ELOCALTOOL + "hierarchicalLayout.gif", true); //$NON-NLS-1$
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY,
+                PATH_ETOOL + "problem_category.gif", true); //$NON-NLS-1$
+        /*
+        declareWorkbenchImage(ideBundle,
+                IDEInternalWorkbenchImages.IMG_LCL_LINKTO_HELP, PATH_ELOCALTOOL
+                        + "linkto_help.gif", false); //$NON-NLS-1$
+         */
+
+        // synchronization indicator objects
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT,
+        // PATH_OVERLAY+"wbet_stat.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT,
+        // PATH_OVERLAY+"sbet_stat.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT,
+        // PATH_OVERLAY+"conflict_stat.gif");
+
+        // content locality indicator objects
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT,
+        // PATH_STAT+"notlocal_stat.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT,
+        // PATH_STAT+"local_stat.gif");
+        // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT,
+        // PATH_STAT+"filllocal_stat.gif");
+    }
+
+    /**
+     * Declares an IDE-specific workbench image.
+     *
+     * @param symbolicName
+     *            the symbolic name of the image
+     * @param path
+     *            the path of the image file; this path is relative to the base
+     *            of the IDE plug-in
+     * @param shared
+     *            <code>true</code> if this is a shared image, and
+     *            <code>false</code> if this is not a shared image
+     * @see IWorkbenchConfigurer#declareImage
+     */
+    private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,
+            String path, boolean shared) {
+        URL url = FileLocator.find(ideBundle, new Path(path), null);
+        ImageDescriptor desc = ImageDescriptor.createFromURL(url);
+        getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId
+     */
+    @Override
+    public String getMainPreferencePageId() {
+        // indicate that we want the Workench preference page to be prominent
+        return WORKBENCH_PREFERENCE_CATEGORY_ID;
+    }
+
+    /**
+     * @return the workspace location string, or <code>null</code> if the
+     *         location is not being shown
+     */
+    public String getWorkspaceLocation() {
+               // read command line, which has priority
+               IEclipseContext context = getWorkbenchConfigurer().getWorkbench().getService(IEclipseContext.class);
+               String location = context != null ? (String) context.get(E4Workbench.FORCED_SHOW_LOCATION) : null;
+               if (location != null) {
+                       return location;
+               }
+               // read the preference
+               if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(IDEInternalPreferences.SHOW_LOCATION)) {
+                       return Platform.getLocation().toOSString();
+               }
+               return null;
+    }
+
+    /**
+     * @return the welcome perspective infos, or <code>null</code> if none or
+     *         if they should be ignored due to the new intro being present
+     */
+    public AboutInfo[] getWelcomePerspectiveInfos() {
+        if (welcomePerspectiveInfos == null) {
+            // support old welcome perspectives if intro plugin is not present
+            if (!hasIntro()) {
+                Map<String, AboutInfo> m = getNewlyAddedBundleGroups();
+                ArrayList<AboutInfo> list = new ArrayList<AboutInfo>(m.size());
+                for (Iterator<AboutInfo> i = m.values().iterator(); i.hasNext();) {
+                    AboutInfo info = i.next();
+                    if (info != null && info.getWelcomePerspectiveId() != null
+                            && info.getWelcomePageURL() != null) {
+                        list.add(info);
+                    }
+                }
+                welcomePerspectiveInfos = new AboutInfo[list.size()];
+                list.toArray(welcomePerspectiveInfos);
+            }
+        }
+        return welcomePerspectiveInfos;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#getWorkbenchErrorHandler()
+     */
+    @Override
+    public AbstractStatusHandler getWorkbenchErrorHandler() {
+        if (ideWorkbenchErrorHandler == null) {
+            ideWorkbenchErrorHandler = new IDEWorkbenchErrorHandler(
+                    getWorkbenchConfigurer());
+        }
+        return ideWorkbenchErrorHandler;
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopIdle(org.eclipse.swt.widgets.Display)
+     */
+    @Override
+    public void eventLoopIdle(Display display) {
+        if (delayedEventsProcessor != null)
+            delayedEventsProcessor.catchUp(display);
+        super.eventLoopIdle(display);
+    }
+
+}