-/*******************************************************************************\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);
++ 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);
+ }
+
+}
-/*******************************************************************************\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;\r
-\r
-import static org.simantics.db.common.utils.Transaction.commit;\r
-import static org.simantics.db.common.utils.Transaction.endTransaction;\r
-import static org.simantics.db.common.utils.Transaction.readGraph;\r
-import static org.simantics.db.common.utils.Transaction.startTransaction;\r
-import static org.simantics.db.common.utils.Transaction.writeGraph;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Map.Entry;\r
-import java.util.Properties;\r
-import java.util.Set;\r
-import java.util.TreeMap;\r
-import java.util.UUID;\r
-\r
-import org.eclipse.core.runtime.ILog;\r
-import org.eclipse.core.runtime.IProduct;\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.NullProgressMonitor;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.eclipse.osgi.service.resolver.BundleDescription;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Databoard;\r
-import org.simantics.datatypes.literal.Font;\r
-import org.simantics.datatypes.literal.RGB;\r
-import org.simantics.db.Driver;\r
-import org.simantics.db.Driver.Management;\r
-import org.simantics.db.Manager;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.SessionModel;\r
-import org.simantics.db.UndoContext;\r
-import org.simantics.db.VirtualGraph;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
-import org.simantics.db.common.request.Queries;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.utils.Transaction;\r
-import org.simantics.db.exception.ClusterSetExistException;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.ResourceNotFoundException;\r
-import org.simantics.db.indexing.DatabaseIndexing;\r
-import org.simantics.db.layer0.genericrelation.DependenciesRelation;\r
-import org.simantics.db.layer0.util.SimanticsClipboardImpl;\r
-import org.simantics.db.layer0.util.SimanticsKeys;\r
-import org.simantics.db.layer0.util.TGTransferableGraphSource;\r
-import org.simantics.db.layer0.variable.VariableRepository;\r
-import org.simantics.db.management.SessionContext;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.db.service.LifecycleSupport.LifecycleListener;\r
-import org.simantics.db.service.LifecycleSupport.LifecycleState;\r
-import org.simantics.db.service.QueryControl;\r
-import org.simantics.db.service.UndoRedoSupport;\r
-import org.simantics.db.service.VirtualGraphSupport;\r
-import org.simantics.db.service.XSupport;\r
-import org.simantics.graph.db.GraphDependencyAnalyzer;\r
-import org.simantics.graph.db.GraphDependencyAnalyzer.IU;\r
-import org.simantics.graph.db.GraphDependencyAnalyzer.IdentityNode;\r
-import org.simantics.graph.db.IImportAdvisor;\r
-import org.simantics.graph.db.TransferableGraphs;\r
-import org.simantics.graph.diff.Diff;\r
-import org.simantics.graph.diff.TransferableGraphDelta1;\r
-import org.simantics.internal.Activator;\r
-import org.simantics.internal.startup.StartupExtensions;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.operation.Layer0X;\r
-import org.simantics.project.IProject;\r
-import org.simantics.project.ProjectFeatures;\r
-import org.simantics.project.ProjectKeys;\r
-import org.simantics.project.Projects;\r
-import org.simantics.project.exception.ProjectException;\r
-import org.simantics.project.features.registry.GroupReference;\r
-import org.simantics.project.management.DatabaseManagement;\r
-import org.simantics.project.management.GraphBundle;\r
-import org.simantics.project.management.GraphBundleEx;\r
-import org.simantics.project.management.GraphBundleRef;\r
-import org.simantics.project.management.PlatformUtil;\r
-import org.simantics.project.management.ServerManager;\r
-import org.simantics.project.management.ServerManagerFactory;\r
-import org.simantics.project.management.WorkspaceUtil;\r
-import org.simantics.utils.FileUtils;\r
-import org.simantics.utils.datastructures.Pair;\r
-import org.simantics.utils.logging.TimeLogger;\r
-\r
-/**\r
- * SimanticsPlatform performs procedures required in order to get simantics\r
- * workbench into operational state. This consists of the following steps:\r
- * <ul>\r
- * <li> Asserting there is Database\r
- * </li>\r
- * <li> Starting Database process\r
- * </li>\r
- * <li> Opening a session to Database process\r
- * </li>\r
- * <li> Asserting required ontologies or other transferable graphs are installed in the database\r
- * </li>\r
- * <li> Asserting required project is installed in the database\r
- * </li>\r
- * <li> Asserting Simantics Features are installed in the database\r
- * </li>\r
- * <li> Asserting Simantics Features are installed to the project\r
- * </li>\r
- * <li> Shutdown: Save Session, Close session, Kill Database process\r
- * </li>\r
- * </ul>\r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class SimanticsPlatform implements LifecycleListener {\r
-\r
- /**\r
- * The policy is relevant when developing Simantics from Eclipse IDE.\r
- * It is applied when the ontology in the database of a workspace doesn't match\r
- * a newer ontology in the Eclipse workspace.\r
- */\r
- public static enum OntologyRecoveryPolicy { ThrowError, Merge, ReinstallDatabase }\r
-\r
- /**\r
- * This policy dictates how the Simantics platform startup should react if\r
- * the started workspace is not set up properly. The alternatives are to\r
- * just throw an error and fail or to attempt all possible measures to fix\r
- * the encountered problems.\r
- */\r
- public static enum RecoveryPolicy { ThrowError, FixError }\r
-\r
- /** Singleton instance, started in SimanticsWorkbenchAdvisor */\r
- public static final SimanticsPlatform INSTANCE = new SimanticsPlatform();\r
-\r
- /** Set to true when the Simantics Platform is in good-and-go condition */\r
- public boolean running;\r
-\r
- /** Database Session */\r
- public Session session;\r
- private Management databasebManagement;\r
-\r
- /** Database session context */\r
- public SessionContext sessionContext;\r
-\r
- /** Project identifier in Database */\r
- public String projectURI;\r
-\r
- /** Project name */\r
- public String projectName;\r
-\r
- /** Project resource */\r
- public Resource projectResource;\r
-\r
- /** Session specific bindings */\r
- public SimanticsBindings simanticsBindings;\r
- public SimanticsBindings simanticsBindings2;\r
-\r
- public Thread mainThread;\r
-\r
- /**\r
- * The {@link IProject} activated by\r
- * {@link #startUp(IProgressMonitor, RecoveryPolicy, OntologyRecoveryPolicy, ServerAddress, PlatformUserAgent)}\r
- */\r
- private IProject project;\r
-\r
- protected ILog log;\r
-\r
- /**\r
- * Create a new simantics plaform manager in uninitialized state and\r
- * with default policies. <p>\r
- */\r
- public SimanticsPlatform() {\r
- log = Platform.getLog(Activator.getBundleContext().getBundle());\r
- mainThread = Thread.currentThread();\r
- }\r
-\r
- public String getApplicationClientId() {\r
- IProduct product = Platform.getProduct();\r
- if(product == null) return "noProduct";//UUID.randomUUID().toString();\r
- String application = product.getApplication();\r
- return application != null ? application : UUID.randomUUID().toString();\r
- }\r
-\r
- private Session setupDatabase(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, PlatformUserAgent userAgent) throws PlatformException {\r
- if (progressMonitor == null)\r
- progressMonitor = new NullProgressMonitor();\r
- File dbLocation = Platform.getLocation().append("db").toFile();\r
- ServerManager serverManager;\r
- try {\r
- serverManager = ServerManagerFactory.create(databaseDriverId, dbLocation.getAbsolutePath());\r
- } catch (DatabaseException | IOException e) {\r
- throw new PlatformException("Failed to initialize Server Manager", e);\r
- }\r
- progressMonitor.beginTask("Setting up Simantics Database", 100);\r
- progressMonitor.setTaskName("Asserting Database is installed.");\r
- String msg = "Failed to initialize Simantics database.";\r
- try {\r
- // Create database\r
- log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Creating database at " + dbLocation));\r
- progressMonitor.setTaskName("Creating database at " + dbLocation);\r
- databasebManagement = serverManager.getManagement(dbLocation);\r
- databasebManagement.create();\r
- // Create layer0.\r
- return serverManager.createDatabase(dbLocation);\r
- } catch (DatabaseException e) {\r
- throw new PlatformException(msg, e);\r
- } catch (Throwable e) {\r
- throw new PlatformException(msg, e);\r
- } finally {\r
- progressMonitor.worked(20);\r
- }\r
- }\r
-\r
- public void synchronizeOntologies(IProgressMonitor progressMonitor, OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize) throws PlatformException {\r
-\r
- if (progressMonitor == null) progressMonitor = new NullProgressMonitor();\r
-\r
- final DatabaseManagement mgmt = new DatabaseManagement();\r
-\r
- PlatformUtil.compileAllDynamicOntologies();\r
-\r
- progressMonitor.setTaskName("Asserting all ontologies are installed");\r
- final Map<GraphBundleRef, GraphBundleEx> platformTGs = new HashMap<GraphBundleRef, GraphBundleEx>();\r
- try {\r
-\r
- // Get a list of bundles installed into the database\r
- progressMonitor.subTask("find installed bundles from database");\r
- Map<GraphBundleRef, GraphBundleEx> installedTGs = new HashMap<GraphBundleRef, GraphBundleEx>();\r
- for (GraphBundle b : session.syncRequest( mgmt.GraphBundleQuery )) {\r
- installedTGs.put(GraphBundleRef.of(b), GraphBundleEx.extend(b));\r
- }\r
-\r
- if(!requireSynchronize && installedTGs.size() > 1 && !Platform.inDevelopmentMode()) return;\r
-// if(installedTGs.size() > 1) return;\r
-\r
- // Get a list of all bundles in the platform (Bundle Context)\r
- List<GraphBundle> tgs = new ArrayList<GraphBundle>();\r
- progressMonitor.subTask("load all transferable graphs from platform");\r
- PlatformUtil.getAllGraphs(tgs);\r
- progressMonitor.subTask("extend bundles to compile versions");\r
- for (GraphBundle b : tgs) {\r
- GraphBundleEx gbe = GraphBundleEx.extend(b);\r
- gbe.build();\r
- platformTGs.put(GraphBundleRef.of(b), gbe);\r
- }\r
-\r
- // Compile a list of TGs that need to be installed or reinstalled in the database\r
- progressMonitor.subTask("check bundle reinstallation demand");\r
- List<GraphBundleEx> installTGs = new ArrayList<GraphBundleEx>();\r
- // Create list of TGs to update, <newTg, oldTg>\r
- Map<GraphBundleEx,GraphBundleEx> reinstallTGs = new TreeMap<GraphBundleEx,GraphBundleEx>();\r
- for (Entry<GraphBundleRef, GraphBundleEx> e : platformTGs.entrySet()) {\r
- GraphBundleRef key = e.getKey();\r
- GraphBundleEx platformBundle = e.getValue();\r
- GraphBundleEx existingBundle = installedTGs.get(key);\r
- \r
-// System.out.println("GraphBundleRef key=" + key.toString());\r
- \r
- if (existingBundle == null) {\r
- // Bundle did not exist in the database, put it into list of bundles to install\r
- installTGs.add(platformBundle);\r
- }\r
- else {\r
- // Bundle exists in the database\r
- boolean platformBundleIsNewer = existingBundle.getVersion().compareTo(platformBundle.getVersion())<0;\r
- if (!platformBundleIsNewer)\r
- continue;\r
- // Check hash of transferable graph to know whether to update or not.\r
- if (platformBundle.getHashcode() == existingBundle.getHashcode())\r
- continue;\r
- //System.out.println("Ontology hashcodes do not match: platform bundle="\r
- // + platformBundle.getVersionedId() + ", hash=" + platformBundle.getHashcode()\r
- // + "; existing bundle=" + existingBundle.getVersionedId() + ", hash=" + existingBundle.getHashcode());\r
- reinstallTGs.put(platformBundle, existingBundle);\r
- }\r
- }\r
- // INSTALL\r
- // Database is missing graphs\r
- if (!installTGs.isEmpty() || !reinstallTGs.isEmpty()) {\r
- session.getService(XSupport.class).setServiceMode(true, true);\r
-\r
- // Throw error\r
- if (ontologyPolicy == OntologyRecoveryPolicy.ThrowError) {\r
- StringBuilder sb = new StringBuilder("The following graphs are not installed in the database: ");\r
- if (!installTGs.isEmpty()) {\r
- int i = 0;\r
- for (GraphBundleEx e : installTGs) {\r
- if (i>0) sb.append(", ");\r
- i++;\r
- sb.append(e.toString());\r
- }\r
- sb.append(" is missing from the database.\n");\r
- }\r
- if (!reinstallTGs.isEmpty()) {\r
- int i = 0;\r
- for (Entry<GraphBundleEx, GraphBundleEx> e : reinstallTGs.entrySet()) {\r
- if (i>0) sb.append(", ");\r
- i++;\r
- sb.append(e.getKey().toString());\r
- }\r
- sb.append(" Database/Platform Bundle version mismatch.\n");\r
- }\r
- sb.append("Hint: Use -fixErrors to install the graphs.");\r
- throw new PlatformException(sb.toString());\r
- }\r
- // Reinstall database\r
- if (ontologyPolicy == OntologyRecoveryPolicy.ReinstallDatabase) {\r
- log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Reinstalling the database."));\r
- // TODO Install DB\r
- // Stop Session\r
- // Kill Process\r
- // Delete Database\r
- // Create Database\r
- // Start Database\r
- // Open Session\r
- // Install TGs\r
- throw new PlatformException("Reinstalling Database, NOT IMPLEMENTED");\r
- }\r
-\r
- if (ontologyPolicy == OntologyRecoveryPolicy.Merge) {\r
- progressMonitor.subTask("Merging ontology changes");\r
- // Sort missing TGs into install order\r
- GraphDependencyAnalyzer<GraphBundle> analyzer = new GraphDependencyAnalyzer<GraphBundle>();\r
- for(GraphBundle tg : installTGs) analyzer.addGraph(tg, tg.getGraph());\r
- for(GraphBundle tg : reinstallTGs.keySet()) analyzer.addGraph(tg, tg.getGraph());\r
- if(!analyzer.analyzeDependency()) {\r
- Collection<Pair<GraphBundle, GraphBundle>> problems = analyzer.getConflicts();\r
- StringBuilder sb = new StringBuilder();\r
- for (Pair<GraphBundle, GraphBundle> problem : problems) {\r
- sb.append("Conflict with "+problem.first+" and "+problem.second+".\n");\r
- }\r
- throw new PlatformException(sb.toString());\r
- }\r
- else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) {\r
- Collection<IdentityNode> unsatisfiedDependencies = analyzer.getUnsatisfiedDependencies();\r
- StringBuilder sb = new StringBuilder();\r
- for (IdentityNode dep: unsatisfiedDependencies) {\r
- sb.append("Unsatisfied Dependency "+dep+". Required by\n");\r
- for(IU iu : GraphDependencyAnalyzer.toCollection(dep.getRequires())) {\r
- sb.append(" " + ((GraphBundle)iu.getId()).getId() + "\n");\r
- }\r
- }\r
- throw new PlatformException(sb.toString());\r
- }\r
- \r
- List<GraphBundle> sortedBundles = analyzer.getSortedGraphs();\r
- if(!sortedBundles.isEmpty()) {\r
- \r
- session.syncRequest(new WriteRequest() {\r
- @Override\r
- public void perform(WriteGraph graph) throws DatabaseException {\r
- try {\r
- graph.newClusterSet(graph.getRootLibrary());\r
- } catch (ClusterSetExistException e) {\r
- // Cluster set exist already, no problem.\r
- }\r
- graph.setClusterSet4NewResource(graph.getRootLibrary());\r
- graph.flushCluster();\r
- }\r
- });\r
-\r
- boolean mergedOntologies = false;\r
-\r
- // Install TGs\r
- for(final GraphBundle tg : sortedBundles) {\r
-\r
- final IImportAdvisor advisor = new OntologyImportAdvisor(tg, mgmt);\r
- final GraphBundle oldTG = reinstallTGs.get(tg);\r
-\r
- if (oldTG==null) {\r
- \r
- boolean createImmutable = tg.getImmutable();\r
- session.getService(XSupport.class).setServiceMode(true, createImmutable);\r
-\r
- // Install TG\r
- log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Installing "+tg.toString()+" - "+tg.getName()));\r
- TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null);\r
- } else {\r
- // Merge TG\r
- startTransaction(session, false);\r
- TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();\r
- final long[] oldResources = oldTG.getResourceArray();\r
- boolean changes = TransferableGraphs.hasChanges(readGraph(), oldResources, delta);\r
- endTransaction();\r
- if (!changes) {\r
- //log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Nothing to merge for "+tg.toString()));\r
- continue;\r
- }\r
-\r
- log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Merging new version of "+tg.toString()));\r
-\r
- startTransaction(session, true);\r
- \r
- //delta.print();\r
- try {\r
- \r
- \r
- long[] resourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResources, delta);\r
- tg.setResourceArray(resourceArray);\r
- mgmt.setGraphBundleEntry(tg);\r
- commit();\r
- mergedOntologies = true;\r
- } catch (Throwable t) {\r
- throw new PlatformException(t);\r
- } finally {\r
- endTransaction();\r
- }\r
- }\r
- }\r
- \r
- session.syncRequest(new WriteRequest() {\r
- @Override\r
- public void perform(WriteGraph graph) throws DatabaseException {\r
- graph.setClusterSet4NewResource(graph.getRootLibrary());\r
- graph.flushCluster();\r
- }\r
- });\r
-\r
- if (mergedOntologies)\r
- DatabaseIndexing.deleteAllIndexes();\r
- }\r
-\r
- TimeLogger.log("Ontologies synchronized.");\r
- \r
- }\r
- session.getService(XSupport.class).setServiceMode(false, false);\r
- }\r
- progressMonitor.worked(20);\r
- } catch (IOException e) {\r
- throw new PlatformException(e);\r
- } catch (DatabaseException e) {\r
- throw new PlatformException(e);\r
- }\r
-\r
- }\r
-\r
- public boolean assertConfiguration(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy) throws PlatformException {\r
-\r
- if (progressMonitor == null) progressMonitor = new NullProgressMonitor();\r
-\r
- File workspaceLocation = Platform.getLocation().toFile();\r
-\r
- boolean installProject = false;\r
- progressMonitor.setTaskName("Asserting simantics.cfg is installed");\r
- try {\r
- File propertyFile = new File(workspaceLocation, "simantics.cfg");\r
- Properties properties;\r
- try {\r
- properties = WorkspaceUtil.readProperties(propertyFile);\r
- } catch (IOException e) {\r
- if (workspacePolicy == RecoveryPolicy.ThrowError) throw new PlatformException("Could not load "+propertyFile);\r
-\r
- // Create a project and write Property file\r
- properties = new Properties();\r
- properties.setProperty("project_uri", "http://Projects/Development%20Project");\r
- properties.setProperty("project_name", "Development Project");\r
- WorkspaceUtil.writeProperties(propertyFile, properties);\r
- installProject |= true;\r
- }\r
- projectURI = properties.getProperty("project_uri");\r
- projectName = properties.getProperty("project_name");\r
- progressMonitor.worked(10);\r
- } catch (IOException e) {\r
- throw new PlatformException(e);\r
- }\r
-\r
- return installProject;\r
-\r
- }\r
-\r
- public boolean assertProject(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, boolean installProject) throws PlatformException {\r
-\r
- if (progressMonitor == null) progressMonitor = new NullProgressMonitor();\r
-\r
- final DatabaseManagement mgmt = new DatabaseManagement();\r
-\r
- progressMonitor.setTaskName("Asserting project resource exists in the database");\r
- try {\r
- projectResource = session.syncRequest( Queries.resource( projectURI ) );\r
- } catch (ResourceNotFoundException nfe) {\r
- // Project was not found\r
- if (workspacePolicy == RecoveryPolicy.ThrowError)\r
- throw new PlatformException("Project Resource "+projectURI+" is not found in the database.");\r
- // Create empty project with no features\r
- try {\r
- Transaction.startTransaction(session, true);\r
- try {\r
- // The project needs to be created mutable.\r
- session.getService(XSupport.class).setServiceMode(true, false);\r
-\r
- ArrayList<String> empty = new ArrayList<String>();\r
- projectResource = mgmt.createProject(projectName, empty);\r
- installProject |= true;\r
-\r
- session.getService(XSupport.class).setServiceMode(false, false);\r
- Transaction.commit();\r
- } finally {\r
- Transaction.endTransaction();\r
- }\r
- //session.getService( LifecycleSupport.class ).save();\r
- } catch (DatabaseException e) {\r
- throw new PlatformException("Failed to create "+projectURI, e);\r
- }\r
- } catch (DatabaseException e) {\r
- throw new PlatformException("Failed to create "+projectURI, e);\r
- }\r
- progressMonitor.worked(10);\r
-\r
- return installProject;\r
-\r
- }\r
-\r
- public void updateInstalledGroups(IProgressMonitor progressMonitor, boolean installProject) throws PlatformException {\r
-\r
- if (installProject)\r
- {\r
- // Attach all feature groups available in platform to created project\r
- progressMonitor.setTaskName("Install all features");\r
- Set<GroupReference> publishedFeatureGroups = ProjectFeatures.getInstallGroupsOfPublishedFeatures();\r
- Collection<GroupReference> groupsWithoutVersion = GroupReference.stripVersions(publishedFeatureGroups);\r
-\r
- // final List<String> Platform_Features = new ArrayList<String>();\r
- //\r
- // // Convert graph instances\r
- // Collection<TransferableGraph1> platformGraphs = new ArrayList<TransferableGraph1>();\r
- // for (GraphBundleEx e : platformTGs.values()) platformGraphs.add( e.getGraph() );\r
- // IGraph graph = Graphs.createGraph(platformGraphs);\r
- //\r
- // Res PublishedProjectFeatures = UriUtils.uriToPath( ProjectResource.URIs.PublishedProjectFeatures );\r
- // Path HasFeature = UriUtils.uriToPath( ProjectResource.URIs.HasFeature );\r
- // for(Res feature : graph.getObjects(PublishedProjectFeatures, HasFeature)) {\r
- // System.out.println("Installing Project Feature: "+feature.toString());\r
- // Platform_Features.add( feature.toString() );\r
- // }\r
-\r
- try {\r
- Transaction.startTransaction(session, true);\r
- try {\r
- // for (String feature : Platform_Features) {\r
- // try {\r
- // getResource(feature);\r
- // } catch(ResourceNotFoundException e) {\r
- // System.out.println(feature+" not found");\r
- // }\r
- // mgmt.installFeature(projectResource, feature);\r
- // }\r
- Projects.setProjectInstalledGroups(writeGraph(), projectResource, groupsWithoutVersion);\r
- Transaction.commit();\r
- } finally {\r
- Transaction.endTransaction();\r
- }\r
- //session.getService( LifecycleSupport.class ).save();\r
- } catch(DatabaseException ae) {\r
- throw new PlatformException("Failed to install features", ae);\r
- }\r
- progressMonitor.worked(10);\r
- }\r
-\r
- }\r
-\r
- public void assertSessionModel(IProgressMonitor progressMonitor) throws PlatformException {\r
-\r
- Properties properties = session.getService(Properties.class);\r
- final String clientId = properties.getProperty("clientId");\r
-\r
- try {\r
-\r
- // Currently this needs to be done before data becomes available\r
- VirtualGraphSupport support = session.getService(VirtualGraphSupport.class);\r
- VirtualGraph activations = support.getWorkspacePersistent("activations");\r
-\r
- Resource sessionModel = session.syncRequest(new Read<Resource>() {\r
-\r
- @Override\r
- public Resource perform(ReadGraph graph) throws DatabaseException {\r
-\r
- Layer0X L0X = Layer0X.getInstance(graph);\r
- for(Resource sessionModel : graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0X.HasSession, L0X.Session))) {\r
- String id = graph.getPossibleRelatedValue(sessionModel, L0X.Session_HasClientId);\r
- if(id != null && id.equals(clientId)) return sessionModel;\r
- }\r
- return null;\r
-\r
- }\r
-\r
- });\r
-\r
- if(sessionModel == null) {\r
-\r
- sessionModel = session.syncRequest(new WriteResultRequest<Resource>(activations) {\r
-\r
- @Override\r
- public Resource perform(WriteGraph graph) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- Layer0X L0X = Layer0X.getInstance(graph);\r
- Resource session = graph.newResource();\r
- graph.claim(session, L0.InstanceOf, null, L0X.Session);\r
- graph.claim(session, L0X.Session_HasUser, null, graph.getResource("http://Users/AdminUser"));\r
- graph.addLiteral(session, L0X.Session_HasClientId, L0X.Session_HasClientId_Inverse, clientId, Bindings.STRING);\r
- graph.claim(graph.getRootLibrary(), L0X.HasSession, session);\r
- return session;\r
- }\r
- });\r
-\r
- }\r
-\r
- session.registerService(SessionModel.class, new PlatformSessionModel(sessionModel));\r
- } catch (DatabaseException e) {\r
- throw new PlatformException(e);\r
- }\r
-\r
- }\r
-\r
- static class PlatformSessionModel implements SessionModel {\r
- private final Resource sessionModel;\r
-\r
- public PlatformSessionModel(Resource model) {\r
- this.sessionModel = model;\r
- }\r
-\r
- @Override\r
- public Resource getResource() {\r
- return sessionModel;\r
- }\r
- }\r
-\r
- public void resetDatabase(IProgressMonitor monitor) throws PlatformException {\r
- File dbLocation = Platform.getLocation().append("db").toFile();\r
- if(!dbLocation.exists()) return;\r
- try { // Load driver\r
- Driver driver = Manager.getDriver("procore");\r
- Management management = driver.getManagement(dbLocation.getAbsolutePath(), null);\r
- management.delete();\r
- } catch (DatabaseException e) {\r
- throw new PlatformException("Failed to remove database at " + dbLocation.getAbsolutePath(), e);\r
- }\r
- // We have created extra files to database folder which have to be deleted also.\r
- // This is an awful idea! Do not create extra files to database folder!\r
- Throwable t = null;\r
- for (int i=0; i<10; ++i) {\r
- try {\r
- FileUtils.deleteAll(dbLocation);\r
- t = null;\r
- break;\r
- } catch (IOException e) {\r
- // Assuming this has been thrown because delete file/folder failed.\r
- t = e;\r
- }\r
- try {\r
- Thread.sleep(200);\r
- } catch (InterruptedException e) {\r
- // Ignoring interrupted exception.\r
- }\r
- }\r
- if (null != t)\r
- throw new PlatformException("Failed to remove database folder at " + dbLocation.getAbsolutePath(), t);\r
- }\r
- public void resetWorkspace(IProgressMonitor monitor, ArrayList<String> fileFilter) throws PlatformException, IllegalStateException, IOException {\r
- File file = Platform.getLocation().toFile();\r
- if (null != fileFilter)\r
- FileUtils.deleteAllWithFilter(file , fileFilter);\r
- resetDatabase(monitor);\r
- }\r
-\r
- /**\r
- * Start-up the platform. The procedure consists of 8 steps. Once everything\r
- * is up and running, all fields are set property.\r
- * <p>\r
- *\r
- * If workspacePolicy is FixErrors, there is an attempt to fix unexpected\r
- * errors. It includes installing database files, installing ontologies, and\r
- * installing project features.\r
- * <p>\r
- *\r
- * In SWB this is handled in SimanticsWorkbenchAdvisor#openWindows().\r
- * <p>\r
- *\r
- * If remote server is given, simantics plaform takes connection there\r
- * instead of local server at "db/".\r
- *\r
- * @param workspacePolicy action to take on workspace/database related\r
- * errors\r
- * @param ontologyPolicy action to take on ontology mismatch\r
- * @param progressMonitor optional progress monitor\r
- * @param userAgent interface for resorting to user feedback during platform\r
- * startup or <code>null</code> to resort to default measures\r
- * @throws PlatformException\r
- */\r
- public SessionContext startUp(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy,\r
- OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize, PlatformUserAgent userAgent)\r
- throws PlatformException\r
- {\r
-\r
- assert(!running);\r
- TimeLogger.log("Beginning of SimanticsPlatform.startUp");\r
-\r
- if (progressMonitor == null) progressMonitor = new NullProgressMonitor();\r
-\r
- // For debugging on what kind of platform automatic tests are running in\r
- // case there are problems.\r
- if ("true".equals(System.getProperty("org.simantics.dumpBundleState")))\r
- dumpPlatformBundleState();\r
-\r
- // 0. Consult all startup extensions before doing anything with the workspace.\r
- StartupExtensions.consultStartupExtensions();\r
- TimeLogger.log("Consulted platform pre-startup extensions");\r
-\r
- // 0.1. Clear all temporary files\r
- Simantics.clearTemporaryDirectory();\r
- TimeLogger.log("Cleared temporary directory");\r
-\r
- // 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb\r
- VariableRepository.clear();\r
- \r
- // 1. Assert there is a database at <workspace>/db\r
- session = setupDatabase(databaseDriverId, progressMonitor, workspacePolicy, userAgent);\r
- TimeLogger.log("Database setup complete");\r
- \r
- // 1.1 \r
- XSupport support = session.getService(XSupport.class);\r
- if (support.rolledback()) {\r
- try {\r
- DatabaseIndexing.deleteAllIndexes();\r
- } catch (IOException e) {\r
- throw new PlatformException(e);\r
- }\r
- }\r
- \r
- // 2. Assert all graphs, and correct versions, are installed to the database\r
- synchronizeOntologies(progressMonitor, ontologyPolicy, requireSynchronize);\r
- TimeLogger.log("Synchronized ontologies");\r
-\r
- // 4. Assert simantics.cfg exists\r
- boolean installProject = assertConfiguration(progressMonitor,workspacePolicy);\r
-\r
- // 5. Assert Project Resource is installed in the database\r
- installProject = assertProject(progressMonitor, workspacePolicy, installProject);\r
-\r
- // 6. Install all features into project, if in debug mode\r
- updateInstalledGroups(progressMonitor, installProject);\r
- TimeLogger.log("Installed all features into project");\r
-\r
- // 7. Assert L0.Session in database for this session\r
- assertSessionModel(progressMonitor);\r
-\r
- session.getService(XSupport.class).setServiceMode(false, false);\r
-\r
- try {\r
- session.sync(new WriteRequest() {\r
-\r
- @Override\r
- public void perform(WriteGraph graph) throws DatabaseException {\r
- QueryControl qc = graph.getService(QueryControl.class);\r
- qc.flush(graph);\r
- }\r
-\r
- });\r
- TimeLogger.log("Flushed queries");\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
- boolean loadProject = true;\r
- try {\r
-\r
- sessionContext = SimanticsPlatform.INSTANCE.createSessionContext(true);\r
- // This must be before setSessionContext since some listeners might query this\r
- sessionContext.setHint(SimanticsKeys.KEY_PROJECT, SimanticsPlatform.INSTANCE.projectResource);\r
-\r
- Simantics.setSessionContext(sessionContext);\r
-\r
- // 1. Put ResourceBinding that throws an exception to General Bindings\r
- simanticsBindings = new SimanticsBindings( null );\r
- Bindings.classBindingFactory.addFactory( simanticsBindings );\r
-\r
-\r
- // 2. Create session-specific second Binding context (Databoard) and\r
- // put that to Session as a service\r
- Session session = sessionContext.getSession();\r
- Databoard sessionDataboard = new Databoard();\r
- session.registerService(Databoard.class, sessionDataboard);\r
- simanticsBindings2 = new SimanticsBindings( session );\r
- sessionDataboard.classBindingFactory.addFactory( simanticsBindings2 );\r
-\r
- // Register datatype bindings\r
- Bindings.defaultBindingFactory.getRepository().put(RGB.Integer.BINDING.type(), RGB.Integer.BINDING);\r
- Bindings.defaultBindingFactory.getRepository().put(Font.BINDING.type(), Font.BINDING);\r
-\r
- if(loadProject) {\r
-\r
- TimeLogger.log("Load projects");\r
- project = Projects.loadProject(sessionContext.getSession(), SimanticsPlatform.INSTANCE.projectResource);\r
-\r
- sessionContext.setHint(ProjectKeys.KEY_PROJECT, project);\r
- TimeLogger.log("Loading projects complete");\r
-\r
- project.activate();\r
- TimeLogger.log("Project activated");\r
- }\r
-\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- throw new PlatformException(e);\r
- } catch (ProjectException e) {\r
- boolean hasStackTrace = e.getStackTrace().length > 0;\r
- if (!hasStackTrace)\r
- throw new PlatformException(e.getMessage(), hasStackTrace);\r
- throw new PlatformException(e, hasStackTrace);\r
- }\r
-\r
- running = true;\r
-\r
- return sessionContext;\r
-\r
- }\r
-\r
- public SessionContext createSessionContext(boolean init) throws PlatformException {\r
- try {\r
- // Construct and initialize SessionContext from Session.\r
- SessionContext sessionContext = SessionContext.create(session, init);\r
- if (init)\r
- sessionContext.registerServices();\r
- return sessionContext;\r
- } catch (DatabaseException e) {\r
- throw new PlatformException(e);\r
- }\r
- }\r
-\r
-// private static File getIgnorePrerequisitesFile(URL workspaceUrl) {\r
-// if (workspaceUrl == null)\r
-// return null;\r
-// return new File(workspaceUrl.getPath(), ".ignorePrerequisites");\r
-// }\r
-//\r
-// private void ensurePrerequisites(IProgressMonitor progressMonitor, PlatformUserAgent userAgent) throws PlatformException {\r
-// Location loc = Platform.getInstanceLocation();\r
-// File ignorePrerequisites = getIgnorePrerequisitesFile(loc.getURL());\r
-// if (loc.isSet() && ignorePrerequisites != null) {\r
-// if (ignorePrerequisites.exists() || ignorePrerequisites.isFile())\r
-// return;\r
-// }\r
-//\r
-// try {\r
-// ServerEnvironment.ensureServerDependenciesMet();\r
-// } catch (ExecutionEnvironmentException e) {\r
-// // Not installed properly, ask user whether to try installation.\r
-// try {\r
-// StringBuilder msg = new StringBuilder();\r
-// msg.append("Your system seems to be missing the following prerequisites for running this application:\n\n");\r
-// for (Product product : e.requiredProducts)\r
-// msg.append("\t" + product.getDescription() + "\n");\r
-// msg.append("\nYou can either install the missing components now or ignore and attempt to start the application without them. Ignore Always will ignore this question for this workspace.");\r
-// msg.append("\n\nSelecting Cancel will close the application.");\r
-//\r
-// int selection = 0;\r
-// if (userAgent != null) {\r
-// selection = userAgent.showPrompt("Missing Prerequisites", msg.toString(), new String[] {\r
-// "Install Pre-requisites",\r
-// "Ignore Now",\r
-// "Ignore Always",\r
-// "Cancel"\r
-// }, selection);\r
-// }\r
-// boolean tryInstall = false;\r
-// switch (selection) {\r
-// case 0:\r
-// tryInstall = true;\r
-// break;\r
-// case 2:\r
-// ignorePrerequisites.createNewFile();\r
-// case 1:\r
-// break;\r
-// case 3:\r
-// case -1:\r
-// throw new CancelStartupException();\r
-// }\r
-//\r
-// if (tryInstall) {\r
-// // Try to install it and check for success afterwards.\r
-// ServerEnvironment.tryInstallDependencies(progressMonitor);\r
-// ServerEnvironment.ensureServerDependenciesMet();\r
-// }\r
-// } catch (InstallException ie) {\r
-// throw new PlatformException(ie);\r
-// } catch (ExecutionEnvironmentException eee) {\r
-// throw new PlatformException(eee);\r
-// } catch (IOException ie) {\r
-// throw new PlatformException(ie);\r
-// }\r
-// }\r
-// }\r
-\r
- /**\r
- * Shutdown Simantics Platform.\r
- *\r
- * In SWB this is handled in SimanticsWorkbenchAdvisor#disconnectFromWorkspace.\r
- *\r
- * @param progressMonitor optional progress monitor\r
- * @throws PlatformException\r
- */\r
- public void shutdown(IProgressMonitor progressMonitor) throws PlatformException\r
- {\r
- SubMonitor progress = SubMonitor.convert(progressMonitor, 100);\r
- PlatformException platformException = null;\r
- try {\r
- progress.subTask("Close Project");\r
- if (project != null) {\r
- project.safeDispose();\r
- }\r
- progress.worked(10);\r
-\r
- running = false;\r
- progress.subTask("Close Database Session");\r
- Databoard databoard = null;\r
- if (sessionContext != null) {\r
- Session s = sessionContext.peekSession();\r
- if (s != null) {\r
- databoard = s.peekService(Databoard.class);\r
-\r
- progress.subTask("Flushing Index Caches");\r
- try {\r
- Simantics.flushIndexCaches(progress.newChild(20), s);\r
- } catch (Throwable t) {\r
- Logger.defaultLogError(t);\r
- }\r
- }\r
-\r
- progress.subTask("Close Database Session");\r
- sessionContext.safeDispose();\r
- sessionContext = null;\r
- Simantics.setSessionContext(null);\r
- }\r
- if (simanticsBindings != null) {\r
- Bindings.classBindingFactory.removeFactory( simanticsBindings );\r
- simanticsBindings = null;\r
- }\r
- if (databoard != null) {\r
- if (simanticsBindings2 != null) {\r
- databoard.classBindingFactory.removeFactory( simanticsBindings2 );\r
- simanticsBindings2 = null;\r
- }\r
- databoard.clear();\r
- }\r
-\r
- // Make sure Simantics clipboard doesn't store unwanted session data references.\r
- Simantics.setClipboard(new SimanticsClipboardImpl());\r
-\r
- progress.worked(30);\r
-\r
- session = null;\r
- projectResource = null;\r
-\r
- DependenciesRelation.assertFinishedTracking();\r
-\r
- } catch (Exception e) {\r
- platformException = new PlatformException("Failed to shutdown Simantics Platform", e);\r
- }\r
-\r
- progress.worked(10);\r
- progress.subTask("Shutting down database");\r
- try {\r
- if (null != databasebManagement)\r
- databasebManagement.shutdown();\r
- } catch (Throwable t) {\r
- Logger.defaultLogError(t);\r
- }\r
- progress.worked(10);\r
-\r
- progress.subTask("Clearing Workspace Temporary Directory");\r
- try {\r
- Simantics.clearTemporaryDirectory();\r
- } catch (Throwable t) {\r
- Logger.defaultLogError(t);\r
- }\r
- progress.worked(10);\r
- if (null != platformException)\r
- throw platformException;\r
- }\r
-\r
- // TODO: consider removing this in the future ??\r
- @Override\r
- public void stateChanged(LifecycleState newState) {\r
- if(newState == LifecycleState.CLOSED) {\r
- if(running) {\r
- if(Platform.isRunning()) {\r
- mainThread.interrupt();\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * @return <code>true</code> if discard was successful, <code>false</code>\r
- * if there was no session, {@link UndoRedoSupport} or\r
- * {@link UndoContext} to discard through\r
- */\r
- public boolean discardSessionUndoHistory() {\r
- Session s = session;\r
- if (s != null) {\r
- UndoRedoSupport urs = s.peekService(UndoRedoSupport.class);\r
- if (urs != null) {\r
- UndoContext uc = urs.getUndoContext(s);\r
- if (uc != null) {\r
- uc.clear();\r
- return true;\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- public void reconnect(String databaseDriverId) throws Exception {\r
- // Starts database server.\r
- SimanticsPlatform.INSTANCE.startUp(databaseDriverId, null, RecoveryPolicy.ThrowError, OntologyRecoveryPolicy.ThrowError, true, null);\r
- }\r
-\r
- private void dumpPlatformBundleState() {\r
- BundleDescription[] bs = Platform.getPlatformAdmin().getState().getBundles();\r
- System.out.println("Total bundles: " + bs.length);\r
- for (BundleDescription b : bs) {\r
- System.out.format("%-80s @ %s\n", b.toString(), b.getLocation());\r
- }\r
- }\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;
+
+import static org.simantics.db.common.utils.Transaction.commit;
+import static org.simantics.db.common.utils.Transaction.endTransaction;
+import static org.simantics.db.common.utils.Transaction.readGraph;
+import static org.simantics.db.common.utils.Transaction.startTransaction;
+import static org.simantics.db.common.utils.Transaction.writeGraph;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Databoard;
+import org.simantics.datatypes.literal.Font;
+import org.simantics.datatypes.literal.RGB;
+import org.simantics.db.Driver;
+import org.simantics.db.Driver.Management;
+import org.simantics.db.Manager;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.SessionModel;
+import org.simantics.db.UndoContext;
+import org.simantics.db.VirtualGraph;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.Queries;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Transaction;
+import org.simantics.db.exception.ClusterSetExistException;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.ResourceNotFoundException;
+import org.simantics.db.indexing.DatabaseIndexing;
+import org.simantics.db.layer0.genericrelation.DependenciesRelation;
+import org.simantics.db.layer0.util.SimanticsClipboardImpl;
+import org.simantics.db.layer0.util.SimanticsKeys;
+import org.simantics.db.layer0.util.TGTransferableGraphSource;
+import org.simantics.db.layer0.variable.VariableRepository;
+import org.simantics.db.management.SessionContext;
+import org.simantics.db.request.Read;
+import org.simantics.db.service.LifecycleSupport.LifecycleListener;
+import org.simantics.db.service.LifecycleSupport.LifecycleState;
+import org.simantics.db.service.QueryControl;
+import org.simantics.db.service.UndoRedoSupport;
+import org.simantics.db.service.VirtualGraphSupport;
+import org.simantics.db.service.XSupport;
+import org.simantics.graph.db.GraphDependencyAnalyzer;
+import org.simantics.graph.db.GraphDependencyAnalyzer.IU;
+import org.simantics.graph.db.GraphDependencyAnalyzer.IdentityNode;
+import org.simantics.graph.db.IImportAdvisor;
+import org.simantics.graph.db.TransferableGraphs;
+import org.simantics.graph.diff.Diff;
+import org.simantics.graph.diff.TransferableGraphDelta1;
+import org.simantics.internal.Activator;
+import org.simantics.internal.startup.StartupExtensions;
+import org.simantics.layer0.Layer0;
+import org.simantics.operation.Layer0X;
+import org.simantics.project.IProject;
+import org.simantics.project.ProjectFeatures;
+import org.simantics.project.ProjectKeys;
+import org.simantics.project.Projects;
+import org.simantics.project.exception.ProjectException;
+import org.simantics.project.features.registry.GroupReference;
+import org.simantics.project.management.DatabaseManagement;
+import org.simantics.project.management.GraphBundle;
+import org.simantics.project.management.GraphBundleEx;
+import org.simantics.project.management.GraphBundleRef;
+import org.simantics.project.management.PlatformUtil;
+import org.simantics.project.management.ServerManager;
+import org.simantics.project.management.ServerManagerFactory;
+import org.simantics.project.management.WorkspaceUtil;
+import org.simantics.utils.FileUtils;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.logging.TimeLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SimanticsPlatform performs procedures required in order to get simantics
+ * workbench into operational state. This consists of the following steps:
+ * <ul>
+ * <li> Asserting there is Database
+ * </li>
+ * <li> Starting Database process
+ * </li>
+ * <li> Opening a session to Database process
+ * </li>
+ * <li> Asserting required ontologies or other transferable graphs are installed in the database
+ * </li>
+ * <li> Asserting required project is installed in the database
+ * </li>
+ * <li> Asserting Simantics Features are installed in the database
+ * </li>
+ * <li> Asserting Simantics Features are installed to the project
+ * </li>
+ * <li> Shutdown: Save Session, Close session, Kill Database process
+ * </li>
+ * </ul>
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class SimanticsPlatform implements LifecycleListener {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SimanticsPlatform.class);
+
+ /**
+ * The policy is relevant when developing Simantics from Eclipse IDE.
+ * It is applied when the ontology in the database of a workspace doesn't match
+ * a newer ontology in the Eclipse workspace.
+ */
+ public static enum OntologyRecoveryPolicy { ThrowError, Merge, ReinstallDatabase }
+
+ /**
+ * This policy dictates how the Simantics platform startup should react if
+ * the started workspace is not set up properly. The alternatives are to
+ * just throw an error and fail or to attempt all possible measures to fix
+ * the encountered problems.
+ */
+ public static enum RecoveryPolicy { ThrowError, FixError }
+
+ /** Singleton instance, started in SimanticsWorkbenchAdvisor */
+ public static final SimanticsPlatform INSTANCE = new SimanticsPlatform();
+
+ /** Set to true when the Simantics Platform is in good-and-go condition */
+ public boolean running;
+
+ /** Database Session */
+ public Session session;
+ private Management databasebManagement;
+
+ /** Database session context */
+ public SessionContext sessionContext;
+
+ /** Project identifier in Database */
+ public String projectURI;
+
+ /** Project name */
+ public String projectName;
+
+ /** Project resource */
+ public Resource projectResource;
+
+ /** Session specific bindings */
+ public SimanticsBindings simanticsBindings;
+ public SimanticsBindings simanticsBindings2;
+
+ public Thread mainThread;
+
+ /**
+ * The {@link IProject} activated by
+ * {@link #startUp(IProgressMonitor, RecoveryPolicy, OntologyRecoveryPolicy, ServerAddress, PlatformUserAgent)}
+ */
+ private IProject project;
+
+ protected ILog log;
+
+ /**
+ * Create a new simantics plaform manager in uninitialized state and
+ * with default policies. <p>
+ */
+ public SimanticsPlatform() {
+ log = Platform.getLog(Activator.getBundleContext().getBundle());
+ mainThread = Thread.currentThread();
+ }
+
+ public String getApplicationClientId() {
+ IProduct product = Platform.getProduct();
+ if(product == null) return "noProduct";//UUID.randomUUID().toString();
+ String application = product.getApplication();
+ return application != null ? application : UUID.randomUUID().toString();
+ }
+
+ private Session setupDatabase(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, PlatformUserAgent userAgent) throws PlatformException {
+ if (progressMonitor == null)
+ progressMonitor = new NullProgressMonitor();
+ File dbLocation = Platform.getLocation().append("db").toFile();
+ ServerManager serverManager;
+ try {
+ serverManager = ServerManagerFactory.create(databaseDriverId, dbLocation.getAbsolutePath());
+ } catch (DatabaseException | IOException e) {
+ throw new PlatformException("Failed to initialize Server Manager", e);
+ }
+ progressMonitor.beginTask("Setting up Simantics Database", 100);
+ progressMonitor.setTaskName("Asserting Database is installed.");
+ String msg = "Failed to initialize Simantics database.";
+ try {
+ // Create database
+ log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Creating database at " + dbLocation));
+ progressMonitor.setTaskName("Creating database at " + dbLocation);
+ databasebManagement = serverManager.getManagement(dbLocation);
+ databasebManagement.create();
+ // Create layer0.
+ return serverManager.createDatabase(dbLocation);
+ } catch (DatabaseException e) {
+ throw new PlatformException(msg, e);
+ } catch (Throwable e) {
+ throw new PlatformException(msg, e);
+ } finally {
+ progressMonitor.worked(20);
+ }
+ }
+
+ public void synchronizeOntologies(IProgressMonitor progressMonitor, OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize) throws PlatformException {
+
+ if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
+
+ final DatabaseManagement mgmt = new DatabaseManagement();
+
+ PlatformUtil.compileAllDynamicOntologies();
+
+ progressMonitor.setTaskName("Asserting all ontologies are installed");
+ final Map<GraphBundleRef, GraphBundleEx> platformTGs = new HashMap<GraphBundleRef, GraphBundleEx>();
+ try {
+
+ // Get a list of bundles installed into the database
+ progressMonitor.subTask("find installed bundles from database");
+ Map<GraphBundleRef, GraphBundleEx> installedTGs = new HashMap<GraphBundleRef, GraphBundleEx>();
+ for (GraphBundle b : session.syncRequest( mgmt.GraphBundleQuery )) {
+ installedTGs.put(GraphBundleRef.of(b), GraphBundleEx.extend(b));
+ }
+
+ if(!requireSynchronize && installedTGs.size() > 1 && !Platform.inDevelopmentMode()) return;
+// if(installedTGs.size() > 1) return;
+
+ // Get a list of all bundles in the platform (Bundle Context)
+ List<GraphBundle> tgs = new ArrayList<GraphBundle>();
+ progressMonitor.subTask("load all transferable graphs from platform");
+ PlatformUtil.getAllGraphs(tgs);
+ progressMonitor.subTask("extend bundles to compile versions");
+ for (GraphBundle b : tgs) {
+ GraphBundleEx gbe = GraphBundleEx.extend(b);
+ gbe.build();
+ platformTGs.put(GraphBundleRef.of(b), gbe);
+ }
+
+ // Compile a list of TGs that need to be installed or reinstalled in the database
+ progressMonitor.subTask("check bundle reinstallation demand");
+ List<GraphBundleEx> installTGs = new ArrayList<GraphBundleEx>();
+ // Create list of TGs to update, <newTg, oldTg>
+ Map<GraphBundleEx,GraphBundleEx> reinstallTGs = new TreeMap<GraphBundleEx,GraphBundleEx>();
+ for (Entry<GraphBundleRef, GraphBundleEx> e : platformTGs.entrySet()) {
+ GraphBundleRef key = e.getKey();
+ GraphBundleEx platformBundle = e.getValue();
+ GraphBundleEx existingBundle = installedTGs.get(key);
+
+// System.out.println("GraphBundleRef key=" + key.toString());
+
+ if (existingBundle == null) {
+ // Bundle did not exist in the database, put it into list of bundles to install
+ installTGs.add(platformBundle);
+ }
+ else {
+ // Bundle exists in the database
+ boolean platformBundleIsNewer = existingBundle.getVersion().compareTo(platformBundle.getVersion())<0;
+ if (!platformBundleIsNewer)
+ continue;
+ // Check hash of transferable graph to know whether to update or not.
+ if (platformBundle.getHashcode() == existingBundle.getHashcode())
+ continue;
+ //System.out.println("Ontology hashcodes do not match: platform bundle="
+ // + platformBundle.getVersionedId() + ", hash=" + platformBundle.getHashcode()
+ // + "; existing bundle=" + existingBundle.getVersionedId() + ", hash=" + existingBundle.getHashcode());
+ reinstallTGs.put(platformBundle, existingBundle);
+ }
+ }
+ // INSTALL
+ // Database is missing graphs
+ if (!installTGs.isEmpty() || !reinstallTGs.isEmpty()) {
+ session.getService(XSupport.class).setServiceMode(true, true);
+
+ // Throw error
+ if (ontologyPolicy == OntologyRecoveryPolicy.ThrowError) {
+ StringBuilder sb = new StringBuilder("The following graphs are not installed in the database: ");
+ if (!installTGs.isEmpty()) {
+ int i = 0;
+ for (GraphBundleEx e : installTGs) {
+ if (i>0) sb.append(", ");
+ i++;
+ sb.append(e.toString());
+ }
+ sb.append(" is missing from the database.\n");
+ }
+ if (!reinstallTGs.isEmpty()) {
+ int i = 0;
+ for (Entry<GraphBundleEx, GraphBundleEx> e : reinstallTGs.entrySet()) {
+ if (i>0) sb.append(", ");
+ i++;
+ sb.append(e.getKey().toString());
+ }
+ sb.append(" Database/Platform Bundle version mismatch.\n");
+ }
+ sb.append("Hint: Use -fixErrors to install the graphs.");
+ throw new PlatformException(sb.toString());
+ }
+ // Reinstall database
+ if (ontologyPolicy == OntologyRecoveryPolicy.ReinstallDatabase) {
+ log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Reinstalling the database."));
+ // TODO Install DB
+ // Stop Session
+ // Kill Process
+ // Delete Database
+ // Create Database
+ // Start Database
+ // Open Session
+ // Install TGs
+ throw new PlatformException("Reinstalling Database, NOT IMPLEMENTED");
+ }
+
+ if (ontologyPolicy == OntologyRecoveryPolicy.Merge) {
+ progressMonitor.subTask("Merging ontology changes");
+ // Sort missing TGs into install order
+ GraphDependencyAnalyzer<GraphBundle> analyzer = new GraphDependencyAnalyzer<GraphBundle>();
+ for(GraphBundle tg : installTGs) analyzer.addGraph(tg, tg.getGraph());
+ for(GraphBundle tg : reinstallTGs.keySet()) analyzer.addGraph(tg, tg.getGraph());
+ if(!analyzer.analyzeDependency()) {
+ Collection<Pair<GraphBundle, GraphBundle>> problems = analyzer.getConflicts();
+ StringBuilder sb = new StringBuilder();
+ for (Pair<GraphBundle, GraphBundle> problem : problems) {
+ sb.append("Conflict with "+problem.first+" and "+problem.second+".\n");
+ }
+ throw new PlatformException(sb.toString());
+ }
+ else if(!session.syncRequest( analyzer.queryExternalDependenciesSatisfied )) {
+ Collection<IdentityNode> unsatisfiedDependencies = analyzer.getUnsatisfiedDependencies();
+ StringBuilder sb = new StringBuilder();
+ for (IdentityNode dep: unsatisfiedDependencies) {
+ sb.append("Unsatisfied Dependency "+dep+". Required by\n");
+ for(IU iu : GraphDependencyAnalyzer.toCollection(dep.getRequires())) {
+ sb.append(" " + ((GraphBundle)iu.getId()).getId() + "\n");
+ }
+ }
+ throw new PlatformException(sb.toString());
+ }
+
+ List<GraphBundle> sortedBundles = analyzer.getSortedGraphs();
+ if(!sortedBundles.isEmpty()) {
+
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ try {
+ graph.newClusterSet(graph.getRootLibrary());
+ } catch (ClusterSetExistException e) {
+ // Cluster set exist already, no problem.
+ }
+ graph.setClusterSet4NewResource(graph.getRootLibrary());
+ graph.flushCluster();
+ }
+ });
+
+ boolean mergedOntologies = false;
+
+ // Install TGs
+ for(final GraphBundle tg : sortedBundles) {
+
+ final IImportAdvisor advisor = new OntologyImportAdvisor(tg, mgmt);
+ final GraphBundle oldTG = reinstallTGs.get(tg);
+
+ if (oldTG==null) {
+
+ boolean createImmutable = tg.getImmutable();
+ session.getService(XSupport.class).setServiceMode(true, createImmutable);
+
+ // Install TG
+ log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Installing "+tg.toString()+" - "+tg.getName()));
+ TransferableGraphs.importGraph1(session, new TGTransferableGraphSource(tg.getGraph()), advisor, null);
+ } else {
+ // Merge TG
+ startTransaction(session, false);
+ TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();
+ final long[] oldResources = oldTG.getResourceArray();
+ boolean changes = TransferableGraphs.hasChanges(readGraph(), oldResources, delta);
+ endTransaction();
+ if (!changes) {
+ //log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Nothing to merge for "+tg.toString()));
+ continue;
+ }
+
+ log.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, "Merging new version of "+tg.toString()));
+
+ startTransaction(session, true);
+
+ //delta.print();
+ try {
+
+
+ long[] resourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResources, delta);
+ tg.setResourceArray(resourceArray);
+ mgmt.setGraphBundleEntry(tg);
+ commit();
+ mergedOntologies = true;
+ } catch (Throwable t) {
+ throw new PlatformException(t);
+ } finally {
+ endTransaction();
+ }
+ }
+ }
+
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ graph.setClusterSet4NewResource(graph.getRootLibrary());
+ graph.flushCluster();
+ }
+ });
+
+ if (mergedOntologies)
+ DatabaseIndexing.deleteAllIndexes();
+ }
+
+ TimeLogger.log("Ontologies synchronized.");
+
+ }
+ session.getService(XSupport.class).setServiceMode(false, false);
+ }
+ progressMonitor.worked(20);
+ } catch (IOException e) {
+ throw new PlatformException(e);
+ } catch (DatabaseException e) {
+ throw new PlatformException(e);
+ }
+
+ }
+
+ public boolean assertConfiguration(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy) throws PlatformException {
+
+ if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
+
+ File workspaceLocation = Platform.getLocation().toFile();
+
+ boolean installProject = false;
+ progressMonitor.setTaskName("Asserting simantics.cfg is installed");
+ try {
+ File propertyFile = new File(workspaceLocation, "simantics.cfg");
+ Properties properties;
+ try {
+ properties = WorkspaceUtil.readProperties(propertyFile);
+ } catch (IOException e) {
+ if (workspacePolicy == RecoveryPolicy.ThrowError) throw new PlatformException("Could not load "+propertyFile);
+
+ // Create a project and write Property file
+ properties = new Properties();
+ properties.setProperty("project_uri", "http://Projects/Development%20Project");
+ properties.setProperty("project_name", "Development Project");
+ WorkspaceUtil.writeProperties(propertyFile, properties);
+ installProject |= true;
+ }
+ projectURI = properties.getProperty("project_uri");
+ projectName = properties.getProperty("project_name");
+ progressMonitor.worked(10);
+ } catch (IOException e) {
+ throw new PlatformException(e);
+ }
+
+ return installProject;
+
+ }
+
+ public boolean assertProject(IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy, boolean installProject) throws PlatformException {
+
+ if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
+
+ final DatabaseManagement mgmt = new DatabaseManagement();
+
+ progressMonitor.setTaskName("Asserting project resource exists in the database");
+ try {
+ projectResource = session.syncRequest( Queries.resource( projectURI ) );
+ } catch (ResourceNotFoundException nfe) {
+ // Project was not found
+ if (workspacePolicy == RecoveryPolicy.ThrowError)
+ throw new PlatformException("Project Resource "+projectURI+" is not found in the database.");
+ // Create empty project with no features
+ try {
+ Transaction.startTransaction(session, true);
+ try {
+ // The project needs to be created mutable.
+ session.getService(XSupport.class).setServiceMode(true, false);
+
+ ArrayList<String> empty = new ArrayList<String>();
+ projectResource = mgmt.createProject(projectName, empty);
+ installProject |= true;
+
+ session.getService(XSupport.class).setServiceMode(false, false);
+ Transaction.commit();
+ } finally {
+ Transaction.endTransaction();
+ }
+ //session.getService( LifecycleSupport.class ).save();
+ } catch (DatabaseException e) {
+ throw new PlatformException("Failed to create "+projectURI, e);
+ }
+ } catch (DatabaseException e) {
+ throw new PlatformException("Failed to create "+projectURI, e);
+ }
+ progressMonitor.worked(10);
+
+ return installProject;
+
+ }
+
+ public void updateInstalledGroups(IProgressMonitor progressMonitor, boolean installProject) throws PlatformException {
+
+ if (installProject)
+ {
+ // Attach all feature groups available in platform to created project
+ progressMonitor.setTaskName("Install all features");
+ Set<GroupReference> publishedFeatureGroups = ProjectFeatures.getInstallGroupsOfPublishedFeatures();
+ Collection<GroupReference> groupsWithoutVersion = GroupReference.stripVersions(publishedFeatureGroups);
+
+ // final List<String> Platform_Features = new ArrayList<String>();
+ //
+ // // Convert graph instances
+ // Collection<TransferableGraph1> platformGraphs = new ArrayList<TransferableGraph1>();
+ // for (GraphBundleEx e : platformTGs.values()) platformGraphs.add( e.getGraph() );
+ // IGraph graph = Graphs.createGraph(platformGraphs);
+ //
+ // Res PublishedProjectFeatures = UriUtils.uriToPath( ProjectResource.URIs.PublishedProjectFeatures );
+ // Path HasFeature = UriUtils.uriToPath( ProjectResource.URIs.HasFeature );
+ // for(Res feature : graph.getObjects(PublishedProjectFeatures, HasFeature)) {
+ // System.out.println("Installing Project Feature: "+feature.toString());
+ // Platform_Features.add( feature.toString() );
+ // }
+
+ try {
+ Transaction.startTransaction(session, true);
+ try {
+ // for (String feature : Platform_Features) {
+ // try {
+ // getResource(feature);
+ // } catch(ResourceNotFoundException e) {
+ // System.out.println(feature+" not found");
+ // }
+ // mgmt.installFeature(projectResource, feature);
+ // }
+ Projects.setProjectInstalledGroups(writeGraph(), projectResource, groupsWithoutVersion);
+ Transaction.commit();
+ } finally {
+ Transaction.endTransaction();
+ }
+ //session.getService( LifecycleSupport.class ).save();
+ } catch(DatabaseException ae) {
+ throw new PlatformException("Failed to install features", ae);
+ }
+ progressMonitor.worked(10);
+ }
+
+ }
+
+ public void assertSessionModel(IProgressMonitor progressMonitor) throws PlatformException {
+
+ Properties properties = session.getService(Properties.class);
+ final String clientId = properties.getProperty("clientId");
+
+ try {
+
+ // Currently this needs to be done before data becomes available
+ VirtualGraphSupport support = session.getService(VirtualGraphSupport.class);
+ VirtualGraph activations = support.getWorkspacePersistent("activations");
+
+ Resource sessionModel = session.syncRequest(new Read<Resource>() {
+
+ @Override
+ public Resource perform(ReadGraph graph) throws DatabaseException {
+
+ Layer0X L0X = Layer0X.getInstance(graph);
+ for(Resource sessionModel : graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0X.HasSession, L0X.Session))) {
+ String id = graph.getPossibleRelatedValue(sessionModel, L0X.Session_HasClientId);
+ if(id != null && id.equals(clientId)) return sessionModel;
+ }
+ return null;
+
+ }
+
+ });
+
+ if(sessionModel == null) {
+
+ sessionModel = session.syncRequest(new WriteResultRequest<Resource>(activations) {
+
+ @Override
+ public Resource perform(WriteGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Layer0X L0X = Layer0X.getInstance(graph);
+ Resource session = graph.newResource();
+ graph.claim(session, L0.InstanceOf, null, L0X.Session);
+ graph.claim(session, L0X.Session_HasUser, null, graph.getResource("http://Users/AdminUser"));
+ graph.addLiteral(session, L0X.Session_HasClientId, L0X.Session_HasClientId_Inverse, clientId, Bindings.STRING);
+ graph.claim(graph.getRootLibrary(), L0X.HasSession, session);
+ return session;
+ }
+ });
+
+ }
+
+ session.registerService(SessionModel.class, new PlatformSessionModel(sessionModel));
+ } catch (DatabaseException e) {
+ throw new PlatformException(e);
+ }
+
+ }
+
+ static class PlatformSessionModel implements SessionModel {
+ private final Resource sessionModel;
+
+ public PlatformSessionModel(Resource model) {
+ this.sessionModel = model;
+ }
+
+ @Override
+ public Resource getResource() {
+ return sessionModel;
+ }
+ }
+
+ public void resetDatabase(IProgressMonitor monitor) throws PlatformException {
+ File dbLocation = Platform.getLocation().append("db").toFile();
+ if(!dbLocation.exists()) return;
+ try { // Load driver
+ Driver driver = Manager.getDriver("procore");
+ Management management = driver.getManagement(dbLocation.getAbsolutePath(), null);
+ management.delete();
+ } catch (DatabaseException e) {
+ throw new PlatformException("Failed to remove database at " + dbLocation.getAbsolutePath(), e);
+ }
+ // We have created extra files to database folder which have to be deleted also.
+ // This is an awful idea! Do not create extra files to database folder!
+ Throwable t = null;
+ for (int i=0; i<10; ++i) {
+ try {
+ FileUtils.deleteAll(dbLocation);
+ t = null;
+ break;
+ } catch (IOException e) {
+ // Assuming this has been thrown because delete file/folder failed.
+ t = e;
+ }
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ // Ignoring interrupted exception.
+ }
+ }
+ if (null != t)
+ throw new PlatformException("Failed to remove database folder at " + dbLocation.getAbsolutePath(), t);
+ }
+ public void resetWorkspace(IProgressMonitor monitor, ArrayList<String> fileFilter) throws PlatformException, IllegalStateException, IOException {
+ File file = Platform.getLocation().toFile();
+ if (null != fileFilter)
+ FileUtils.deleteAllWithFilter(file , fileFilter);
+ resetDatabase(monitor);
+ }
+
+ /**
+ * Start-up the platform. The procedure consists of 8 steps. Once everything
+ * is up and running, all fields are set property.
+ * <p>
+ *
+ * If workspacePolicy is FixErrors, there is an attempt to fix unexpected
+ * errors. It includes installing database files, installing ontologies, and
+ * installing project features.
+ * <p>
+ *
+ * In SWB this is handled in SimanticsWorkbenchAdvisor#openWindows().
+ * <p>
+ *
+ * If remote server is given, simantics plaform takes connection there
+ * instead of local server at "db/".
+ *
+ * @param workspacePolicy action to take on workspace/database related
+ * errors
+ * @param ontologyPolicy action to take on ontology mismatch
+ * @param progressMonitor optional progress monitor
+ * @param userAgent interface for resorting to user feedback during platform
+ * startup or <code>null</code> to resort to default measures
+ * @throws PlatformException
+ */
+ public SessionContext startUp(String databaseDriverId, IProgressMonitor progressMonitor, RecoveryPolicy workspacePolicy,
+ OntologyRecoveryPolicy ontologyPolicy, boolean requireSynchronize, PlatformUserAgent userAgent)
+ throws PlatformException
+ {
+
+ assert(!running);
+ TimeLogger.log("Beginning of SimanticsPlatform.startUp");
+
+ LOGGER.info("Beginning of SimanticsPlatform.startUp");
+
+ if (progressMonitor == null) progressMonitor = new NullProgressMonitor();
+
+ // For debugging on what kind of platform automatic tests are running in
+ // case there are problems.
+ if ("true".equals(System.getProperty("org.simantics.dumpBundleState")))
+ dumpPlatformBundleState();
+
+ // 0. Consult all startup extensions before doing anything with the workspace.
+ StartupExtensions.consultStartupExtensions();
+ TimeLogger.log("Consulted platform pre-startup extensions");
+
+ // 0.1. Clear all temporary files
+ Simantics.clearTemporaryDirectory();
+ TimeLogger.log("Cleared temporary directory");
+
+ // 0.2 Clear VariableRepository.repository static map which holds references to SessionImplDb
+ VariableRepository.clear();
+
+ // 1. Assert there is a database at <workspace>/db
+ session = setupDatabase(databaseDriverId, progressMonitor, workspacePolicy, userAgent);
+ TimeLogger.log("Database setup complete");
-
++
++ // 1.1
++ XSupport support = session.getService(XSupport.class);
++ if (support.rolledback()) {
++ try {
++ DatabaseIndexing.deleteAllIndexes();
++ } catch (IOException e) {
++ throw new PlatformException(e);
++ }
++ }
++
+ // 2. Assert all graphs, and correct versions, are installed to the database
+ synchronizeOntologies(progressMonitor, ontologyPolicy, requireSynchronize);
+ TimeLogger.log("Synchronized ontologies");
+
+ // 4. Assert simantics.cfg exists
+ boolean installProject = assertConfiguration(progressMonitor,workspacePolicy);
+
+ // 5. Assert Project Resource is installed in the database
+ installProject = assertProject(progressMonitor, workspacePolicy, installProject);
+
+ // 6. Install all features into project, if in debug mode
+ updateInstalledGroups(progressMonitor, installProject);
+ TimeLogger.log("Installed all features into project");
+
+ // 7. Assert L0.Session in database for this session
+ assertSessionModel(progressMonitor);
+
+ session.getService(XSupport.class).setServiceMode(false, false);
+
+ try {
+ session.sync(new WriteRequest() {
+
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ QueryControl qc = graph.getService(QueryControl.class);
+ qc.flush(graph);
+ }
+
+ });
+ TimeLogger.log("Flushed queries");
+ } catch (DatabaseException e) {
+ LOGGER.error("Flushing queries failed.", e);
+ }
+ boolean loadProject = true;
+ try {
+
+ sessionContext = SimanticsPlatform.INSTANCE.createSessionContext(true);
+ // This must be before setSessionContext since some listeners might query this
+ sessionContext.setHint(SimanticsKeys.KEY_PROJECT, SimanticsPlatform.INSTANCE.projectResource);
+
+ Simantics.setSessionContext(sessionContext);
+
+ // 1. Put ResourceBinding that throws an exception to General Bindings
+ simanticsBindings = new SimanticsBindings( null );
+ Bindings.classBindingFactory.addFactory( simanticsBindings );
+
+
+ // 2. Create session-specific second Binding context (Databoard) and
+ // put that to Session as a service
+ Session session = sessionContext.getSession();
+ Databoard sessionDataboard = new Databoard();
+ session.registerService(Databoard.class, sessionDataboard);
+ simanticsBindings2 = new SimanticsBindings( session );
+ sessionDataboard.classBindingFactory.addFactory( simanticsBindings2 );
+
+ // Register datatype bindings
+ Bindings.defaultBindingFactory.getRepository().put(RGB.Integer.BINDING.type(), RGB.Integer.BINDING);
+ Bindings.defaultBindingFactory.getRepository().put(Font.BINDING.type(), Font.BINDING);
+
+ if(loadProject) {
+
+ TimeLogger.log("Load projects");
+ project = Projects.loadProject(sessionContext.getSession(), SimanticsPlatform.INSTANCE.projectResource);
+
+ sessionContext.setHint(ProjectKeys.KEY_PROJECT, project);
+ TimeLogger.log("Loading projects complete");
+
+ project.activate();
+ TimeLogger.log("Project activated");
+ }
+
+ } catch (DatabaseException e) {
+ LOGGER.error("Platform startup failed.", e);
+ throw new PlatformException(e);
+ } catch (ProjectException e) {
+ boolean hasStackTrace = e.getStackTrace().length > 0;
+ if (!hasStackTrace)
+ throw new PlatformException(e.getMessage(), hasStackTrace);
+ throw new PlatformException(e, hasStackTrace);
+ }
+
+ running = true;
+
+ return sessionContext;
+
+ }
+
+ public SessionContext createSessionContext(boolean init) throws PlatformException {
+ try {
+ // Construct and initialize SessionContext from Session.
+ SessionContext sessionContext = SessionContext.create(session, init);
+ if (init)
+ sessionContext.registerServices();
+ return sessionContext;
+ } catch (DatabaseException e) {
+ throw new PlatformException(e);
+ }
+ }
+
+// private static File getIgnorePrerequisitesFile(URL workspaceUrl) {
+// if (workspaceUrl == null)
+// return null;
+// return new File(workspaceUrl.getPath(), ".ignorePrerequisites");
+// }
+//
+// private void ensurePrerequisites(IProgressMonitor progressMonitor, PlatformUserAgent userAgent) throws PlatformException {
+// Location loc = Platform.getInstanceLocation();
+// File ignorePrerequisites = getIgnorePrerequisitesFile(loc.getURL());
+// if (loc.isSet() && ignorePrerequisites != null) {
+// if (ignorePrerequisites.exists() || ignorePrerequisites.isFile())
+// return;
+// }
+//
+// try {
+// ServerEnvironment.ensureServerDependenciesMet();
+// } catch (ExecutionEnvironmentException e) {
+// // Not installed properly, ask user whether to try installation.
+// try {
+// StringBuilder msg = new StringBuilder();
+// msg.append("Your system seems to be missing the following prerequisites for running this application:\n\n");
+// for (Product product : e.requiredProducts)
+// msg.append("\t" + product.getDescription() + "\n");
+// msg.append("\nYou can either install the missing components now or ignore and attempt to start the application without them. Ignore Always will ignore this question for this workspace.");
+// msg.append("\n\nSelecting Cancel will close the application.");
+//
+// int selection = 0;
+// if (userAgent != null) {
+// selection = userAgent.showPrompt("Missing Prerequisites", msg.toString(), new String[] {
+// "Install Pre-requisites",
+// "Ignore Now",
+// "Ignore Always",
+// "Cancel"
+// }, selection);
+// }
+// boolean tryInstall = false;
+// switch (selection) {
+// case 0:
+// tryInstall = true;
+// break;
+// case 2:
+// ignorePrerequisites.createNewFile();
+// case 1:
+// break;
+// case 3:
+// case -1:
+// throw new CancelStartupException();
+// }
+//
+// if (tryInstall) {
+// // Try to install it and check for success afterwards.
+// ServerEnvironment.tryInstallDependencies(progressMonitor);
+// ServerEnvironment.ensureServerDependenciesMet();
+// }
+// } catch (InstallException ie) {
+// throw new PlatformException(ie);
+// } catch (ExecutionEnvironmentException eee) {
+// throw new PlatformException(eee);
+// } catch (IOException ie) {
+// throw new PlatformException(ie);
+// }
+// }
+// }
+
+ /**
+ * Shutdown Simantics Platform.
+ *
+ * In SWB this is handled in SimanticsWorkbenchAdvisor#disconnectFromWorkspace.
+ *
+ * @param progressMonitor optional progress monitor
+ * @throws PlatformException
+ */
+ public void shutdown(IProgressMonitor progressMonitor) throws PlatformException
+ {
+ SubMonitor progress = SubMonitor.convert(progressMonitor, 100);
+ PlatformException platformException = null;
+ try {
+ progress.subTask("Close Project");
+ if (project != null) {
+ project.safeDispose();
+ }
+ progress.worked(10);
+
+ running = false;
+ progress.subTask("Close Database Session");
+ Databoard databoard = null;
+ if (sessionContext != null) {
+ Session s = sessionContext.peekSession();
+ if (s != null) {
+ databoard = s.peekService(Databoard.class);
+
+ progress.subTask("Flushing Index Caches");
+ try {
+ Simantics.flushIndexCaches(progress.newChild(20), s);
+ } catch (Throwable t) {
+ LOGGER.error("Failed to flush index caches.", t);
+ }
+ }
+
+ progress.subTask("Close Database Session");
+ sessionContext.safeDispose();
+ sessionContext = null;
+ Simantics.setSessionContext(null);
+ }
+ if (simanticsBindings != null) {
+ Bindings.classBindingFactory.removeFactory( simanticsBindings );
+ simanticsBindings = null;
+ }
+ if (databoard != null) {
+ if (simanticsBindings2 != null) {
+ databoard.classBindingFactory.removeFactory( simanticsBindings2 );
+ simanticsBindings2 = null;
+ }
+ databoard.clear();
+ }
+
+ // Make sure Simantics clipboard doesn't store unwanted session data references.
+ Simantics.setClipboard(new SimanticsClipboardImpl());
+
+ progress.worked(30);
+
+ session = null;
+ projectResource = null;
+
+ DependenciesRelation.assertFinishedTracking();
+
+ } catch (Exception e) {
+ platformException = new PlatformException("Failed to shutdown Simantics Platform", e);
+ }
+
+ progress.worked(10);
+ progress.subTask("Shutting down database");
+ try {
+ if (null != databasebManagement)
+ databasebManagement.shutdown();
+ } catch (Throwable t) {
+ LOGGER.error("Database shutdown failed.", t);
+ }
+ progress.worked(10);
+
+ progress.subTask("Clearing Workspace Temporary Directory");
+ try {
+ Simantics.clearTemporaryDirectory();
+ } catch (Throwable t) {
+ LOGGER.error("Failed to clear the temporary directory.", t);
+ }
+ progress.worked(10);
+ if (null != platformException)
+ throw platformException;
+ }
+
+ // TODO: consider removing this in the future ??
+ @Override
+ public void stateChanged(LifecycleState newState) {
+ if(newState == LifecycleState.CLOSED) {
+ if(running) {
+ if(Platform.isRunning()) {
+ mainThread.interrupt();
+ }
+ }
+ }
+ }
+
+ /**
+ * @return <code>true</code> if discard was successful, <code>false</code>
+ * if there was no session, {@link UndoRedoSupport} or
+ * {@link UndoContext} to discard through
+ */
+ public boolean discardSessionUndoHistory() {
+ Session s = session;
+ if (s != null) {
+ UndoRedoSupport urs = s.peekService(UndoRedoSupport.class);
+ if (urs != null) {
+ UndoContext uc = urs.getUndoContext(s);
+ if (uc != null) {
+ uc.clear();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void reconnect(String databaseDriverId) throws Exception {
+ // Starts database server.
+ SimanticsPlatform.INSTANCE.startUp(databaseDriverId, null, RecoveryPolicy.ThrowError, OntologyRecoveryPolicy.ThrowError, true, null);
+ }
+
+ private void dumpPlatformBundleState() {
+ BundleDescription[] bs = Platform.getPlatformAdmin().getState().getBundles();
+ System.out.println("Total bundles: " + bs.length);
+ for (BundleDescription b : bs) {
+ System.out.format("%-80s @ %s\n", b.toString(), b.getLocation());
+ }
+ }
+
+}
+