OSDN Git Service

first commit
[japandigitalstudio/build-jds.git] / bundles.plugins.application.src.org.bonitasoft.studio.application.BonitaStudioWorkbenchAdvisor.java
1 /**
2  * Copyright (C) 2009-2011 BonitaSoft S.A.
3  * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2.0 of the License, or
7  * (at your option) any later version.
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  */
15 package org.bonitasoft.studio.application;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.lang.reflect.InvocationTargetException;
20 import java.net.URI;
21 import java.net.URL;
22 import java.util.Objects;
23 import java.util.stream.Stream;
24
25 import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor;
26 import org.bonitasoft.studio.application.contribution.IPreShutdownContribution;
27 import org.bonitasoft.studio.application.handler.OpenReleaseNoteHandler;
28 import org.bonitasoft.studio.application.i18n.Messages;
29 import org.bonitasoft.studio.common.DateUtil;
30 import org.bonitasoft.studio.common.FileUtil;
31 import org.bonitasoft.studio.common.ProjectUtil;
32 import org.bonitasoft.studio.common.RedirectURLBuilder;
33 import org.bonitasoft.studio.common.extension.BonitaStudioExtensionRegistryManager;
34 import org.bonitasoft.studio.common.extension.IPostStartupContribution;
35 import org.bonitasoft.studio.common.jface.MessageDialogWithLink;
36 import org.bonitasoft.studio.common.log.BonitaStudioLog;
37 import org.bonitasoft.studio.common.platform.tools.PlatformUtil;
38 import org.bonitasoft.studio.common.repository.AbstractRepository;
39 import org.bonitasoft.studio.common.repository.RepositoryManager;
40 import org.bonitasoft.studio.common.repository.core.ActiveOrganizationProvider;
41 import org.bonitasoft.studio.common.repository.core.maven.DependencyGetOperation;
42 import org.bonitasoft.studio.common.repository.core.maven.contribution.InstallBonitaMavenArtifactsOperation;
43 import org.bonitasoft.studio.common.repository.core.maven.migration.model.GAV;
44 import org.bonitasoft.studio.common.repository.core.maven.repository.MavenRepositories;
45 import org.bonitasoft.studio.designer.core.UIDesignerServerManager;
46 import org.bonitasoft.studio.engine.BOSEngineManager;
47 import org.bonitasoft.studio.engine.BOSWebServerManager;
48 import org.bonitasoft.studio.engine.server.StartEngineJob;
49 import org.bonitasoft.studio.model.process.diagram.part.ProcessDiagramEditorPlugin;
50 import org.bonitasoft.studio.model.process.impl.ContractInputImpl;
51 import org.bonitasoft.studio.preferences.BonitaStudioPreferencesPlugin;
52 import org.bonitasoft.studio.preferences.BonitaThemeConstants;
53 import org.bonitasoft.studio.preferences.dialog.BonitaPreferenceDialog;
54 import org.eclipse.core.internal.databinding.beans.BeanPropertyHelper;
55 import org.eclipse.core.internal.resources.Workspace;
56 import org.eclipse.core.resources.ResourcesPlugin;
57 import org.eclipse.core.runtime.CoreException;
58 import org.eclipse.core.runtime.FileLocator;
59 import org.eclipse.core.runtime.IConfigurationElement;
60 import org.eclipse.core.runtime.IProgressMonitor;
61 import org.eclipse.core.runtime.IStatus;
62 import org.eclipse.core.runtime.InvalidRegistryObjectException;
63 import org.eclipse.core.runtime.MultiStatus;
64 import org.eclipse.core.runtime.Path;
65 import org.eclipse.core.runtime.Platform;
66 import org.eclipse.core.runtime.Status;
67 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
68 import org.eclipse.core.runtime.jobs.Job;
69 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
70 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
71 import org.eclipse.e4.core.di.InjectionException;
72 import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
73 import org.eclipse.gmf.runtime.lite.svg.SVGFigure;
74 import org.eclipse.jface.dialogs.ErrorDialog;
75 import org.eclipse.jface.dialogs.IDialogConstants;
76 import org.eclipse.jface.dialogs.MessageDialog;
77 import org.eclipse.jface.operation.IRunnableWithProgress;
78 import org.eclipse.jface.resource.ImageDescriptor;
79 import org.eclipse.m2e.core.MavenPlugin;
80 import org.eclipse.m2e.core.embedder.IMavenConfiguration;
81 import org.eclipse.m2e.core.repository.IRepository;
82 import org.eclipse.m2e.core.repository.IRepositoryRegistry;
83 import org.eclipse.swt.widgets.Display;
84 import org.eclipse.swt.widgets.Shell;
85 import org.eclipse.ui.IStartup;
86 import org.eclipse.ui.IWorkbenchPage;
87 import org.eclipse.ui.PlatformUI;
88 import org.eclipse.ui.application.IWorkbenchConfigurer;
89 import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
90 import org.eclipse.ui.application.WorkbenchAdvisor;
91 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
92 import org.eclipse.ui.contexts.IContextService;
93 import org.eclipse.ui.ide.IDE;
94 import org.eclipse.ui.internal.Workbench;
95 import org.eclipse.ui.internal.browser.WebBrowserUtil;
96 import org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages;
97 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
98 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
99 import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
100 import org.osgi.framework.Bundle;
101
102 import com.google.common.base.Joiner;
103
104 public class BonitaStudioWorkbenchAdvisor extends WorkbenchAdvisor implements IStartup {
105
106     private static final String AWT_DRAW_STRING_AS_IMAGE = "drawStringAsImage";
107
108     private final class PreShutdownStudio implements IRunnableWithProgress {
109
110         @Override
111         public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
112             monitor.beginTask(Messages.shuttingDown, IProgressMonitor.UNKNOWN);
113             UIDesignerServerManager.getInstance().stop();
114             Job.getJobManager().cancel(StartEngineJob.FAMILY);
115             executePreShutdownContribution();
116             new ActiveOrganizationProvider().flush();
117             if (BOSWebServerManager.getInstance().serverIsStarted() && BOSEngineManager.getInstance().isRunning()) {
118                 BOSEngineManager.getInstance().stop();
119             }
120             FileUtil.deleteDir(ProjectUtil.getBonitaStudioWorkFolder());
121             deleteTomcatTempDir();
122             monitor.done();
123         }
124
125         private void deleteTomcatTempDir() {
126             File tempDir = new File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString() + File.separator
127                     + "tomcat" + File.separator + "server" + File.separator + "temp");
128             if (tempDir.exists()) {
129                 FileUtil.deleteDir(tempDir);
130             }
131         }
132
133         private void executePreShutdownContribution() {
134             final IConfigurationElement[] elements = BonitaStudioExtensionRegistryManager.getInstance()
135                     .getConfigurationElements(
136                             "org.bonitasoft.studio.application.preshutdown"); //$NON-NLS-1$
137             IPreShutdownContribution contrib = null;
138             for (final IConfigurationElement elem : elements) {
139                 try {
140                     contrib = (IPreShutdownContribution) elem.createExecutableExtension("class"); //$NON-NLS-1$
141                     contrib.execute();
142                 } catch (final CoreException e) {
143                     BonitaStudioLog.error(e);
144                 }
145             }
146         }
147     }
148
149     private static final String FIRST_STARTUP = "firstStartup";
150
151     @Override
152     public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(final IWorkbenchWindowConfigurer configurer) {
153         return new BonitaStudioWorkbenchWindowAdvisor(configurer);
154     }
155
156     @Override
157     public void initialize(final IWorkbenchConfigurer configurer) {
158         super.initialize(configurer);
159         configurer.setSaveAndRestore(true);
160         final IContextService contextService = PlatformUI.getWorkbench().getService(IContextService.class);
161         contextService.activateContext("org.bonitasoft.studio.context.id");
162         initializeIDEImages(configurer);
163     }
164
165     /**
166      * Workaround to load icons for Common Navigator component in a RCP
167      */
168     private void initializeIDEImages(final IWorkbenchConfigurer configurer) {
169         IDE.registerAdapters();
170         declareWorkbenchImages();
171     }
172
173     /********************************************************************
174      * /!\ Copy-pasted from IDEWorkbenchAvisor.declareWorkbenchImages() *
175      * ******************************************************************
176      * Declares all IDE-specific workbench images. This includes both "shared"
177      * images (named in {@link org.eclipse.ui.ide.IDE.SharedImages}) and internal images (named in
178      * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).
179      *
180      * @see IWorkbenchConfigurer#declareImage
181      */
182     private void declareWorkbenchImages() {
183
184         final String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$
185         final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; // Enabled //$NON-NLS-1$
186
187         // toolbar
188         // icons.
189         final String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; // Disabled //$NON-NLS-1$
190         // //$NON-NLS-1$
191         // toolbar
192         // icons.
193         final String PATH_ETOOL = ICONS_PATH + "etool16/"; // Enabled toolbar //$NON-NLS-1$
194         // //$NON-NLS-1$
195         // icons.
196         final String PATH_DTOOL = ICONS_PATH + "dtool16/"; // Disabled toolbar //$NON-NLS-1$
197         // //$NON-NLS-1$
198         // icons.
199         final String PATH_OBJECT = ICONS_PATH + "obj16/"; // Model object //$NON-NLS-1$
200         // //$NON-NLS-1$
201         // icons
202         final String PATH_WIZBAN = ICONS_PATH + "wizban/"; // Wizard //$NON-NLS-1$
203         // //$NON-NLS-1$
204         // icons
205
206         // View icons
207         final String PATH_EVIEW = ICONS_PATH + "eview16/"; //$NON-NLS-1$
208
209         final Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
210
211         declareWorkbenchImage(ideBundle,
212                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL
213                         + "build_exec.png", //$NON-NLS-1$
214                 false);
215         declareWorkbenchImage(ideBundle,
216                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,
217                 PATH_ETOOL + "build_exec.png", false); //$NON-NLS-1$
218         declareWorkbenchImage(ideBundle,
219                 IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,
220                 PATH_DTOOL + "build_exec.png", false); //$NON-NLS-1$
221
222         declareWorkbenchImage(ideBundle,
223                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL
224                         + "search_src.png", //$NON-NLS-1$
225                 false);
226         declareWorkbenchImage(ideBundle,
227                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,
228                 PATH_ETOOL + "search_src.png", false); //$NON-NLS-1$
229         declareWorkbenchImage(ideBundle,
230                 IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,
231                 PATH_DTOOL + "search_src.png", false); //$NON-NLS-1$
232
233         declareWorkbenchImage(ideBundle,
234                 IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL
235                         + "next_nav.png", //$NON-NLS-1$
236                 false);
237
238         declareWorkbenchImage(ideBundle,
239                 IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL
240                         + "prev_nav.png", //$NON-NLS-1$
241                 false);
242
243         declareWorkbenchImage(ideBundle,
244                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN
245                         + "newprj_wiz.png", //$NON-NLS-1$
246                 false);
247         declareWorkbenchImage(ideBundle,
248                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,
249                 PATH_WIZBAN + "newfolder_wiz.png", false); //$NON-NLS-1$
250         declareWorkbenchImage(ideBundle,
251                 IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN
252                         + "newfile_wiz.png", //$NON-NLS-1$
253                 false);
254
255         declareWorkbenchImage(ideBundle,
256                 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,
257                 PATH_WIZBAN + "importdir_wiz.png", false); //$NON-NLS-1$
258         declareWorkbenchImage(ideBundle,
259                 IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,
260                 PATH_WIZBAN + "importzip_wiz.png", false); //$NON-NLS-1$
261
262         declareWorkbenchImage(ideBundle,
263                 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,
264                 PATH_WIZBAN + "exportdir_wiz.png", false); //$NON-NLS-1$
265         declareWorkbenchImage(ideBundle,
266                 IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,
267                 PATH_WIZBAN + "exportzip_wiz.png", false); //$NON-NLS-1$
268
269         declareWorkbenchImage(ideBundle,
270                 IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,
271                 PATH_WIZBAN + "workset_wiz.png", false); //$NON-NLS-1$
272
273         declareWorkbenchImage(ideBundle,
274                 IDEInternalWorkbenchImages.IMG_DLGBAN_SAVEAS_DLG, PATH_WIZBAN
275                         + "saveas_wiz.png", //$NON-NLS-1$
276                 false);
277
278         declareWorkbenchImage(ideBundle,
279                 IDEInternalWorkbenchImages.IMG_DLGBAN_QUICKFIX_DLG, PATH_WIZBAN
280                         + "quick_fix.png", //$NON-NLS-1$
281                 false);
282
283         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,
284                 PATH_OBJECT + "prj_obj.png", true); //$NON-NLS-1$
285         declareWorkbenchImage(ideBundle,
286                 IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT
287                         + "cprj_obj.png", //$NON-NLS-1$
288                 true);
289         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,
290                 PATH_ELOCALTOOL + "gotoobj_tsk.png", true); //$NON-NLS-1$
291
292         // Quick fix icons
293         declareWorkbenchImage(ideBundle,
294                 IDEInternalWorkbenchImages.IMG_ELCL_QUICK_FIX_ENABLED,
295                 PATH_ELOCALTOOL + "smartmode_co.png", true); //$NON-NLS-1$
296
297         declareWorkbenchImage(ideBundle,
298                 IDEInternalWorkbenchImages.IMG_DLCL_QUICK_FIX_DISABLED,
299                 PATH_DLOCALTOOL + "smartmode_co.png", true); //$NON-NLS-1$
300
301         declareWorkbenchImage(ideBundle,
302                 IDEInternalWorkbenchImages.IMG_OBJS_FIXABLE_WARNING,
303                 PATH_OBJECT + "quickfix_warning_obj.png", true); //$NON-NLS-1$
304         declareWorkbenchImage(ideBundle,
305                 IDEInternalWorkbenchImages.IMG_OBJS_FIXABLE_ERROR,
306                 PATH_OBJECT + "quickfix_error_obj.png", true); //$NON-NLS-1$
307
308         // task objects
309         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK,
310         // PATH_OBJECT+"hprio_tsk.png");
311         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK,
312         // PATH_OBJECT+"mprio_tsk.png");
313         // declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK,
314         // PATH_OBJECT+"lprio_tsk.png");
315
316         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,
317                 PATH_OBJECT + "taskmrk_tsk.png", true); //$NON-NLS-1$
318         declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,
319                 PATH_OBJECT + "bkmrk_tsk.png", true); //$NON-NLS-1$
320
321         declareWorkbenchImage(ideBundle,
322                 IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT
323                         + "complete_tsk.png", //$NON-NLS-1$
324                 true);
325         declareWorkbenchImage(ideBundle,
326                 IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT
327                         + "incomplete_tsk.png", //$NON-NLS-1$
328                 true);
329         declareWorkbenchImage(ideBundle,
330                 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT
331                         + "welcome_item.png", //$NON-NLS-1$
332                 true);
333         declareWorkbenchImage(ideBundle,
334                 IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT
335                         + "welcome_banner.png", //$NON-NLS-1$
336                 true);
337         declareWorkbenchImage(ideBundle,
338                 IDEInternalWorkbenchImages.IMG_OBJS_ERROR_PATH, PATH_OBJECT
339                         + "error_tsk.png", //$NON-NLS-1$
340                 true);
341         declareWorkbenchImage(ideBundle,
342                 IDEInternalWorkbenchImages.IMG_OBJS_WARNING_PATH, PATH_OBJECT
343                         + "warn_tsk.png", //$NON-NLS-1$
344                 true);
345         declareWorkbenchImage(ideBundle,
346                 IDEInternalWorkbenchImages.IMG_OBJS_INFO_PATH, PATH_OBJECT
347                         + "info_tsk.png", //$NON-NLS-1$
348                 true);
349
350         declareWorkbenchImage(ideBundle,
351                 IDEInternalWorkbenchImages.IMG_LCL_FLAT_LAYOUT, PATH_ELOCALTOOL
352                         + "flatLayout.png", //$NON-NLS-1$
353                 true);
354         declareWorkbenchImage(ideBundle,
355                 IDEInternalWorkbenchImages.IMG_LCL_HIERARCHICAL_LAYOUT,
356                 PATH_ELOCALTOOL + "hierarchicalLayout.png", true); //$NON-NLS-1$
357         declareWorkbenchImage(ideBundle,
358                 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEM_CATEGORY,
359                 PATH_ETOOL + "problem_category.png", true); //$NON-NLS-1$
360
361         declareWorkbenchImage(ideBundle,
362                 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEMS_VIEW,
363                 PATH_EVIEW + "problems_view.png", true); //$NON-NLS-1$
364         declareWorkbenchImage(ideBundle,
365                 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEMS_VIEW_ERROR,
366                 PATH_EVIEW + "problems_view_error.png", true); //$NON-NLS-1$
367         declareWorkbenchImage(ideBundle,
368                 IDEInternalWorkbenchImages.IMG_ETOOL_PROBLEMS_VIEW_WARNING,
369                 PATH_EVIEW + "problems_view_warning.png", true); //$NON-NLS-1$
370     }
371
372     /**
373      * Declares an IDE-specific workbench image.
374      *
375      * @param symbolicName
376      *        the symbolic name of the image
377      * @param path
378      *        the path of the image file; this path is relative to the base
379      *        of the IDE plug-in
380      * @param shared
381      *        <code>true</code> if this is a shared image, and
382      *        <code>false</code> if this is not a shared image
383      * @see IWorkbenchConfigurer#declareImage
384      */
385     private void declareWorkbenchImage(final Bundle ideBundle, final String symbolicName,
386             final String path, final boolean shared) {
387         final URL url = FileLocator.find(ideBundle, new Path(path), null);
388         final ImageDescriptor desc = ImageDescriptor.createFromURL(url);
389         getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);
390     }
391
392     @Override
393     public String getInitialWindowPerspectiveId() {
394         return null;
395     }
396
397     @Override
398     public String getMainPreferencePageId() {
399         return "org.bonitasoft.studio.preferences.preferences.UIPreferencePage";
400     }
401
402     @Override
403     public void preStartup() {
404         // Initialize adapter factories and avoid deadlock at startup
405         ProcessDiagramEditorPlugin.getInstance().getItemProvidersAdapterFactory();
406         try {
407             new InstallBonitaMavenArtifactsOperation(MavenPlugin.getMaven().getLocalRepository()).execute();
408         } catch (CoreException e) {
409            BonitaStudioLog.error(e);
410         }
411         disableInternalWebBrowser();
412         setSystemProperties();
413     }
414
415     protected void setSystemProperties() {
416         var instanceLocation = Platform.getInstanceLocation();
417         if (instanceLocation != null) {
418             String workspaceLocation = new File(instanceLocation.getURL().getFile()).getPath();
419             System.setProperty("bonita.tomcat.lib.dir", String.format("%s%stomcat%sserver%slib", workspaceLocation,
420                     File.separator, File.separator, File.separator));
421             BonitaStudioLog.info("bonita.tomcat.lib.dir=" + System.getProperty("bonita.tomcat.lib.dir"),
422                     ApplicationPlugin.PLUGIN_ID);
423         } else {
424             BonitaStudioLog.warning("Property 'bonita.tomcat.lib.dir' has not been set.", ApplicationPlugin.PLUGIN_ID);
425         }
426         // Workaround for STUDIO-3651
427         System.setProperty(AWT_DRAW_STRING_AS_IMAGE, System.getProperty(AWT_DRAW_STRING_AS_IMAGE, "true"));
428     }
429
430     @Override
431     public void postStartup() {
432         var initializeProjectJob = new Job("Initialize project") {
433
434             @Override
435             protected IStatus run(IProgressMonitor monitor) {
436                 RepositoryManager.getInstance().getAccessor().start(monitor);
437                 return Status.OK_STATUS;
438             }
439         };
440         initializeProjectJob.addJobChangeListener(new JobChangeAdapter() {
441
442             @Override
443             public void done(IJobChangeEvent event) {
444                 if (initializeProjectJob.equals(event.getJob())) {
445                     executePostStartupContributions();
446                 }
447                 super.done(event);
448             }
449         });
450         initializeProjectJob.setPriority(Job.INTERACTIVE);
451         initializeProjectJob.schedule();
452
453         super.postStartup();
454         IThemeEngine engine = PlatformUI.getWorkbench().getService(IThemeEngine.class);
455         synchroniseTheme(engine);
456         applyTheme(engine);
457     }
458
459     /**
460      * Synchronise active eclipse theme with the Bonita preference,
461      * to ensure that specifics adjustments for Dark theme are applied.
462      * The preference value can be outdated if the user update the theme from the eclipse preference panel.
463      */
464     private void synchroniseTheme(IThemeEngine engine) {
465         String currentValue = BonitaStudioPreferencesPlugin.getDefault().getPreferenceStore()
466                 .getString(BonitaThemeConstants.STUDIO_THEME_PREFERENCE);
467         String activeTheme = engine.getActiveTheme() == null
468                 ? null
469                 : engine.getActiveTheme().getId();
470         if (!themeIsValid(activeTheme)) {
471             BonitaStudioPreferencesPlugin.getDefault().getPreferenceStore()
472                     .setValue(BonitaThemeConstants.STUDIO_THEME_PREFERENCE, BonitaThemeConstants.LIGHT_THEME);
473         } else if (!Objects.equals(currentValue, engine.getActiveTheme().getId())) {
474             BonitaStudioPreferencesPlugin.getDefault().getPreferenceStore()
475                     .setValue(BonitaThemeConstants.STUDIO_THEME_PREFERENCE, engine.getActiveTheme().getId());
476         }
477     }
478
479     private boolean themeIsValid(String themeId) {
480         if (themeId != null && !themeId.isBlank()) {
481             return Objects.equals(themeId, BonitaThemeConstants.LIGHT_THEME)
482                     || Objects.equals(themeId, BonitaThemeConstants.DARK_THEME);
483         }
484         return false;
485     }
486
487     /**
488      * Apply the theme if required (usually on first start).
489      */
490     private void applyTheme(IThemeEngine engine) {
491         String expectedTheme = BonitaStudioPreferencesPlugin.getDefault().getPreferenceStore()
492                 .getString(BonitaThemeConstants.STUDIO_THEME_PREFERENCE);
493         if (engine.getActiveTheme() == null
494                 || !Objects.equals(expectedTheme, engine.getActiveTheme().getId())) {
495             BonitaStudioLog.info(String.format("Applying theme %s", expectedTheme), ApplicationPlugin.PLUGIN_ID);
496             engine.setTheme(expectedTheme, true);
497         }
498     }
499
500     /**
501      * Disconnect from the core workspace.
502      */
503     private void disconnectFromWorkspace(final IProgressMonitor monitor) {
504         // save the workspace
505         final MultiStatus status = new MultiStatus(
506                 IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
507                 IDEWorkbenchMessages.ProblemSavingWorkbench, null);
508         try {
509             final ProgressMonitorJobsDialog p = new ProgressMonitorJobsDialog(
510                     null);
511
512             final boolean applyPolicy = ResourcesPlugin.getWorkspace()
513                     .getDescription().isApplyFileStatePolicy();
514
515             final IRunnableWithProgress runnable = new IRunnableWithProgress() {
516
517                 @Override
518                 public void run(final IProgressMonitor monitor) {
519                     try {
520                         if (applyPolicy) {
521                             status.merge(((Workspace) ResourcesPlugin
522                                     .getWorkspace()).save(true, true, monitor));
523                         }
524                     } catch (final CoreException e) {
525                         status.merge(e.getStatus());
526                     }
527                 }
528             };
529             p.run(true, false, runnable);
530         } catch (final InvocationTargetException e) {
531             status
532                     .merge(new Status(IStatus.ERROR,
533                             IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
534                             IDEWorkbenchMessages.InternalError, e
535                                     .getTargetException()));
536         } catch (final InterruptedException e) {
537             status.merge(new Status(IStatus.ERROR,
538                     IDEWorkbenchPlugin.IDE_WORKBENCH, 1,
539                     IDEWorkbenchMessages.InternalError, e));
540         }
541         ErrorDialog.openError(null,
542                 IDEWorkbenchMessages.ProblemsSavingWorkspace, null, status,
543                 IStatus.ERROR | IStatus.WARNING);
544         if (!status.isOK()) {
545             IDEWorkbenchPlugin.log(
546                     IDEWorkbenchMessages.ProblemsSavingWorkspace, status);
547         }
548     }
549
550     protected void disableInternalWebBrowser() {
551         final String noRegister = System.getProperty("bonita.noregister"); //$NON-NLS-1$
552         if (noRegister == null || !noRegister.equals("1")) {
553             WebBrowserUtil.isInternalBrowserOperational = false;
554         }
555     }
556
557     @Override
558     public void postShutdown() {
559         super.postShutdown();
560         disconnectFromWorkspace(AbstractRepository.NULL_PROGRESS_MONITOR);
561     }
562
563     @Override
564     public boolean preShutdown() {
565         IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
566                 .getActivePage();
567         Stream.of(activePage.getViewReferences())
568                 .filter(vr -> Objects.equals("org.eclipse.ui.browser.view", vr.getId()))
569                 .forEach(activePage::hideView);
570         Job.getJobManager().cancel(StartEngineJob.FAMILY);
571         final boolean returnValue = super.preShutdown();
572         if (returnValue) {
573             try {
574                 if (PlatformUI.isWorkbenchRunning() && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null
575                         && PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() != null) {
576                     PlatformUI.getWorkbench().getProgressService().run(true, false, new PreShutdownStudio());
577                     return true;
578                 }
579             } catch (final Exception e) {
580                 BonitaStudioLog.error(e);
581             }
582         }
583         return returnValue;
584     }
585
586     @Override
587     public void earlyStartup() {
588         if (PlatformUtil.isHeadless()) {
589             return;//Do not execute earlyStartup in headless mode
590         }
591
592         new Job("Setup internal maven repository") {
593
594             @Override
595             protected IStatus run(IProgressMonitor monitor) {
596                 new InstallBonitaMavenArtifactsOperation(MavenRepositories.internalRepository()).execute();
597                 try {
598                     testMavenCentralAccess(monitor);
599                 } catch (InvocationTargetException | InterruptedException e) {
600                     return new Status(IStatus.ERROR, getClass(), e.getMessage());
601                 }
602                 return Status.OK_STATUS;
603             }
604
605             private void testMavenCentralAccess(IProgressMonitor monitor)
606                     throws InvocationTargetException, InterruptedException {
607                 // Use an arbitrary artifact (small) to test maven central access
608                 var operation = new DependencyGetOperation(
609                         new GAV("org.bonitasoft.engine", "bonita-engine", "7.13.0", null, "pom", null));
610                 MavenPlugin.getRepositoryRegistry().getRepositories(IRepositoryRegistry.SCOPE_SETTINGS).stream()
611                         .map(IRepository::getUrl)
612                         .forEach(operation::addRemoteRespository);
613                 operation.run(monitor);
614                 var result = operation.getResult();
615                 if (result == null) {
616                     IMavenConfiguration mavenConfiguration = MavenPlugin.getMavenConfiguration();
617                     var userSettingsFile = mavenConfiguration.getUserSettingsFile() != null
618                             ? new File(mavenConfiguration.getUserSettingsFile())
619                             : SettingsXmlConfigurationProcessor.DEFAULT_USER_SETTINGS_FILE;
620                     Display.getDefault().syncExec(() -> {
621                         var message = Messages.cannotReachMavenCentralRepositoryMessage;
622                         if (userSettingsFile.exists()) {
623                             message = message + System.lineSeparator()
624                                     + String.format(Messages.validateExistingMavenConfigurationMessage,
625                                             userSettingsFile.getAbsolutePath());
626                         }
627                         int buttonId = new MessageDialogWithLink(Display.getDefault().getActiveShell(),
628                                 Messages.cannotReachMavenCentralRepositoryTitle,
629                                 null,
630                                 message,
631                                 MessageDialog.WARNING,
632                                 new String[] { IDialogConstants.IGNORE_LABEL,
633                                         Messages.retry,
634                                         Messages.configure },
635                                 0,
636                                 URI.create(RedirectURLBuilder.create("728"))).open();
637                         if (buttonId == 2) {
638                             BonitaPreferenceDialog dialog = new BonitaPreferenceDialog(
639                                     new Shell(Display.getDefault()));
640                             dialog.create();
641                             dialog.setSelectedPreferencePage(BonitaPreferenceDialog.MAVEN_PAGE_ID);
642                             dialog.open();
643                             try {
644                                 testMavenCentralAccess(monitor);
645                             } catch (InvocationTargetException | InterruptedException e) {
646                                 BonitaStudioLog.error(e);
647                             }
648                         } else if (buttonId == 1) {
649                             try {
650                                 testMavenCentralAccess(monitor);
651                             } catch (InvocationTargetException | InterruptedException e) {
652                                 BonitaStudioLog.error(e);
653                             }
654                         }
655                     });
656                 }
657             }
658         }.schedule();
659
660         preLoad();
661
662         final long startupDuration = System.currentTimeMillis() - BonitaStudioApplication.START_TIME;
663         BonitaStudioLog.info("Startup duration : " + DateUtil.getDisplayDuration(startupDuration),
664                 ApplicationPlugin.PLUGIN_ID);
665         ApplicationPlugin.getDefault().getPreferenceStore().setDefault(FIRST_STARTUP, true);
666         if (isFirstStartup()) {
667 //            new OpenReleaseNoteHandler().openBrowser();
668 //            PlatformUtil.openIntroIfNoOtherEditorOpen();
669 //        }else {
670             PlatformUtil.openDashboardIfNoOtherEditorOpen();
671         }
672         ApplicationPlugin.getDefault().getPreferenceStore().setValue(FIRST_STARTUP, false);
673     }
674
675     private void executePostStartupContributions() {
676         final IConfigurationElement[] elements = BonitaStudioExtensionRegistryManager.getInstance()
677                 .getConfigurationElements(
678                         "org.bonitasoft.studio.common.poststartup"); //$NON-NLS-1$
679         for (final IConfigurationElement elem : elements) {
680             final Workbench workbench = (Workbench) PlatformUI.getWorkbench();
681             try {
682                 IPostStartupContribution contrib = (IPostStartupContribution) ContextInjectionFactory
683                         .make(Platform.getBundle(elem.getDeclaringExtension().getNamespaceIdentifier())
684                                 .loadClass(elem.getAttribute("class")), workbench.getContext());
685                 Display.getDefault().asyncExec(contrib::execute);
686             } catch (InjectionException | ClassNotFoundException | InvalidRegistryObjectException e) {
687                 BonitaStudioLog.error(e);
688             }
689         }
690     }
691
692     private boolean isFirstStartup() {
693         return ApplicationPlugin.getDefault().getPreferenceStore().getBoolean(FIRST_STARTUP);
694     }
695
696     private void preLoad() {
697         //Fix performance issue
698         BeanPropertyHelper.getPropertyDescriptor(ContractInputImpl.class, "name");
699         preLoadSVG();
700     }
701
702     private void preLoadSVG() {
703         final SVGFigure svgFigure = new SVGFigure();
704         try {
705             final File iconsFolder = new File(
706                     FileLocator.toFileURL(Platform.getBundle("org.bonitasoft.studio.pics").getResource("icons"))
707                             .getFile());
708             initSVGFigure(svgFigure, iconsFolder, "figures");
709             initSVGFigure(svgFigure, iconsFolder, "decoration", "svg");
710         } catch (final IOException e) {
711             BonitaStudioLog.error(e);
712         }
713     }
714
715     private void initSVGFigure(final SVGFigure svgFigure, final File iconsFolder, final String... pathToFolder) {
716         for (final String filename : new File(iconsFolder, Joiner.on(File.separatorChar).join(pathToFolder)).list()) {
717             if (filename.endsWith(".svgz")) {
718                 svgFigure
719                         .setURI("platform:/plugin/org.bonitasoft.studio.pics/icons/" + Joiner.on("/").join(pathToFolder)
720                                 + "/" + filename);
721             }
722         }
723     }
724
725 }