null
if uninitialized. Key type:
* String
, Value type: AboutInfo
.
*/
private MapAboutInfo
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 Keys
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 BindingToModelProcessor
.
*
*
* 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();
// #6353: Workaround for
fixBindings();
return true;
}
}
// Make sure platform shutdown is ran if window opening fails.
try {
platformShutdownRunnable.run(null);
} catch (InvocationTargetException e) {
Activator.logError(getClass().getSimpleName() + ".openWindows failed", e.getCause());
} catch (InterruptedException e) {
Activator.logError(getClass().getSimpleName() + ".openWindows failed", e);
}
return false;
}
protected boolean startPlatform() {
// Verify selected perspective
if (args.contains(SimanticsArguments.PERSPECTIVE)) {
String perspectiveId = args.get(SimanticsArguments.PERSPECTIVE);
IPerspectiveDescriptor perspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
if (perspective == null) {
StringBuilder msg = new StringBuilder();
msg.append("Requested perspective not found: '" + perspectiveId + "'\n");
msg.append("Valid alternatives are:\n");
for (IPerspectiveDescriptor pd : PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives()) {
msg.append(" " + pd.getId() + "\n");
}
ShowMessage.syncShowError("Invalid Perspective", msg.toString());
return false;
}
}
ILog log = Platform.getLog(Activator.getDefault().getBundle());
try {
//
//
// Create Simantics Platform Helper.
//
// If Simantics is started from Eclipse IDE or with -fixerrors option,
// there is an attempt to fix errors.
//
// On ontology mismatch, there is an attempt to merge new ontology to the
// existing database. With -reinstall, the database is cleaned and
// reinstalled.
//
//
RecoveryPolicy workspacePolicy = Platform.inDevelopmentMode() ? RecoveryPolicy.FixError : RecoveryPolicy.ThrowError;
OntologyRecoveryPolicy ontologyPolicy = Platform.inDevelopmentMode() ? OntologyRecoveryPolicy.Merge : OntologyRecoveryPolicy.ThrowError;
if (args.contains(SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS)) {
workspacePolicy = RecoveryPolicy.FixError;
ontologyPolicy = OntologyRecoveryPolicy.Merge;
}
boolean requireSynchronize = true;
if (args.contains(SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL)) {
ontologyPolicy = OntologyRecoveryPolicy.ReinstallDatabase;
}
if (args.contains(SimanticsArguments.DO_NOT_SYNCHRONIZE_ONTOLOGIES)) {
requireSynchronize = false;
}
if (args.contains(SimanticsArguments.DISABLE_INDEX)) {
Indexing.setDefaultDependenciesIndexingEnabled(false);
}
if (args.contains(SimanticsArguments.SERVER)) {
String serverAddress = args.get(SimanticsArguments.SERVER);
throw new PlatformException("Argument not supported: " + SimanticsArguments.SERVER + " " + serverAddress);
}
String databaseDriverId = Simantics.getDefaultDatabaseDriver();
if (args.contains(SimanticsArguments.DATABASE_ID)) {
databaseDriverId = args.get(SimanticsArguments.DATABASE_ID);
Simantics.setDefaultDatabaseDriver(databaseDriverId);
}
IProgressMonitor mon = null;
if (PROFILE_PLATFORM_STARTUP)
mon = new TimingProgressMonitor();
SimanticsPlatform.INSTANCE.startUp(databaseDriverId, mon, workspacePolicy, ontologyPolicy, requireSynchronize, new JFaceUserAgent());
// Make sure that the default perspective comes from the project if
// the project has set ProjectKeys#DEFAULT_PERSPECTIVE.
// This might go wrong if project features interact with
// PerspectiveRegistry while configuring themselves, since that will
// cause an invocation to #getInitialWindowPerspectiveId() while
// the project has not yet been properly initialized.
getWorkbenchConfigurer().getWorkbench().getPerspectiveRegistry().setDefaultPerspective(getInitialWindowPerspectiveId());
TimeLogger.log("Completed setting default perspective");
return true;
} catch (CancelStartupException e) {
return false;
} catch (PlatformException e) {
boolean hasStackTrace = e.getStackTrace().length > 0;
Throwable ee = e;
while (ee.getCause() != null) {
ee = ee.getCause();
hasStackTrace = ee.getStackTrace().length > 0;
}
log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), hasStackTrace ? e : null));
if (hasStackTrace) {
new ShowError("Platform Initialization Failed", "Simantics Platform initialization failed:\n\n" + e.getMessage(), e, true);
} else {
StringBuilder sb = new StringBuilder(256);
sb.append(e.getMessage());
for (Throwable c=e.getCause(); null != c && null != c.getMessage(); c=c.getCause())
sb.append("\ncause: ").append(c.getMessage());
new ShowError("Startup Failed", sb.toString(), (Exception) null, true);
}
return false;
} catch (Exception e) {
log.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
Throwable cause = e.getCause();
if (cause instanceof RebootRequiredException) {
RebootRequiredException rre = (RebootRequiredException) cause;
StringBuilder msg = new StringBuilder();
msg.append("The application must be restarted after installing the following products:\n");
for (Product product : rre.products)
msg.append("\t" + product + "\n");
msg.append("\nThe application will now close.");
MessageDialog.openInformation(null, "Restart Required", msg.toString());
} else {
new ShowError("Platform Startup Failed", "Simantics Platform startup failed:\n\n" + e.getMessage(), e, true);
}
return false;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()
*/
@Override
public void preStartup() {
// Suspend background jobs while we startup
Job.getJobManager().suspend();
// Register the build actions
IProgressService service = PlatformUI.getWorkbench()
.getProgressService();
ImageDescriptor newImage = IDEInternalWorkbenchImages
.getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
service.registerIconForFamily(newImage,
ResourcesPlugin.FAMILY_MANUAL_BUILD);
service.registerIconForFamily(newImage,
ResourcesPlugin.FAMILY_AUTO_BUILD);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
*/
@Override
public void postStartup() {
try {
refreshFromLocal();
activateProxyService();
((Workbench) PlatformUI.getWorkbench()).registerService(
ISelectionConversionService.class,
new IDESelectionConversionService());
initializeSettingsChangeListener();
Display.getCurrent().addListener(SWT.Settings,
settingsChangeListener);
} finally {// Resume background jobs after we startup
Job.getJobManager().resume();
}
}
/**
* Activate the proxy service by obtaining it.
*/
private void activateProxyService() {
Bundle bundle = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$
Object proxyService = null;
if (bundle != null) {
ServiceReference> ref = bundle.getBundleContext().getServiceReference(IProxyService.class.getName());
if (ref != null)
proxyService = bundle.getBundleContext().getService(ref);
}
if (proxyService == null) {
IDEWorkbenchPlugin.log("Proxy service could not be found."); //$NON-NLS-1$
}
}
/**
* Initialize the listener for settings changes.
*/
private void initializeSettingsChangeListener() {
settingsChangeListener = new Listener() {
boolean currentHighContrast = Display.getCurrent()
.getHighContrast();
@Override
public void handleEvent(org.eclipse.swt.widgets.Event event) {
if (Display.getCurrent().getHighContrast() == currentHighContrast)
return;
currentHighContrast = !currentHighContrast;
// make sure they really want to do this
if (new MessageDialog(null,
IDEWorkbenchMessages.SystemSettingsChange_title, null,
IDEWorkbenchMessages.SystemSettingsChange_message,
MessageDialog.QUESTION, new String[] {
IDEWorkbenchMessages.SystemSettingsChange_yes,
IDEWorkbenchMessages.SystemSettingsChange_no },
1).open() == Window.OK) {
PlatformUI.getWorkbench().restart();
}
}
};
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown
*/
@Override
public void postShutdown() {
if (activityHelper != null) {
activityHelper.shutdown();
activityHelper = null;
}
if (idleHelper != null) {
idleHelper.shutdown();
idleHelper = null;
}
if (workspaceUndoMonitor != null) {
workspaceUndoMonitor.shutdown();
workspaceUndoMonitor = null;
}
if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {
disconnectFromWorkspace();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()
*/
@Override
public boolean preShutdown() {
Display.getCurrent().removeListener(SWT.Settings,
settingsChangeListener);
return super.preShutdown();
}
/**
* Return true if the intro plugin is present and false otherwise.
*
* @return boolean
*/
public boolean hasIntro() {
return getWorkbenchConfigurer().getWorkbench().getIntroManager()
.hasIntro();
}
private void refreshFromLocal() {
String[] commandLineArgs = Platform.getCommandLineArgs();
IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
.getPreferenceStore();
boolean refresh = store
.getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);
if (!refresh) {
return;
}
// Do not refresh if it was already done by core on startup.
for (int i = 0; i < commandLineArgs.length; i++) {
if (commandLineArgs[i].equalsIgnoreCase("-refresh")) { //$NON-NLS-1$
return;
}
}
final IContainer root = ResourcesPlugin.getWorkspace().getRoot();
Job job = new WorkspaceJob(IDEWorkbenchMessages.Workspace_refreshing) {
@Override
public IStatus runInWorkspace(IProgressMonitor monitor)
throws CoreException {
root.refreshLocal(IResource.DEPTH_INFINITE, monitor);
return Status.OK_STATUS;
}
};
job.setRule(root);
job.schedule();
}
private static class CancelableProgressMonitorWrapper extends ProgressMonitorWrapper {
private double total = 0;
private ProgressMonitorJobsDialog dialog;
CancelableProgressMonitorWrapper(IProgressMonitor monitor,
ProgressMonitorJobsDialog dialog) {
super(monitor);
this.dialog = dialog;
}
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.ProgressMonitorWrapper#internalWorked(double)
*/
public void internalWorked(double work) {
super.internalWorked(work);
total += work;
updateProgressDetails();
}
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.ProgressMonitorWrapper#worked(int)
*/
public void worked(int work) {
super.worked(work);
total += work;
updateProgressDetails();
}
public void beginTask(String name, int totalWork) {
super.beginTask(name, totalWork);
subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_preHistoryCompaction);
}
private void updateProgressDetails() {
if (!isCanceled() && Math.abs(total - 4.0) < 0.0001 /* right before history compacting */) {
subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_cancelHistoryPruning);
dialog.setCancelable(true);
}
if (Math.abs(total - 5.0) < 0.0001 /* history compacting finished */) {
subTask(IDEWorkbenchMessages.IDEWorkbenchAdvisor_postHistoryCompaction);
dialog.setCancelable(false);
}
}
}
private static class CancelableProgressMonitorJobsDialog extends ProgressMonitorJobsDialog {
public CancelableProgressMonitorJobsDialog(Shell parent) {
super(parent);
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog#createDetailsButton(org.eclipse.swt.widgets.Composite)
*/
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
registerCancelButtonListener();
}
public void registerCancelButtonListener() {
cancel.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
subTaskLabel.setText(""); //$NON-NLS-1$
}
});
}
}
final IRunnableWithProgress platformShutdownRunnable = new IRunnableWithProgress() {
/**
* @param monitor
* the progress monitor to use for reporting progress to the
* user, or null
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();
ExecutorWorker.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 = Simantics.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:
* String
, value type: AboutInfo
)
* @since 3.0
*/
private MapString
) -> infos (value type:
* AboutInfo
).
*/
public Maptrue
if this is a shared image, and
* false
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 null
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 null
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