diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TracingOptionsManager.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TracingOptionsManager.java index 5d53461899e..8db8215cc73 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TracingOptionsManager.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TracingOptionsManager.java @@ -24,16 +24,16 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.pde.core.plugin.IPluginModelBase; import org.eclipse.pde.core.plugin.PluginRegistry; @@ -44,8 +44,8 @@ public TracingOptionsManager() { super(); } - public Map getTemplateTable(String pluginId) { - Map tracingTemplate = getTracingTemplate(); + public Map getTemplateTable(String pluginId, IProgressMonitor monitor) { + Map tracingTemplate = getTracingTemplate(monitor); Map defaults = new HashMap<>(); tracingTemplate.forEach((key, value) -> { if (belongsTo(key, pluginId)) { @@ -60,9 +60,9 @@ private boolean belongsTo(String option, String pluginId) { return pluginId.equalsIgnoreCase(firstSegment); } - public Map getTracingOptions(Map storedOptions) { + public Map getTracingOptions(Map storedOptions, IProgressMonitor monitor) { // Start with the fresh template from plugins - Map defaults = getTracingTemplateCopy(); + Map defaults = getTracingTemplateCopy(monitor); if (storedOptions != null) { // Load stored values, but only for existing keys storedOptions.forEach((key, value) -> { @@ -74,21 +74,29 @@ public Map getTracingOptions(Map storedOptions) return defaults; } - public Map getTracingTemplateCopy() { - return new HashMap<>(getTracingTemplate()); + public Map getTracingTemplateCopy(IProgressMonitor monitor) { + return new HashMap<>(getTracingTemplate(monitor)); } - private synchronized Map getTracingTemplate() { - if (template == null) { - Map temp = new HashMap<>(); - IPluginModelBase[] models = PluginRegistry.getAllModels(); - Arrays.stream(models).map(TracingOptionsManager::getOptions).filter(Objects::nonNull).forEach(p -> { + private synchronized Map getTracingTemplate(IProgressMonitor monitor) { + if (template != null) { + return template; + } + + Map temp = new HashMap<>(); + IPluginModelBase[] models = PluginRegistry.getAllModels(); + SubMonitor subMonitor = SubMonitor.convert(monitor, models.length); + + for (IPluginModelBase model : models) { + subMonitor.split(1); + Properties options = TracingOptionsManager.getOptions(model); + if (options != null) { @SuppressWarnings({ "rawtypes", "unchecked" }) - Map entries = (Map) p; + Map entries = (Map) options; temp.putAll(entries); // All entries are of String/String - }); - template = temp; + } } + template = temp; return template; } @@ -129,7 +137,7 @@ private void saveOptions(Path file, Map entries) { } public void save(Path file, Map map, Set selected) { - Map properties = getTracingOptions(map); + Map properties = getTracingOptions(map, null); properties.keySet().removeIf(key -> { IPath path = IPath.fromOSString(key); return path.segmentCount() < 1 || !selected.contains(path.segment(0)); @@ -138,7 +146,7 @@ public void save(Path file, Map map, Set selected) { } public void save(Path file, Map map) { - saveOptions(file, getTracingOptions(map)); + saveOptions(file, getTracingOptions(map, null)); } private static Properties getOptions(IPluginModelBase model) { diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java index 04299c53830..71edc2cba67 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java @@ -1093,6 +1093,7 @@ public class PDEUIMessages extends NLS { public static String TracingTab_AttributeLabel_TracingChecked; public static String TracingTab_AttributeLabel_TracingNone; + public static String TracingBlock_initializing_tracing_options; public static String TracingBlock_restore_default; public static String TracingBlock_restore_default_selected; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/TracingBlock.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/TracingBlock.java index 759c45bccc9..16302555983 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/TracingBlock.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/TracingBlock.java @@ -18,16 +18,21 @@ import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.BiFunction; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.IStructuredSelection; @@ -58,6 +63,61 @@ public class TracingBlock { + /** + * This class encapsulates all calls to the tracing options manager and runs them using a + */ + private static final class TracingOptionsManagerDelegate { + + private IRunnableContext fRunnableContext; + + public void setRunnableContext(IRunnableContext runnableContext) { + fRunnableContext = runnableContext; + } + + Map getTracingTemplateCopy() { + return runShowingProgress( + (tracingOptionsManager, monitor) -> tracingOptionsManager.getTracingTemplateCopy(monitor)); + } + + public Map getTracingOptions(Map options) { + return runShowingProgress( + (tracingOptionsManager, monitor) -> tracingOptionsManager.getTracingOptions(options, monitor)); + } + + public Map getTemplateTable(String pluginId) { + return runShowingProgress( + (tracingOptionsManager, monitor) -> tracingOptionsManager.getTemplateTable(pluginId, monitor)); + } + + private Map runShowingProgress( + BiFunction> task) { + try { + String taskName = PDEUIMessages.TracingBlock_initializing_tracing_options; + final Map result = new HashMap<>(); + + // due to a bug + // (https://github.com/eclipse-platform/eclipse.platform/issues/769), + // the task needs to be forked otherwise the UI + // does not show the progress indicator + fRunnableContext.run(true, false, monitor -> { + SubMonitor subMonitor = SubMonitor.convert(monitor, taskName, 1); + result.putAll(task.apply(PDECore.getDefault().getTracingOptionsManager(), subMonitor.split(1))); + }); + + return result; + } catch (InvocationTargetException | InterruptedException e) { + PDEPlugin.logException(e); + } + + // This should never happen since the task can not be canceled + // (yet). If it does happen then some exception occurred while + // calling the TracingOptionsManager and all bets are off (i.e. NPEs + // will follow) + return null; + } + } + + private final TracingOptionsManagerDelegate fTracingOptionsManagerDelegate = new TracingOptionsManagerDelegate(); private final TracingTab fTab; private Button fTracingCheck; private CheckboxTableViewer fPluginViewer; @@ -201,8 +261,7 @@ private void createRestoreButtonSection(Composite parent) { if (selec.getFirstElement() instanceof IPluginModelBase model) { String modelName = model.getBundleDescription().getSymbolicName(); if (modelName != null) { - Map properties = PDECore.getDefault().getTracingOptionsManager() - .getTracingTemplateCopy(); + Map properties = fTracingOptionsManagerDelegate.getTracingTemplateCopy(); properties.forEach((key, value) -> { if (key.startsWith(modelName + '/')) { fMasterOptions.put(key, value); @@ -222,7 +281,7 @@ private void createRestoreButtonSection(Composite parent) { fRestoreDefaultButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { disposePropertySources(); fMasterOptions.clear(); - fMasterOptions.putAll(PDECore.getDefault().getTracingOptionsManager().getTracingTemplateCopy()); + fMasterOptions.putAll(fTracingOptionsManagerDelegate.getTracingTemplateCopy()); Object[] elements = fPluginViewer.getCheckedElements(); for (Object element : elements) { if (element instanceof IPluginModelBase model) { @@ -265,14 +324,17 @@ protected int createPropertySheet(Composite parent) { return style == SWT.NULL ? 2 : 0; } - public void initializeFrom(ILaunchConfiguration config) { + private void activateInternal(ILaunchConfiguration config) { fMasterOptions.clear(); disposePropertySources(); try { fTracingCheck.setSelection(config.getAttribute(IPDELauncherConstants.TRACING, false)); Map options = config.getAttribute(IPDELauncherConstants.TRACING_OPTIONS, (Map) null); - TracingOptionsManager mgr = PDECore.getDefault().getTracingOptionsManager(); - fMasterOptions.putAll(options == null ? mgr.getTracingTemplateCopy() : mgr.getTracingOptions(options)); + + fMasterOptions.putAll(options == null // + ? fTracingOptionsManagerDelegate.getTracingTemplateCopy() // + : fTracingOptionsManagerDelegate.getTracingOptions(options)); + masterCheckChanged(); String checked = config.getAttribute(IPDELauncherConstants.TRACING_CHECKED, (String) null); if (checked == null) { @@ -302,6 +364,10 @@ public void initializeFrom(ILaunchConfiguration config) { } } + public void setRunnableContext(IRunnableContext runnableContext) { + fTracingOptionsManagerDelegate.setRunnableContext(runnableContext); + } + public void performApply(ILaunchConfigurationWorkingCopy config) { boolean tracingEnabled = fTracingCheck.getSelection(); config.setAttribute(IPDELauncherConstants.TRACING, tracingEnabled); @@ -348,6 +414,7 @@ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { } public void activated(ILaunchConfigurationWorkingCopy workingCopy) { + activateInternal(workingCopy); fPageBook.getParent().getParent().layout(true); } @@ -435,7 +502,7 @@ private TracingPropertySource getPropertySource(IPluginModelBase model) { return null; return fPropertySources.computeIfAbsent(model, m -> { String id = m.getPluginBase().getId(); - Map defaults = PDECore.getDefault().getTracingOptionsManager().getTemplateTable(id); + Map defaults = fTracingOptionsManagerDelegate.getTemplateTable(id); TracingPropertySource source = new TracingPropertySource(m, fMasterOptions, defaults, this); source.setChanged(true); return source; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties index cf7c3f47dc8..110d70ed079 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties @@ -599,6 +599,7 @@ TracingTab_AttributeLabel_TracingOptions=Tracing options TracingTab_AttributeLabel_TracingChecked=Tracing select all TracingTab_AttributeLabel_TracingNone=Tracing select none +TracingBlock_initializing_tracing_options=Initializing tracing options TracingBlock_restore_default=Restore &All to Defaults TracingBlock_restore_default_selected=Restore &Selected to Defaults TracingLauncherTab_name = Trac&ing diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/ui/launcher/TracingTab.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/ui/launcher/TracingTab.java index 636dd712d39..5fc25c0371c 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/ui/launcher/TracingTab.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/ui/launcher/TracingTab.java @@ -16,6 +16,7 @@ import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.pde.internal.ui.IHelpContextIds; import org.eclipse.pde.internal.ui.PDEPlugin; @@ -81,7 +82,13 @@ public void dispose() { @Override public void initializeFrom(ILaunchConfiguration config) { - fTracingBlock.initializeFrom(config); + // the heavy lifting occurs in #activated(...) + } + + @Override + public void setLaunchConfigurationDialog(ILaunchConfigurationDialog dialog) { + super.setLaunchConfigurationDialog(dialog); + fTracingBlock.setRunnableContext(dialog); } @Override