Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspingel2008-04-18 21:20:56 +0000
committerspingel2008-04-18 21:20:56 +0000
commit73a22a9421d33160ed3b96e64fd7f503599cbf8b (patch)
tree7ead048ae61883b85f7bc6d06a89d5ff42fcde1e /org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal
parent947464379423a02059c5089bcb2fe378280ac488 (diff)
downloadorg.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')
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/AttributeTaskMapper.java68
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/DefaultTaskContributor.java70
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/IRepositoryConstants.java26
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/KeyValueParser.java103
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMapping.java46
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/PluginRepositoryMappingManager.java128
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskContributorManager.java114
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TaskErrorReporter.java154
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/TasksBugsPlugin.java51
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/NewTaskFromErrorAction.java114
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/actions/ReportBugAction.java46
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/FeatureStatus.java31
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/ReportBugWizard.java76
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectFeaturePage.java157
-rw-r--r--org.eclipse.mylyn.tasks.bugs/src/org/eclipse/mylyn/internal/tasks/bugs/wizards/SelectProductPage.java283
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

Back to the top