### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.context.ui Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.contexts/org.eclipse.mylyn.context.ui/META-INF/MANIFEST.MF,v retrieving revision 1.381 diff -u -r1.381 MANIFEST.MF --- META-INF/MANIFEST.MF 26 Jun 2010 07:37:24 -0000 1.381 +++ META-INF/MANIFEST.MF 12 Mar 2011 01:04:45 -0000 @@ -23,6 +23,7 @@ Bundle-ActivationPolicy: lazy Bundle-Vendor: %Bundle-Vendor Export-Package: org.eclipse.mylyn.context.ui, + org.eclipse.mylyn.context.ui.strategy, org.eclipse.mylyn.internal.context.ui;x-internal:=true, org.eclipse.mylyn.internal.context.ui.actions;x-internal:=true, org.eclipse.mylyn.internal.context.ui.commands;x-internal:=true, Index: plugin.xml =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.contexts/org.eclipse.mylyn.context.ui/plugin.xml,v retrieving revision 1.168 diff -u -r1.168 plugin.xml --- plugin.xml 3 Mar 2011 02:03:26 -0000 1.168 +++ plugin.xml 12 Mar 2011 01:04:45 -0000 @@ -13,6 +13,7 @@ + Index: schema/strategies.exsd =================================================================== RCS file: schema/strategies.exsd diff -N schema/strategies.exsd --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ schema/strategies.exsd 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,102 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + Index: src/org/eclipse/mylyn/context/ui/strategy/AbstractContextComputationStrategy.java =================================================================== RCS file: src/org/eclipse/mylyn/context/ui/strategy/AbstractContextComputationStrategy.java diff -N src/org/eclipse/mylyn/context/ui/strategy/AbstractContextComputationStrategy.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/context/ui/strategy/AbstractContextComputationStrategy.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.context.ui.strategy; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.mylyn.context.core.IInteractionContext; +import org.eclipse.mylyn.tasks.core.data.TaskData; + +/** + * A strategy for computing context of a task. Implementations take a task data and from it derive a list of objects + * that can be added to the context. + * + * @author David Green + * @since 3.6 + */ +public abstract class AbstractContextComputationStrategy { + /** + * compute a list of objects that should be added to the context based on the task data. + */ + public abstract List computeContext(IProgressMonitor monitor, IInteractionContext context, TaskData taskData); + +} Index: src/org/eclipse/mylyn/context/ui/strategy/CompoundContextComputationStrategy.java =================================================================== RCS file: src/org/eclipse/mylyn/context/ui/strategy/CompoundContextComputationStrategy.java diff -N src/org/eclipse/mylyn/context/ui/strategy/CompoundContextComputationStrategy.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/context/ui/strategy/CompoundContextComputationStrategy.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.context.ui.strategy; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.mylyn.context.core.IInteractionContext; +import org.eclipse.mylyn.tasks.core.data.TaskData; + +/** + * A compound context computation strategy, that uses delegates to do the work of computing a context. + * + * @author David Green + * @since 3.6 + */ +public class CompoundContextComputationStrategy extends AbstractContextComputationStrategy { + + private List delegates; + + @Override + public List computeContext(IProgressMonitor m, IInteractionContext context, TaskData taskData) { + if (delegates == null || delegates.isEmpty()) { + return Collections.emptyList(); + } + List objects = new ArrayList(); + + SubMonitor monitor = SubMonitor.convert(m); + int workPerDelegate = 1000; + monitor.beginTask("Computing context", delegates.size() * workPerDelegate); + try { + for (AbstractContextComputationStrategy delegate : delegates) { + if (monitor.isCanceled()) { + break; + } + objects.addAll(delegate.computeContext(monitor.newChild(workPerDelegate), context, taskData)); + } + } finally { + monitor.done(); + } + + return objects; + } + + public List getDelegates() { + return delegates; + } + + public void setDelegates(List delegates) { + this.delegates = delegates; + } + +} Index: src/org/eclipse/mylyn/internal/context/ui/ContextPopulationStrategy.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/context/ui/ContextPopulationStrategy.java diff -N src/org/eclipse/mylyn/internal/context/ui/ContextPopulationStrategy.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/context/ui/ContextPopulationStrategy.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.context.ui; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.mylyn.context.core.AbstractContextStructureBridge; +import org.eclipse.mylyn.context.core.ContextChangeEvent; +import org.eclipse.mylyn.context.core.ContextCore; +import org.eclipse.mylyn.context.core.IInteractionContext; +import org.eclipse.mylyn.context.ui.AbstractFocusViewAction; +import org.eclipse.mylyn.context.ui.strategy.AbstractContextComputationStrategy; +import org.eclipse.mylyn.context.ui.strategy.CompoundContextComputationStrategy; +import org.eclipse.mylyn.monitor.core.InteractionEvent; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.ITask.SynchronizationState; +import org.eclipse.mylyn.tasks.core.data.TaskData; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.internal.Workbench; +import org.eclipse.ui.progress.UIJob; + +/** + * Populate a context from a task data + * + * @author David Green + * @see AbstractContextComputationStrategy + */ +public class ContextPopulationStrategy { + + private static final String PART_ID = ContextPopulationStrategy.class.getName(); + + private AbstractContextComputationStrategy contextComputationStrategy; + + private boolean disabled; + + public void activated(ContextChangeEvent event) { + if (disabled) { + return; + } + + // detect empty context + if (event.getContext().getAllElements().isEmpty()) { + // get corresponding task + ITask task = TasksUi.getRepositoryModel().getTask(event.getContextHandle()); + if (task != null) { + try { + TaskData taskData; + if (task.getSynchronizationState() == SynchronizationState.OUTGOING + || task.getSynchronizationState() == SynchronizationState.OUTGOING_NEW) { + taskData = TasksUi.getTaskDataManager().getWorkingCopy(task).getEditsData(); + } else { + taskData = TasksUi.getTaskDataManager().getTaskData(task); + } + if (taskData != null) { + IInteractionContext context = event.getContext(); + populateContext(context, taskData); + } + } catch (CoreException e) { + ContextUiPlugin.getDefault().getLog().log(e.getStatus()); + } + } + } + } + + public void populateContext(final IInteractionContext context, final TaskData taskData) { + + Job job = new Job("Populate context") { + @Override + protected IStatus run(IProgressMonitor monitor) { + final List contextItems = getContextComputationStrategy().computeContext(monitor, context, + taskData); + if (monitor.isCanceled()) { + return Status.CANCEL_STATUS; + } + if (!contextItems.isEmpty()) { + UIJob uiJob = new UIJob("Populate Context") { + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + IInteractionContext activeContext = ContextCore.getContextManager().getActiveContext(); + if (activeContext != null + && activeContext.getHandleIdentifier().equals(context.getHandleIdentifier())) { + monitor.beginTask("Populate Context", contextItems.size()); + try { + for (Object element : contextItems) { + + monitor.worked(1); + AbstractContextStructureBridge structureBridge = ContextCore.getStructureBridge(element); + if (structureBridge != null) { + String handleIdentifier = structureBridge.getHandleIdentifier(element); + if (handleIdentifier != null) { + try { + ContextCore.getContextManager().processInteractionEvent( + new InteractionEvent(InteractionEvent.Kind.SELECTION, + structureBridge.getContentType(), handleIdentifier, + PART_ID)); + } catch (Exception e) { + IStatus status = new Status(IStatus.ERROR, + ContextUiPlugin.ID_PLUGIN, "cannot manipulate context", e); + ContextUiPlugin.getDefault().getLog().log(status); + } + } + } + } + } finally { + monitor.done(); + } + if (!activeContext.getAllElements().isEmpty()) { + // activate structured view filters if needed + if (ContextUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(IContextUiPreferenceContstants.AUTO_FOCUS_NAVIGATORS)) { + for (IWorkbenchWindow window : Workbench.getInstance().getWorkbenchWindows()) { + for (IWorkbenchPage page : window.getPages()) { + for (IViewReference viewReference : page.getViewReferences()) { + IViewPart viewPart = (IViewPart) viewReference.getPart(false); + if (viewPart != null) { + AbstractFocusViewAction applyAction = AbstractFocusViewAction.getActionForPart(viewPart); + if (applyAction != null) { + applyAction.update(true); + } + } + } + } + } + } + } + } + + return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; + } + }; + uiJob.schedule(); + + } + return Status.OK_STATUS; + } + }; + job.schedule(); + } + + public synchronized AbstractContextComputationStrategy getContextComputationStrategy() { + if (contextComputationStrategy == null) { + List strategies = StrategiesExtensionPointReader.readContextComputationStrategies(); + if (strategies.isEmpty()) { + disabled = true; + } else if (strategies.size() > 1) { + CompoundContextComputationStrategy compoundStrategy = new CompoundContextComputationStrategy(); + compoundStrategy.setDelegates(strategies); + contextComputationStrategy = compoundStrategy; + } else { + contextComputationStrategy = strategies.get(0); + } + } + return contextComputationStrategy; + } + + public void setContextComputationStrategy(AbstractContextComputationStrategy contextComputationStrategy) { + this.contextComputationStrategy = contextComputationStrategy; + } + +} Index: src/org/eclipse/mylyn/internal/context/ui/ContextUiPlugin.java =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.contexts/org.eclipse.mylyn.context.ui/src/org/eclipse/mylyn/internal/context/ui/ContextUiPlugin.java,v retrieving revision 1.45 diff -u -r1.45 ContextUiPlugin.java --- src/org/eclipse/mylyn/internal/context/ui/ContextUiPlugin.java 21 Feb 2011 21:21:37 -0000 1.45 +++ src/org/eclipse/mylyn/internal/context/ui/ContextUiPlugin.java 12 Mar 2011 01:04:45 -0000 @@ -83,6 +83,7 @@ switch (event.getEventKind()) { case PRE_ACTIVATED: initLazyStart(); + contextPopulationStrategy.activated(event); break; } } @@ -110,6 +111,8 @@ private final Map> preservedFilterIds = new HashMap>(); + private final ContextPopulationStrategy contextPopulationStrategy = new ContextPopulationStrategy(); + private static final AbstractContextLabelProvider DEFAULT_LABEL_PROVIDER = new AbstractContextLabelProvider() { @Override @@ -235,9 +238,6 @@ StatusHandler.log(new Status(IStatus.ERROR, super.getBundle().getSymbolicName(), IStatus.ERROR, "Could not lazy start context plug-in", t)); //$NON-NLS-1$ } - if (TasksUi.getTaskActivityManager() != null) { - ContextCore.getContextManager().removeListener(contextActivationListener); - } } } Index: src/org/eclipse/mylyn/internal/context/ui/StrategiesExtensionPointReader.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/context/ui/StrategiesExtensionPointReader.java diff -N src/org/eclipse/mylyn/internal/context/ui/StrategiesExtensionPointReader.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/context/ui/StrategiesExtensionPointReader.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.context.ui; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.context.ui.strategy.AbstractContextComputationStrategy; +import org.eclipse.osgi.util.NLS; + +/** + * Read the strategies extension point + * + * @author David Green + */ +public class StrategiesExtensionPointReader { + + private static final String CONTEXT_COMPUTATION_STRATEGY = "contextComputationStrategy"; //$NON-NLS-1$ + + private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$ + + private static final String STRATEGIES_EXTENSION_POINT_ID = "org.eclipse.mylyn.context.ui.strategies"; //$NON-NLS-1$ + + public static List readContextComputationStrategies() { + List strategies = new ArrayList(); + + IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint( + STRATEGIES_EXTENSION_POINT_ID); + IExtension[] extensions = extensionPoint.getExtensions(); + for (IExtension extension : extensions) { + IConfigurationElement[] configurationElements = extension.getConfigurationElements(); + for (IConfigurationElement element : configurationElements) { + if (element.getName().equals(CONTEXT_COMPUTATION_STRATEGY)) { + try { + AbstractContextComputationStrategy strategy = (AbstractContextComputationStrategy) element.createExecutableExtension(ATTRIBUTE_CLASS); + strategies.add(strategy); + } catch (Throwable t) { + ContextUiPlugin.getDefault() + .getLog() + .log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind( + "Cannot instantiate {0} from bundle {1}: {2}", + new Object[] { element.getAttribute(ATTRIBUTE_CLASS), + extension.getContributor().getName(), t.getMessage() }), t)); + } + } + } + } + return strategies; + } +} #P org.eclipse.mylyn.java.tests Index: src/org/eclipse/mylyn/java/tests/JavaStackTraceContextComputationStrategyTest.java =================================================================== RCS file: src/org/eclipse/mylyn/java/tests/JavaStackTraceContextComputationStrategyTest.java diff -N src/org/eclipse/mylyn/java/tests/JavaStackTraceContextComputationStrategyTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/java/tests/JavaStackTraceContextComputationStrategyTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.java.tests; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.mylyn.internal.context.core.InteractionContext; +import org.eclipse.mylyn.internal.context.core.InteractionContextScaling; +import org.eclipse.mylyn.internal.java.ui.JavaStackTraceContextComputationStrategy; +import org.eclipse.mylyn.internal.java.ui.JavaStackTraceContextComputationStrategy.Element; + +/** + * test for {@link JavaStackTraceContextComputationStrategy} + * + * @author David Green + */ +public class JavaStackTraceContextComputationStrategyTest extends TestCase { + + private InteractionContext context; + + private JavaStackTraceContextComputationStrategy stackTraceDetector; + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = new InteractionContext("test", new InteractionContextScaling()); + stackTraceDetector = new JavaStackTraceContextComputationStrategy(); + } + + public void testStackTrace() throws IOException { + List contextObjects = stackTraceDetector.computeElements(getContent("resources/taskDescription1.txt")); + assertFalse(contextObjects.isEmpty()); + assertTrue(contextObjects.contains(new Element("java.lang.NullPointerException", null))); + assertTrue(contextObjects.contains(new Element( + "org.eclipse.mylyn.internal.tasks.ui.editors.AttachmentTableLabelProvider", "getAttachmentId"))); + assertTrue(contextObjects.contains(new Element( + "org.eclipse.mylyn.internal.tasks.ui.editors.AttachmentTableLabelProvider", "getColumnText"))); + assertTrue(contextObjects.contains(new Element( + "org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable", "run"))); + } + + private String getContent(String path) throws IOException { + InputStream in = JavaStackTraceContextComputationStrategyTest.class.getResourceAsStream(path); + if (in == null) { + throw new IllegalStateException(path); + } + try { + StringWriter writer = new StringWriter(); + Reader reader = new InputStreamReader(new BufferedInputStream(in), "utf-8"); + int i; + while ((i = reader.read()) != -1) { + writer.write(i); + } + return writer.toString(); + } finally { + in.close(); + } + } +} Index: src/org/eclipse/mylyn/java/tests/resources/taskDescription1.txt =================================================================== RCS file: src/org/eclipse/mylyn/java/tests/resources/taskDescription1.txt diff -N src/org/eclipse/mylyn/java/tests/resources/taskDescription1.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/java/tests/resources/taskDescription1.txt 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,102 @@ +FYI, a refresh of the task editor fixes this problem if you see it, but a fix is in the works. + +java.lang.NullPointerException +at org.eclipse.mylyn.internal.tasks.ui.editors.AttachmentTableLabelProvider.getAttachmentId(AttachmentTableLabelProvider.java:133) +at org.eclipse.mylyn.internal.tasks.ui.editors.AttachmentTableLabelProvider.getColumnText(AttachmentTableLabelProvider.java:126) +at org.eclipse.mylyn.internal.tasks.ui.editors.AttachmentTableLabelProvider.update(AttachmentTableLabelProvider.java:210) +at org.eclipse.jface.viewers.ViewerColumn.refresh(ViewerColumn.java:152) +at org.eclipse.jface.viewers.AbstractTableViewer.doUpdateItem(AbstractTableViewer.java:399) +at org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable.run(StructuredViewer.java:481) +at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) +at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) +at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) +at org.eclipse.jface.viewers.StructuredViewer.updateItem(StructuredViewer.java:2141) +at org.eclipse.jface.viewers.AbstractTableViewer.internalRefreshAll(AbstractTableViewer.java:711) +at org.eclipse.jface.viewers.AbstractTableViewer.internalRefresh(AbstractTableViewer.java:649) +at org.eclipse.jface.viewers.AbstractTableViewer.internalRefresh(AbstractTableViewer.java:636) +at org.eclipse.jface.viewers.StructuredViewer$7.run(StructuredViewer.java:1487) +at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1422) +at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1383) +at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1485) +at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer.java:537) +at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1444) +at org.eclipse.mylyn.internal.provisional.commons.ui.TableViewerSupport.restore(TableViewerSupport.java:143) +at org.eclipse.mylyn.internal.provisional.commons.ui.TableViewerSupport.(TableViewerSupport.java:66) +at org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttachmentPart.createAttachmentTable(TaskEditorAttachmentPart.java:183) +at org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttachmentPart.expandSection(TaskEditorAttachmentPart.java:249) +at org.eclipse.mylyn.internal.tasks.ui.editors.TaskEditorAttachmentPart.createControl(TaskEditorAttachmentPart.java:226) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.initializePart(AbstractTaskEditorPage.java:1290) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.access$6(AbstractTaskEditorPage.java:1282) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage$14.run(AbstractTaskEditorPage.java:867) +at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createParts(AbstractTaskEditorPage.java:858) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createParts(AbstractTaskEditorPage.java:842) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createFormContentInternal(AbstractTaskEditorPage.java:729) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createFormContent(AbstractTaskEditorPage.java:674) +at org.eclipse.ui.forms.editor.FormPage$1.run(FormPage.java:152) +at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) +at org.eclipse.ui.forms.editor.FormPage.createPartControl(FormPage.java:150) +at org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage.createPartControl(AbstractTaskEditorPage.java:632) +at org.eclipse.ui.forms.editor.FormEditor.pageChange(FormEditor.java:471) +at org.eclipse.ui.part.MultiPageEditorPart.setActivePage(MultiPageEditorPart.java:1067) +at org.eclipse.ui.forms.editor.FormEditor.setActivePage(FormEditor.java:603) +at org.eclipse.ui.forms.editor.SharedHeaderFormEditor.setActivePage(SharedHeaderFormEditor.java:110) +at org.eclipse.mylyn.tasks.ui.editors.TaskEditor.addPages(TaskEditor.java:407) +at org.eclipse.ui.forms.editor.FormEditor.createPages(FormEditor.java:138) +at org.eclipse.ui.forms.editor.SharedHeaderFormEditor.createPages(SharedHeaderFormEditor.java:98) +at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) +at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) +at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) +at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) +at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:289) +at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2863) +at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2768) +at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2760) +at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2711) +at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) +at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2707) +at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2691) +at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2674) +at org.eclipse.mylyn.tasks.ui.TasksUiUtil.openEditor(TasksUiUtil.java:177) +at org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal.openTask(TasksUiInternal.java:890) +at org.eclipse.mylyn.tasks.ui.TasksUiUtil.openTask(TasksUiUtil.java:280) +at org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal.refreshAndOpenTaskListElement(TasksUiInternal.java:291) +at org.eclipse.mylyn.internal.tasks.ui.actions.OpenTaskListElementAction.runWithEvent(OpenTaskListElementAction.java:56) +at org.eclipse.mylyn.internal.tasks.ui.actions.OpenTaskListElementAction.run(OpenTaskListElementAction.java:47) +at org.eclipse.mylyn.internal.tasks.ui.views.TaskListView$20.open(TaskListView.java:1254) +at org.eclipse.jface.viewers.StructuredViewer$2.run(StructuredViewer.java:845) +at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) +at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49) +at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) +at org.eclipse.jface.viewers.StructuredViewer.fireOpen(StructuredViewer.java:843) +at org.eclipse.jface.viewers.StructuredViewer.handleOpen(StructuredViewer.java:1131) +at org.eclipse.jface.viewers.StructuredViewer$6.handleOpen(StructuredViewer.java:1235) +at org.eclipse.jface.util.OpenStrategy.fireOpenEvent(OpenStrategy.java:264) +at org.eclipse.jface.util.OpenStrategy.access$2(OpenStrategy.java:258) +at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:298) +at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) +at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) +at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066) +at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657) +at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629) +at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593) +at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427) +at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670) +at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) +at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663) +at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) +at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115) +at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) +at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) +at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) +at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369) +at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) +at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) +at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) +at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) +at java.lang.reflect.Method.invoke(Unknown Source) +at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619) +at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574) +at org.eclipse.equinox.launcher.Main.run(Main.java:1407) +at org.eclipse.equinox.launcher.Main.main(Main.java:1383) + #P org.eclipse.mylyn.java.ui Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.contexts/org.eclipse.mylyn.java.ui/META-INF/MANIFEST.MF,v retrieving revision 1.393 diff -u -r1.393 MANIFEST.MF --- META-INF/MANIFEST.MF 26 Jun 2010 07:37:46 -0000 1.393 +++ META-INF/MANIFEST.MF 12 Mar 2011 01:04:46 -0000 @@ -27,6 +27,7 @@ org.eclipse.mylyn.commons.ui;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.monitor.ui;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.resources.ui;bundle-version="[3.0.0,4.0.0)", + org.eclipse.mylyn.tasks.core;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.monitor.core;bundle-version="[3.0.0,4.0.0)", org.eclipse.mylyn.ide.ui;bundle-version="[3.0.0,4.0.0)" Bundle-ActivationPolicy: lazy Index: plugin.xml =================================================================== RCS file: /cvsroot/mylyn/org.eclipse.mylyn.contexts/org.eclipse.mylyn.java.ui/plugin.xml,v retrieving revision 1.156 diff -u -r1.156 plugin.xml --- plugin.xml 21 Feb 2011 21:21:37 -0000 1.156 +++ plugin.xml 12 Mar 2011 01:04:46 -0000 @@ -544,5 +544,11 @@ name="%command.folding.auto.name"> + + + + Index: src/org/eclipse/mylyn/internal/java/ui/AbstractJavaContextComputationStrategy.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/java/ui/AbstractJavaContextComputationStrategy.java diff -N src/org/eclipse/mylyn/internal/java/ui/AbstractJavaContextComputationStrategy.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/java/ui/AbstractJavaContextComputationStrategy.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.java.ui; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.search.IJavaSearchConstants; +import org.eclipse.jdt.core.search.SearchEngine; +import org.eclipse.jdt.core.search.TypeNameMatch; +import org.eclipse.jdt.core.search.TypeNameMatchRequestor; +import org.eclipse.mylyn.context.ui.strategy.AbstractContextComputationStrategy; + +/** + * An abstract strategy that can find Java types in the workspace based on their fully qualified name. + * + * @author David Green + */ +public abstract class AbstractJavaContextComputationStrategy extends AbstractContextComputationStrategy { + + protected IType findTypeInWorkspace(String typeName) throws CoreException { + int dot = typeName.lastIndexOf('.'); + char[][] qualifications; + String simpleName; + if (dot != -1) { + qualifications = new char[][] { typeName.substring(0, dot).toCharArray() }; + simpleName = typeName.substring(dot + 1); + } else { + qualifications = null; + simpleName = typeName; + } + char[][] typeNames = new char[][] { simpleName.toCharArray() }; + + class ResultException extends RuntimeException { + private static final long serialVersionUID = 1L; + + private final IType fType; + + public ResultException(IType type) { + fType = type; + } + } + TypeNameMatchRequestor requestor = new TypeNameMatchRequestor() { + @Override + public void acceptTypeNameMatch(TypeNameMatch match) { + throw new ResultException(match.getType()); + } + }; + try { + new SearchEngine().searchAllTypeNames(qualifications, typeNames, SearchEngine.createWorkspaceScope(), + requestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null); + } catch (ResultException e) { + return e.fType; + } catch (Throwable t) { + // ignore + } + return null; + } +} Index: src/org/eclipse/mylyn/internal/java/ui/JavaStackTraceContextComputationStrategy.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/java/ui/JavaStackTraceContextComputationStrategy.java diff -N src/org/eclipse/mylyn/internal/java/ui/JavaStackTraceContextComputationStrategy.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/java/ui/JavaStackTraceContextComputationStrategy.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,192 @@ +/******************************************************************************* + * Copyright (c) 2011 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ +package org.eclipse.mylyn.internal.java.ui; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IType; +import org.eclipse.mylyn.context.core.IInteractionContext; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.core.data.TaskData; + +/** + * A strategy that computes Java items based on a Java stack trace in the task description. + * + * @author David Green + */ +public class JavaStackTraceContextComputationStrategy extends AbstractJavaContextComputationStrategy { + + private static final String PACKAGE_PART = "([a-z][a-z0-9]*)"; //$NON-NLS-1$ + + private static final String CLASS_PART = "[A-Za-z][a-zA-Z0-9_$]*"; //$NON-NLS-1$ + + private static final String FQN_PART = "((" + PACKAGE_PART + "\\.)*" + CLASS_PART + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + private static final Pattern STACK_TRACE_PATTERN = Pattern.compile("\\s*((" + "((Caused by:\\s+)|(at\\s+))?" //$NON-NLS-1$//$NON-NLS-2$ + + FQN_PART + "((:\\s+\\w.*)|(\\.((\\<(?:cl)?init\\>)|([a-zA-Z0-9_$]+))\\(.*?\\)))?" //$NON-NLS-1$ + + ")|(\\.\\.\\.\\s\\d+\\smore))"); //$NON-NLS-1$ + + /** + * public for testing only + */ + public static class Element { + String fqn; + + String methodName; + + public Element(String fqn, String methodName) { + this.fqn = fqn; + this.methodName = methodName; + } + + public Element() { + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Element [fqn="); //$NON-NLS-1$ + builder.append(fqn); + builder.append(", methodName="); //$NON-NLS-1$ + builder.append(methodName); + builder.append("]"); //$NON-NLS-1$ + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((fqn == null) ? 0 : fqn.hashCode()); + result = prime * result + ((methodName == null) ? 0 : methodName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Element other = (Element) obj; + if (fqn == null) { + if (other.fqn != null) { + return false; + } + } else if (!fqn.equals(other.fqn)) { + return false; + } + if (methodName == null) { + if (other.methodName != null) { + return false; + } + } else if (!methodName.equals(other.methodName)) { + return false; + } + return true; + } + + } + + private final int maxElements = 10; + + @Override + public List computeContext(IProgressMonitor monitor, IInteractionContext context, TaskData taskData) { + + TaskAttribute descriptionAttr = taskData.getRoot().getMappedAttribute(TaskAttribute.DESCRIPTION); + if (descriptionAttr != null) { + String description = descriptionAttr.getValue(); + if (description != null && description.length() > 0) { + return computeContext(monitor, description); + } + } + return Collections.emptyList(); + } + + public List computeContext(IProgressMonitor m, String description) { + SubMonitor monitor = SubMonitor.convert(m); + try { + List elements = computeElements(description); + if (!elements.isEmpty()) { + + monitor.beginTask("Finding Java context elements", elements.size()); + + final List javaElements = new ArrayList(); + try { + for (Element element : elements) { + try { + if (monitor.isCanceled()) { + break; + } + IType type = findTypeInWorkspace(element.fqn); + if (type != null) { + javaElements.add(type); + if (element.methodName != null) { + IMethod[] methods = type.getMethods(); + for (IMethod method : methods) { + if (method.getElementName().equals(element.methodName)) { + javaElements.add(method); + } + } + } + } + } catch (CoreException e) { + JavaUiBridgePlugin.getDefault().getLog().log(e.getStatus()); + } + monitor.worked(1); + } + } finally { + monitor.done(); + } + return javaElements; + } + } catch (IOException e) { + // ignore + } + return Collections.emptyList(); + } + + /** + * Public for test purposes only + */ + public List computeElements(String description) throws IOException { + List elements = new ArrayList(); + + BufferedReader reader = new BufferedReader(new StringReader(description)); + for (String line = reader.readLine(); line != null && elements.size() < maxElements; line = reader.readLine()) { + Matcher matcher = STACK_TRACE_PATTERN.matcher(line); + if (matcher.matches()) { + String fqn = matcher.group(6); + if (fqn != null) { + Element element = new Element(fqn, matcher.group(12)); + elements.add(element); + } + } + } + return elements; + } +}