diff options
author | spingel | 2008-04-18 21:20:56 +0000 |
---|---|---|
committer | spingel | 2008-04-18 21:20:56 +0000 |
commit | 73a22a9421d33160ed3b96e64fd7f503599cbf8b (patch) | |
tree | 7ead048ae61883b85f7bc6d06a89d5ff42fcde1e /org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal | |
parent | 947464379423a02059c5089bcb2fe378280ac488 (diff) | |
download | org.eclipse.mylyn.tasks-73a22a9421d33160ed3b96e64fd7f503599cbf8b.tar.gz org.eclipse.mylyn.tasks-73a22a9421d33160ed3b96e64fd7f503599cbf8b.tar.xz org.eclipse.mylyn.tasks-73a22a9421d33160ed3b96e64fd7f503599cbf8b.zip |
NEW - bug 217725: [api] review plug-in and feature dependencies
https://bugs.eclipse.org/bugs/show_bug.cgi?id=217725
Diffstat (limited to 'org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal')
15 files changed, 1467 insertions, 0 deletions
diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/AttributeTaskMapper.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/AttributeTaskMapper.java new file mode 100644 index 000000000..6a890d19e --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/AttributeTaskMapper.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.mylyn.tasks.core.DefaultTaskSchema; +import org.eclipse.mylyn.tasks.core.RepositoryTaskData; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.TaskSelection; +import org.eclipse.mylyn.tasks.ui.TasksUi; + +/** + * @author Steffen Pingel + */ +public class AttributeTaskMapper { + + private final Map<String, String> attributes; + + public AttributeTaskMapper(Map<String, String> attributes) { + Assert.isNotNull(attributes); + this.attributes = attributes; + } + + public boolean isMappingComplete() { + return getTaskRepository() != null && attributes.get(IRepositoryConstants.PRODUCT) != null; + } + + public TaskRepository getTaskRepository() { + TaskRepository taskRepository = null; + String repositoryUrl = attributes.get(IRepositoryConstants.REPOSITORY_URL); + if (repositoryUrl != null) { + String repositoryKind = attributes.get(IRepositoryConstants.REPOSITORY_KIND); + if (repositoryKind != null) { + taskRepository = TasksUi.getRepositoryManager().getRepository(repositoryUrl); + } else { + taskRepository = TasksUi.getRepositoryManager().getRepository(repositoryUrl, repositoryKind); + } + } + return taskRepository; + } + + public TaskSelection createTaskSelection() { + TaskSelection selection = new TaskSelection("", ""); + applyTo(selection.getTaskData()); + return selection; + } + + public void applyTo(RepositoryTaskData taskData) { + DefaultTaskSchema schema = new DefaultTaskSchema(taskData); + for (Entry<String, String> entry : attributes.entrySet()) { + if (IRepositoryConstants.PRODUCT.equals(entry.getKey())) { + schema.setProduct(entry.getValue()); + } else if (IRepositoryConstants.COMPONENT.equals(entry.getKey())) { + schema.setComponent(entry.getValue()); + } + } + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/DefaultTaskContributor.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/DefaultTaskContributor.java new file mode 100644 index 000000000..1b5e51c80 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/DefaultTaskContributor.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Map; + +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.mylyn.internal.tasks.bugs.wizards.FeatureStatus; +import org.eclipse.mylyn.tasks.bugs.AbstractTaskContributor; +import org.eclipse.mylyn.tasks.ui.editors.TaskEditor; +import org.osgi.framework.Bundle; + +/** + * @author Steffen Pingel + */ +public class DefaultTaskContributor extends AbstractTaskContributor { + + @Override + public Map<String, String> getAttributes(IStatus status) { + return null; + } + + @Override + public String getDescription(IStatus status) { + if (status instanceof FeatureStatus) { + StringBuilder sb = new StringBuilder(); + sb.append("\n\n\n"); + sb.append("-- Installed Plug-ins --\n"); + IBundleGroup bundleGroup = ((FeatureStatus)status).getBundleGroup(); + + sb.append(bundleGroup.getIdentifier()); + sb.append(" "); + sb.append(bundleGroup.getVersion()); + + Bundle[] bundles = bundleGroup.getBundles(); + if (bundles != null) { + for (Bundle bundle : bundles) { + sb.append(bundle.getBundleId()); + } + } + return sb.toString(); + + } else { + StringBuilder sb = new StringBuilder(); + sb.append("\n\n-- Error Details --\n"); + if (status.getException() != null) { + sb.append("\nStack Trace:\n"); + StringWriter writer = new StringWriter(); + status.getException().printStackTrace(new PrintWriter(writer)); + sb.append(writer.getBuffer()); + } + return sb.toString(); + } + } + + @Override + public String getEditorId(IStatus status) { + return TaskEditor.ID_EDITOR; + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/IRepositoryConstants.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/IRepositoryConstants.java new file mode 100644 index 000000000..54e33f06e --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/IRepositoryConstants.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +/** + * @author Steffen Pingel + */ +public class IRepositoryConstants { + + public static final String REPOSITORY_URL = "repositoryUrl"; + + public static final String REPOSITORY_KIND = "repositoryKind"; + + public static final String COMPONENT = "component"; + + public static final String PRODUCT = "product"; + + public static final String BRANDING = "branding"; + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/KeyValueParser.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/KeyValueParser.java new file mode 100644 index 000000000..2468fd2c1 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/KeyValueParser.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.text.ParseException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Steffen Pingel + */ +public class KeyValueParser { + + private final String text; + + private enum Mode { + KEY, VALUE + }; + + private Map<String, String> pairs; + + private StringBuilder token; + + private boolean escaping; + + private Mode mode; + + private String key; + + public KeyValueParser(String text) { + this.text = text; + + } + + public Map<String, String> parse() throws ParseException { + init(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '\\': + if (escaping) { + append(c); + } else { + escaping = true; + } + break; + case '=': + if (escaping) { + append(c); + } else if (mode == Mode.VALUE) { + throw new ParseException("Unexpected character '='", i); + } else { + key = token.toString(); + token.setLength(0); + mode = Mode.VALUE; + } + break; + case ';': + if (escaping) { + append(c); + } else if (mode == Mode.KEY) { + throw new ParseException("Unexpected character ';'", i); + } else { + pairs.put(key, token.toString()); + token.setLength(0); + mode = Mode.KEY; + } + break; + default: + append(c); + } + } + + if (mode == Mode.KEY) { + throw new ParseException("Unexpected end of input", text.length()); + } + + pairs.put(key, token.toString()); + + return Collections.unmodifiableMap(pairs); + } + + private void append(char c) { + escaping = false; + token.append(c); + } + + private void init() { + pairs = new HashMap<String, String>(); + token = new StringBuilder(); + mode = Mode.KEY; + escaping = false; + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMapping.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMapping.java new file mode 100644 index 000000000..ea159a33c --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMapping.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Steffen Pingel + */ +public class PluginRepositoryMapping { + + private List<String> prefixes = new ArrayList<String>(); + + private Map<String, String> attributes = new HashMap<String, String>(); + + public void addPrefix(String prefix) { + prefixes.add(prefix); + } + + public void addAttributes(Map<String, String> attributes) { + this.attributes.putAll(attributes); + } + + public void removePrefix(String prefix) { + prefixes.remove(prefix); + } + + public Map<String, String> getAttributes() { + return Collections.unmodifiableMap(attributes); + } + + public List<String> getPrefixes() { + return Collections.unmodifiableList(prefixes); + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMappingManager.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMappingManager.java new file mode 100644 index 000000000..07d7276d2 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMappingManager.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.text.ParseException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.monitor.core.StatusHandler; + +/** + * @author Steffen Pingel + */ +public class PluginRepositoryMappingManager { + + private static final String EXTENSION_ID_PLUGIN_REPOSITORY_MAPPING = "org.eclipse.mylyn.tasks.bugs.pluginRepositoryMappings"; + + private static final String ELEMENT_MAPPING = "mapping"; + + private static final String ELEMENT_MAPPING_ATTRIBUTES = "attributes"; + + private static final String ATTRIBUTE_PLUGID_ID_PREFIX = "pluginIdPrefix"; + + private TreeMap<String, PluginRepositoryMapping> mappingByPrefix; + + public PluginRepositoryMappingManager() { + readExtensions(); + } + + private void readMapping(IConfigurationElement element) { + String pluginIdPrefix = element.getAttribute(ATTRIBUTE_PLUGID_ID_PREFIX); + + Map<String, String> attributes = null; + IConfigurationElement[] attributeElements = element.getChildren(ELEMENT_MAPPING_ATTRIBUTES); + for (IConfigurationElement attributeElement : attributeElements) { + String repositoryAttributes = attributeElement.getValue(); + try { + KeyValueParser parser = new KeyValueParser(repositoryAttributes); + attributes = parser.parse(); + } catch (ParseException e) { + StatusHandler.log(new Status(IStatus.WARNING, TasksBugsPlugin.ID_PLUGIN, + "Invalid attributes in extension.", e)); + return; + } + } + + if (attributes != null) { + PluginRepositoryMapping pluginRepositoryMapping = new PluginRepositoryMapping(); + pluginRepositoryMapping.addAttributes(attributes); + pluginRepositoryMapping.addPrefix(pluginIdPrefix); + addPluginRepositoryMapping(pluginRepositoryMapping); + } else { + StatusHandler.log(new Status(IStatus.ERROR, TasksBugsPlugin.ID_PLUGIN, + "Missing attributes in extension.")); + } + } + + private void addPluginRepositoryMapping(PluginRepositoryMapping pluginRepositoryMapping) { + List<String> prefixs = pluginRepositoryMapping.getPrefixes(); + for (String prefix : prefixs) { + mappingByPrefix.put(prefix, pluginRepositoryMapping); + } + } + + private synchronized void readExtensions() { + mappingByPrefix = new TreeMap<String, PluginRepositoryMapping>(); + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = registry.getExtensionPoint(EXTENSION_ID_PLUGIN_REPOSITORY_MAPPING); + IExtension[] extensions = extensionPoint.getExtensions(); + for (IExtension extension : extensions) { + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (IConfigurationElement element : elements) { + if (element.getName().equals(ELEMENT_MAPPING)) { + readMapping(element); + } + } + } + } + + public PluginRepositoryMapping getMapping(String prefix) { + return mappingByPrefix.get(prefix); + } + + public String getAttribute(String prefix, String key) { + for (int i = prefix.length() - 1; i >= 0; i--) { + PluginRepositoryMapping mapping = getMapping(prefix.substring(0, i)); + if (mapping != null) { + String value = mapping.getAttributes().get(key); + if (value != null) { + return value; + } + } + } + return null; + } + + public Map<String, String> getAllAttributes(String prefix) { + Map<String, String> attributes = new HashMap<String, String>(); + for (int i = 0; i <= prefix.length(); i++) { + PluginRepositoryMapping mapping = getMapping(prefix.substring(0, i)); + if (mapping != null) { + attributes.putAll(mapping.getAttributes()); + } + } + return attributes; + } + + public boolean hasMappings() { + return !mappingByPrefix.isEmpty(); + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskContributorManager.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskContributorManager.java new file mode 100644 index 000000000..d1f408085 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskContributorManager.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.internal.monitor.core.IMonitorCoreConstants; +import org.eclipse.mylyn.monitor.core.StatusHandler; +import org.eclipse.mylyn.tasks.bugs.AbstractTaskContributor; +import org.eclipse.mylyn.tasks.core.RepositoryTaskData; + +/** + * @author Steffen Pingel + */ +public class TaskContributorManager { + + private static final String ELEMENT_CLASS = "class"; + + private static final String ELEMENT_TASK_CONTRIBUTOR = "contributor"; + + private static final String EXTENSION_ID_TASK_CONTRIBUTORS = "org.eclipse.mylyn.tasks.bugs.taskContributors"; + + private final DefaultTaskContributor defaultTaskContributor = new DefaultTaskContributor(); + + private boolean readExtensions; + + private final List<AbstractTaskContributor> taskContributors = new CopyOnWriteArrayList<AbstractTaskContributor>(); + + public void addErrorReporter(AbstractTaskContributor taskContributor) { + taskContributors.add(taskContributor); + } + + public String getEditorId(IStatus status) { + readExtensions(); + + for (AbstractTaskContributor contributor : taskContributors) { + String editorId = contributor.getEditorId(status); + if (editorId != null) { + return editorId; + } + } + + return defaultTaskContributor.getEditorId(status); + } + + private synchronized void readExtensions() { + if (readExtensions) { + return; + } + readExtensions = true; + + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = registry.getExtensionPoint(EXTENSION_ID_TASK_CONTRIBUTORS); + IExtension[] extensions = extensionPoint.getExtensions(); + for (IExtension extension : extensions) { + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (IConfigurationElement element : elements) { + if (element.getName().equals(ELEMENT_TASK_CONTRIBUTOR)) { + readTaskContributor(element); + } + } + } + } + + private void readTaskContributor(IConfigurationElement element) { + try { + Object object = element.createExecutableExtension(ELEMENT_CLASS); + if (object instanceof AbstractTaskContributor) { + taskContributors.add((AbstractTaskContributor) object); + } else { + StatusHandler.log(new Status(IStatus.WARNING, IMonitorCoreConstants.ID_PLUGIN, + "Could not load task contributor extenstion: \"" + object.getClass().getCanonicalName() + "\"" + + " does not implement \"" + AbstractTaskContributor.class.getCanonicalName() + "\"")); + } + } catch (CoreException e) { + StatusHandler.log(new Status(IStatus.WARNING, IMonitorCoreConstants.ID_PLUGIN, + "Could not load task contributor extension", e)); + } + } + + public void removeErrorReporter(AbstractTaskContributor taskContributor) { + taskContributors.remove(taskContributor); + } + + public void updateAttributes(RepositoryTaskData taskData, IStatus status) { + readExtensions(); + + for (AbstractTaskContributor contributor : taskContributors) { + String description = contributor.getDescription(status); + if (description != null) { + taskData.setDescription(description); + return; + } + } + + taskData.setDescription(defaultTaskContributor.getDescription(status)); + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskErrorReporter.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskErrorReporter.java new file mode 100644 index 000000000..565ab35ac --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskErrorReporter.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import java.lang.reflect.InvocationTargetException; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.monitor.core.AbstractErrorReporter; +import org.eclipse.mylyn.tasks.core.AbstractAttributeFactory; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.AbstractTask; +import org.eclipse.mylyn.tasks.core.AbstractTaskDataHandler; +import org.eclipse.mylyn.tasks.core.RepositoryTaskData; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.TaskSelection; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.mylyn.tasks.ui.TasksUiUtil; +import org.eclipse.mylyn.tasks.ui.editors.NewTaskEditorInput; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; + +/** + * @author Steffen Pingel + */ +public class TaskErrorReporter extends AbstractErrorReporter { + + private PluginRepositoryMappingManager manager; + + TaskErrorReporter() { + manager = new PluginRepositoryMappingManager(); + } + + public boolean isEnabled() { + return manager.hasMappings(); + } + + @Override + public int getPriority(IStatus status) { + Assert.isNotNull(status); + + String pluginId = status.getPlugin(); + for (int i = 0; i <= pluginId.length(); i++) { + if (manager.getMapping(pluginId.substring(0, i)) != null) { + return PRIORITY_DEFAULT; + } + } + + return PRIORITY_NONE; + } + + @Override + public void handle(IStatus status) { + Assert.isNotNull(status); + + String pluginId = status.getPlugin(); + Map<String, String> attributes = manager.getAllAttributes(pluginId); + + openNewTaskEditor(status, attributes); + } + + private void openNewTaskEditor(IStatus status, Map<String, String> attributes) { + AttributeTaskMapper mapper = new AttributeTaskMapper(attributes); + + TaskRepository taskRepository = mapper.getTaskRepository(); + try { + if (taskRepository != null) { + RepositoryTaskData taskData = createTaskData(taskRepository, mapper); + if (taskData != null) { + taskData.setSummary(status.getMessage()); + + TaskContributorManager manager = new TaskContributorManager(); + manager.updateAttributes(taskData, status); + + String editorId = manager.getEditorId(status); + + NewTaskEditorInput editorInput = new NewTaskEditorInput(taskRepository, taskData); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + TasksUiUtil.openEditor(editorInput, editorId, page); + return; + } + } + + TaskSelection taskSelection = mapper.createTaskSelection(); + updateAttributes(taskSelection.getTaskData(), status); + + // fall back to opening wizard + TasksUiUtil.openNewTaskEditor(null, taskSelection, taskRepository); + } catch (OperationCanceledException e) { + // ignore + } + } + + private RepositoryTaskData createTaskData(final TaskRepository taskRepository, AttributeTaskMapper mapper) { + AbstractRepositoryConnector connector = TasksUi.getRepositoryManager().getRepositoryConnector( + taskRepository.getConnectorKind()); + final AbstractTaskDataHandler taskDataHandler = connector.getTaskDataHandler(); + if (taskDataHandler == null) { + return null; + } + + AbstractAttributeFactory attributeFactory = taskDataHandler.getAttributeFactory(taskRepository.getRepositoryUrl(), + taskRepository.getConnectorKind(), AbstractTask.DEFAULT_TASK_KIND); + + final RepositoryTaskData taskData = new RepositoryTaskData(attributeFactory, taskRepository.getConnectorKind(), + taskRepository.getRepositoryUrl(), TasksUiPlugin.getDefault().getNextNewRepositoryTaskId()); + taskData.setNew(true); + + mapper.applyTo(taskData); + + try { + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + if (!taskDataHandler.initializeTaskData(taskRepository, taskData, monitor)) { + throw new InvocationTargetException(new Exception()); + } + } catch (CoreException e) { + throw new InvocationTargetException(e); + } catch (OperationCanceledException e) { + throw new InterruptedException(); + } + } + }; + + PlatformUI.getWorkbench().getProgressService().busyCursorWhile(runnable); + } catch (InvocationTargetException e) { + return null; + } catch (InterruptedException e) { + throw new OperationCanceledException(); + } + + taskDataHandler.cloneTaskData(mapper.createTaskSelection().getTaskData(), taskData); + + return taskData; + } + + private void updateAttributes(RepositoryTaskData taskData, IStatus status) { + + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TasksBugsPlugin.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TasksBugsPlugin.java new file mode 100644 index 000000000..3d1dc6472 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TasksBugsPlugin.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * @author Steffen Pingel + */ +public class TasksBugsPlugin extends AbstractUIPlugin { + + public static final String ID_PLUGIN = "org.eclipse.mylyn.tasks.bugs"; + + private static TasksBugsPlugin INSTANCE; + + private static TaskErrorReporter taskErrorReporter; + + public static TasksBugsPlugin getDefault() { + return INSTANCE; + } + + public static synchronized TaskErrorReporter getTaskErrorReporter() { + if (taskErrorReporter == null) { + taskErrorReporter = new TaskErrorReporter(); + } + return taskErrorReporter; + } + + public TasksBugsPlugin() { + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + INSTANCE = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + INSTANCE = null; + super.stop(context); + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/NewTaskFromErrorAction.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/NewTaskFromErrorAction.java new file mode 100644 index 000000000..1308e852c --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/NewTaskFromErrorAction.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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: + * Chris Aniszczyk <zx@us.ibm.com> - bug 208819 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.actions; + +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.mylyn.internal.tasks.bugs.TasksBugsPlugin; +import org.eclipse.mylyn.tasks.core.TaskSelection; +import org.eclipse.mylyn.tasks.ui.TasksUiUtil; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.views.log.LogEntry; + +/** + * Creates a new task from the selected error log entry. + * + * @author Jeff Pound + * @author Steffen Pingel + */ +public class NewTaskFromErrorAction implements IObjectActionDelegate { + + public static final String ID = "org.eclipse.mylyn.tasklist.ui.repositories.actions.create"; + + private LogEntry entry; + + /** + * Fills a {@link StringBuilder} with {@link LogEntry} information, optionally including subentries too + * + * @param entry + * The {@link LogEntry} who provides the information + * @param sb + * An {@link StringBuilder} to be filled with + * @param includeChildren + * Indicates if it should include subentries, if the {@link LogEntry} have any + */ + private void buildDescriptionFromLogEntry(LogEntry entry, StringBuilder sb, boolean includeChildren) { + sb.append("\n\n-- Error Log --\nDate: "); + sb.append(entry.getDate()); + sb.append("\nMessage: "); + sb.append(entry.getMessage()); + sb.append("\nSeverity: " + entry.getSeverityText()); + sb.append("\nPlugin ID: "); + sb.append(entry.getPluginId()); + sb.append("\nStack Trace:\n"); + if (entry.getStack() == null) { + sb.append("no stack trace available"); + } else { + sb.append(entry.getStack()); + } + + if (includeChildren && entry.hasChildren()) { + Object[] children = entry.getChildren(null); + for (Object child : children) { + if (child instanceof LogEntry) { + buildDescriptionFromLogEntry((LogEntry) child, sb, includeChildren); + } + } + } + } + + private void createTask(LogEntry entry) { + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + boolean includeChildren = false; + + if (entry.hasChildren() + && MessageDialog.openQuestion(shell, "Report Bug", "Include children of this entry in the report?")) { + includeChildren = true; + } + + StringBuilder sb = new StringBuilder(); + buildDescriptionFromLogEntry(entry, sb, includeChildren); + + if (TasksBugsPlugin.getTaskErrorReporter().isEnabled()) { + Status status = new Status(entry.getSeverity(), entry.getPluginId(), entry.getMessage()); + TasksBugsPlugin.getTaskErrorReporter().handle(status); + } else { + TaskSelection taskSelection = new TaskSelection("", sb.toString()); + TasksUiUtil.openNewTaskEditor(shell, taskSelection, null); + } + } + + public void run() { + createTask(entry); + } + + public void run(IAction action) { + run(); + } + + public void selectionChanged(IAction action, ISelection selection) { + Object object = ((IStructuredSelection) selection).getFirstElement(); + if (object instanceof LogEntry) { + entry = (LogEntry) object; + } + } + + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/ReportBugAction.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/ReportBugAction.java new file mode 100644 index 000000000..9d4df472d --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/ReportBugAction.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.mylyn.internal.tasks.bugs.TasksBugsPlugin; +import org.eclipse.mylyn.internal.tasks.bugs.wizards.ReportBugWizard; +import org.eclipse.mylyn.internal.tasks.ui.actions.NewTaskAction; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +/** + * @author Mik Kersten + */ +public class ReportBugAction implements IWorkbenchWindowActionDelegate { + + private IWorkbenchWindow window; + + public void dispose() { + } + + public void init(IWorkbenchWindow window) { + this.window = window; + } + + public void run(IAction action) { + if (TasksBugsPlugin.getTaskErrorReporter().isEnabled()) { + WizardDialog dialog = new WizardDialog(window.getShell(), new ReportBugWizard()); + dialog.open(); + } else { + new NewTaskAction().run(action); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + // ignore + } +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/FeatureStatus.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/FeatureStatus.java new file mode 100644 index 000000000..5637669ab --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/FeatureStatus.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.wizards; + +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @author Steffen Pingel + */ +public class FeatureStatus extends Status { + + private final IBundleGroup bundleGroup; + + public FeatureStatus(IBundleGroup bundleGroup) { + super(IStatus.INFO, bundleGroup.getIdentifier(), ""); + this.bundleGroup = bundleGroup; + } + + public IBundleGroup getBundleGroup() { + return bundleGroup; + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/ReportBugWizard.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/ReportBugWizard.java new file mode 100644 index 000000000..4f8c156f7 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/ReportBugWizard.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.wizards; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.mylyn.internal.tasks.bugs.TasksBugsPlugin; +import org.eclipse.mylyn.internal.tasks.bugs.PluginRepositoryMappingManager; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiImages; + +/** + * @author Steffen Pingel + */ +public class ReportBugWizard extends Wizard { + + private SelectProductPage selectProductPage; + + private PluginRepositoryMappingManager manager; + + public ReportBugWizard() { + setForcePreviousAndNextButtons(true); + setNeedsProgressMonitor(false); + setWindowTitle("Report Bug or Enhancement"); + setDefaultPageImageDescriptor(TasksUiImages.BANNER_REPOSITORY); + } + + @Override + public void addPages() { + manager = new PluginRepositoryMappingManager(); + selectProductPage = new SelectProductPage("selectBundleGroupProvider", manager); + addPage(selectProductPage); + } + + @Override + public boolean canFinish() { + return getSelectedBundleGroup() != null; + } + + public IBundleGroup getSelectedBundleGroup() { + IWizardPage page = getContainer().getCurrentPage(); + if (page instanceof SelectProductPage) { + if (page.isPageComplete() && !((SelectProductPage)page).canFlipToNextPage()) { + return ((SelectProductPage)page).getSelectedBundleGroup(); + } + } else if (page instanceof SelectFeaturePage) { + if (page.isPageComplete()) { + return ((SelectFeaturePage)page).getSelectedBundleGroup(); + } + } + return null; + } + + @Override + public boolean performFinish() { + final IBundleGroup bundle = getSelectedBundleGroup(); + Assert.isNotNull(bundle); + + // delay run this until after the dialog has been closed + getShell().getDisplay().asyncExec(new Runnable() { + public void run() { + TasksBugsPlugin.getTaskErrorReporter().handle(new FeatureStatus(bundle)); + } + }); + + return true; + } + +} diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectFeaturePage.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectFeaturePage.java new file mode 100644 index 000000000..16d81588a --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectFeaturePage.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.wizards; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.branding.IBundleGroupConstants; + +/** + * @author Steffen Pingel + */ +public class SelectFeaturePage extends WizardPage { + + private static final int TABLE_HEIGHT = IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH; + + private IBundleGroup selectedBundleGroup; + + private final IBundleGroup[] bundleGroups; + + private ImageRegistry imageRegistry; + + public SelectFeaturePage(String pageName, IBundleGroup[] bundleGroups) { + super(pageName); + this.bundleGroups = bundleGroups; + setTitle("Select a feature"); + } + + public void createControl(Composite parent) { + Composite container = new Composite(parent, SWT.NULL); + GridLayout layout = new GridLayout(1, true); + container.setLayout(layout); + + imageRegistry = new ImageRegistry(getShell().getDisplay()); + + for (IBundleGroup bundleGroup : bundleGroups) { + String imageUrl = bundleGroup.getProperty(IBundleGroupConstants.FEATURE_IMAGE); + if (imageUrl != null) { + try { + ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(new URL(imageUrl)); + imageRegistry.put(bundleGroup.getIdentifier(), imageDescriptor); + } catch (MalformedURLException e) { + // ignore + } + } + } + + TableViewer viewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).hint(SWT.DEFAULT, TABLE_HEIGHT).applyTo(viewer.getControl()); + viewer.setContentProvider(new IStructuredContentProvider() { + + public Object[] getElements(Object inputElement) { + return bundleGroups; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + }); + viewer.setLabelProvider(new LabelProvider() { + + @Override + public Image getImage(Object element) { + if (element instanceof IBundleGroup) { + IBundleGroup bundleGroup = (IBundleGroup) element; + return imageRegistry.get(bundleGroup.getIdentifier()); + } + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof IBundleGroup) { + IBundleGroup bundleGroup = (IBundleGroup) element; + return bundleGroup.getName(); + } + return ""; + } + + }); + viewer.setInput(TasksUi.getRepositoryManager().getRepositoryConnectors()); + + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.getFirstElement() instanceof IBundleGroup) { + selectedBundleGroup = (IBundleGroup) selection.getFirstElement(); + setMessage(selectedBundleGroup.getDescription()); + setPageComplete(true); + } else { + setMessage(null); + setPageComplete(false); + } + } + }); + + viewer.addOpenListener(new IOpenListener() { + + public void open(OpenEvent event) { + if (getWizard().performFinish()) { + ((WizardDialog) getContainer()).close(); + } + } + }); + + viewer.getTable().showSelection(); + viewer.getTable().setFocus(); + + viewer.setSorter(new ViewerSorter()); + + setControl(container); + } + + @Override + public void dispose() { + if (imageRegistry != null) { + imageRegistry.dispose(); + } + super.dispose(); + } + + public IBundleGroup getSelectedBundleGroup() { + return selectedBundleGroup; + } + +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectProductPage.java b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectProductPage.java new file mode 100644 index 000000000..4629721b9 --- /dev/null +++ b/org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectProductPage.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.bugs.wizards; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IBundleGroup; +import org.eclipse.core.runtime.IBundleGroupProvider; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.mylyn.internal.tasks.bugs.AttributeTaskMapper; +import org.eclipse.mylyn.internal.tasks.bugs.IRepositoryConstants; +import org.eclipse.mylyn.internal.tasks.bugs.PluginRepositoryMappingManager; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.branding.IBundleGroupConstants; + +/** + * @author Steffen Pingel + */ +public class SelectProductPage extends WizardPage { + + private static final int TABLE_HEIGHT = IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH; + + /** + * A container for bundles that map to the same name. + */ + private class BundleGroupContainer { + + private final IBundleGroup displayGroup; + + private final List<IBundleGroup> groups; + + private final String name; + + public BundleGroupContainer(String name, IBundleGroup displayGroup) { + this.name = name; + this.displayGroup = displayGroup; + this.groups = new ArrayList<IBundleGroup>(); + this.groups.add(displayGroup); + } + + public IBundleGroup getDisplayGroup() { + return displayGroup; + } + + public void addBundleGroup(IBundleGroup bundleGroup) { + for (IBundleGroup group : groups) { + if (group.getName().equals(bundleGroup.getName())) { + return; + } + } + groups.add(bundleGroup); + } + + public List<IBundleGroup> getGroups() { + return groups; + } + + private String getName() { + return name; + } + + public boolean requiresSelection() { + return groups.size() > 1; + } + + } + + private ImageRegistry imageRegistry; + + private final PluginRepositoryMappingManager manager; + + private BundleGroupContainer selectedBundleGroupContainer; + + public SelectProductPage(String pageName, PluginRepositoryMappingManager manager) { + super(pageName); + this.manager = manager; + setTitle("Select a product"); + } + + @Override + public boolean canFlipToNextPage() { + return selectedBundleGroupContainer != null && selectedBundleGroupContainer.requiresSelection(); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, true); + composite.setLayout(layout); + + imageRegistry = new ImageRegistry(getShell().getDisplay()); + + final Map<String, BundleGroupContainer> containerByName = getProducts(); + + TableViewer viewer = new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).hint(SWT.DEFAULT, TABLE_HEIGHT).applyTo(viewer.getControl()); + viewer.setContentProvider(new IStructuredContentProvider() { + + public void dispose() { + } + + public Object[] getElements(Object inputElement) { + return containerByName.values().toArray(); + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + }); + viewer.setLabelProvider(new LabelProvider() { + + @Override + public Image getImage(Object element) { + if (element instanceof BundleGroupContainer) { + BundleGroupContainer product = (BundleGroupContainer) element; + return imageRegistry.get(product.getName()); + } + return null; + } + + @Override + public String getText(Object element) { + if (element instanceof BundleGroupContainer) { + BundleGroupContainer product = (BundleGroupContainer) element; + return product.getName(); + } + return ""; + } + + }); + viewer.setInput(TasksUi.getRepositoryManager().getRepositoryConnectors()); + + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.getFirstElement() instanceof BundleGroupContainer) { + selectedBundleGroupContainer = (BundleGroupContainer) selection.getFirstElement(); + if (selectedBundleGroupContainer.requiresSelection()) { + setMessage(null); + } else { + setMessage(selectedBundleGroupContainer.getDisplayGroup().getDescription()); + } + setPageComplete(true); + } else { + setMessage(null); + setPageComplete(false); + } + } + }); + + viewer.addOpenListener(new IOpenListener() { + + public void open(OpenEvent event) { + if (canFlipToNextPage()) { + getContainer().showPage(getNextPage()); + } else if (isPageComplete()) { + if (getWizard().performFinish()) { + ((WizardDialog) getContainer()).close(); + } + } + } + }); + + viewer.getTable().showSelection(); + viewer.getTable().setFocus(); + + viewer.setSorter(new ViewerSorter()); + + setControl(composite); + } + + @Override + public void dispose() { + if (imageRegistry != null) { + imageRegistry.dispose(); + } + super.dispose(); + } + + @Override + public IWizardPage getNextPage() { + if (canFlipToNextPage()) { + SelectFeaturePage page = new SelectFeaturePage("selectBundle", getSelectedBundleGroups()); + page.setWizard(getWizard()); + return page; + } + return null; + } + + private Map<String, BundleGroupContainer> getProducts() { + final Map<String, BundleGroupContainer> containerByName = new HashMap<String, BundleGroupContainer>(); + IBundleGroupProvider[] providers = Platform.getBundleGroupProviders(); + if (providers != null) { + for (IBundleGroupProvider provider : providers) { + for (IBundleGroup bundleGroup : provider.getBundleGroups()) { + addProduct(containerByName, bundleGroup); + } + } + } + return containerByName; + } + + private void addProduct(Map<String, BundleGroupContainer> containerByName, IBundleGroup bundleGroup) { + Map<String, String> attributes = manager.getAllAttributes(bundleGroup.getIdentifier()); + + AttributeTaskMapper mapper = new AttributeTaskMapper(attributes); + if (!mapper.isMappingComplete()) { + return; + } + + String imageUrl = bundleGroup.getProperty(IBundleGroupConstants.FEATURE_IMAGE); + if (imageUrl == null) { + return; + } + + String productName = attributes.get(IRepositoryConstants.BRANDING); + if (productName == null) { + productName = bundleGroup.getName(); + } + + try { + ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(new URL(imageUrl)); + imageRegistry.put(productName, imageDescriptor); + } catch (MalformedURLException e) { + // ignore bundles that do not have a feature image + return; + } + + BundleGroupContainer container = containerByName.get(productName); + if (container == null) { + container = new BundleGroupContainer(productName, bundleGroup); + containerByName.put(productName, container); + } else { + container.addBundleGroup(bundleGroup); + } + } + + public IBundleGroup getSelectedBundleGroup() { + if (selectedBundleGroupContainer != null) { + return selectedBundleGroupContainer.getGroups().get(0); + } + return null; + } + + public IBundleGroup[] getSelectedBundleGroups() { + if (selectedBundleGroupContainer != null) { + return selectedBundleGroupContainer.getGroups().toArray(new IBundleGroup[0]); + } + return null; + } + +}
\ No newline at end of file |