Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkersten2005-07-12 23:41:41 +0000
committermkersten2005-07-12 23:41:41 +0000
commit23c8cbf0c6d069ce144d0844eb6071420662b796 (patch)
tree5767983ebefbf27e4b6e6fe04cb55f5118c191cf /org.eclipse.mylyn.tasks.core/src
parentbe3f7f6ab9e002af2321a0c1858251ba98df0441 (diff)
downloadorg.eclipse.mylyn.tasks-23c8cbf0c6d069ce144d0844eb6071420662b796.tar.gz
org.eclipse.mylyn.tasks-23c8cbf0c6d069ce144d0844eb6071420662b796.tar.xz
org.eclipse.mylyn.tasks-23c8cbf0c6d069ce144d0844eb6071420662b796.zip
Progress on Bugzilla Bug 103099
decouple tasks from mylar.ui
Diffstat (limited to 'org.eclipse.mylyn.tasks.core/src')
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaEditingMonitor.java46
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaMylarBridge.java143
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaNodeLabelProvider.java66
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaStructureBridge.java279
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaUiBridge.java141
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/MylarBugzillaPlugin.java100
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearch.java174
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchJob.java109
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchOperation.java526
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaReferencesProvider.java143
-rw-r--r--org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/Util.java195
11 files changed, 1922 insertions, 0 deletions
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaEditingMonitor.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaEditingMonitor.java
new file mode 100644
index 000000000..3bee8b160
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaEditingMonitor.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Apr 27, 2005
+ */
+package org.eclipse.mylar.bugzilla;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.bugzilla.ui.editor.AbstractBugEditor;
+import org.eclipse.mylar.bugzilla.ui.outline.BugzillaReportSelection;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaTaskEditor;
+import org.eclipse.mylar.core.AbstractSelectionMonitor;
+import org.eclipse.ui.IWorkbenchPart;
+
+
+/**
+ * @author Mik Kersten
+ */
+public class BugzillaEditingMonitor extends AbstractSelectionMonitor {
+
+ public BugzillaEditingMonitor() {
+ super();
+ }
+
+ @Override
+ protected void handleWorkbenchPartSelection(IWorkbenchPart part, ISelection selection) {
+ if(!(part instanceof AbstractBugEditor) && !(part instanceof BugzillaTaskEditor))
+ return;
+
+ if(selection instanceof StructuredSelection){
+ StructuredSelection ss = (StructuredSelection)selection;
+ Object object = ss.getFirstElement();
+ if(object instanceof BugzillaReportSelection) super.handleElementSelection(part, object);
+ }
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaMylarBridge.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaMylarBridge.java
new file mode 100644
index 000000000..38325ab31
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaMylarBridge.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Oct 1, 2004
+ */
+package org.eclipse.mylar.bugzilla;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+
+
+/**
+ * Class to handle the bridge between mylar and bugzilla
+ *
+ * @author Shawn Minto
+ */
+public class BugzillaMylarBridge {
+
+ /** The hash of all of the landmarks and their related search hits */
+ private HashMap<String, Map<Integer, List<BugzillaReportNode>>> landmarksHash;
+ /**
+ * The currently running search jobs so that we can cancel it if necessary <br> KEY: IMember VALUE: Job
+ */
+ public static HashMap<String, Job> runningJobs = new HashMap<String, Job>();
+
+ /**
+ * Constructor
+ */
+ public BugzillaMylarBridge() {
+ landmarksHash = new HashMap<String, Map<Integer, List<BugzillaReportNode>>>();
+ }
+
+
+ /**
+ * Remove a landmark from the hash
+ *
+ * @param removed
+ * This landmark to remove (IJavaElement)
+ */
+ public void removeFromLandmarksHash(IJavaElement removed) {
+ landmarksHash.remove(removed.getHandleIdentifier());
+ }
+
+ /**
+ * Remove all of the landmarks from the hash that are in the list
+ *
+ * @param removed
+ * This list of landmarks to remove (IJavaElements)
+ */
+ public void removeFromLandmarksHash(List<IJavaElement> removed) {
+
+ for(IJavaElement je : removed) {
+ landmarksHash.remove(je.getHandleIdentifier());
+ }
+ }
+
+ /**
+ * Add data to the landmarks hash
+ *
+ * @param doiList
+ * The list of BugzillaSearchHitDoiInfo
+ * @param m
+ * The member that this list is for
+ */
+ public void addToLandmarksHash(List<BugzillaReportNode> doiList, IMember m, int scope) {
+ Map<Integer, List<BugzillaReportNode>> searches = landmarksHash.get(m.getHandleIdentifier());
+
+ if(searches == null){
+ searches = new HashMap<Integer, List<BugzillaReportNode>>();
+ }
+ searches.put(scope, doiList);
+ landmarksHash.put(m.getHandleIdentifier(), searches);
+ }
+
+ /**
+ * Get the doiList for the given IMember from the landmarks hash
+ *
+ * @param m
+ * The member to get the doiList for
+ * @return The doiList or null if it doesn't exist
+ */
+ public List<BugzillaReportNode> getFromLandmarksHash(IMember m, int scope) {
+ Map<Integer, List<BugzillaReportNode>> scopes = landmarksHash.get(m.getHandleIdentifier());
+ if(scopes == null)
+ return null;
+ else
+ return scopes.get(scope);
+ }
+
+ /**
+ * Determine whether the current element has a search job running for it
+ *
+ * @param e
+ * The element that we want to know whether there is a search job
+ * or not
+ * @return <code>true</code> if it does else <code>false</code>
+ */
+ public static boolean doesJobExist(String handle) {
+ return runningJobs.containsKey(handle);
+ }
+
+ /**
+ * Remove search job for the given element
+ *
+ * @param m
+ * The element that we want to make sure that the search is
+ * canceled for
+ */
+ public static void removeSearchJob(String handle) {
+
+ // make sure that there wasn't a previous search job that we know
+ // of. If there was, cancel it
+ if (doesJobExist(handle)) {
+ // get the search job and wait until it is cancelled
+ Job prevJob = runningJobs.get(handle);
+ prevJob.cancel();
+ runningJobs.remove(handle);
+ }
+ }
+
+ /**
+ * Add a search job to our list
+ * @param handle The handle of the element that we are searching for
+ * @param searchJob The job that represents the search
+ */
+ public static void addJob(String handle, Job searchJob) {
+ runningJobs.put(handle, searchJob);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaNodeLabelProvider.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaNodeLabelProvider.java
new file mode 100644
index 000000000..b43781a00
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaNodeLabelProvider.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Apr 18, 2005
+ */
+package org.eclipse.mylar.bugzilla;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.mylar.bugzilla.core.BugReport;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+import org.eclipse.mylar.core.model.ITaskscapeNode;
+import org.eclipse.mylar.ui.MylarImages;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @author Mik Kersten
+ */
+public class BugzillaNodeLabelProvider implements ILabelProvider {
+
+ public Image getImage(Object element) {
+ return MylarImages.getImage(MylarImages.BUG);
+ }
+
+ /**
+ * TODO: slow?
+ */
+ public String getText(Object element) {
+ ITaskscapeNode node = (ITaskscapeNode)element;
+
+ // try to get from the cache before downloading
+ Object report;
+ BugzillaReportNode reportNode = MylarBugzillaPlugin.getReferenceProvider().getCached(node.getElementHandle());
+ BugReport cachedReport = MylarBugzillaPlugin.getDefault().getStructureBridge().getCached(node.getElementHandle());
+ if(reportNode != null && cachedReport == null){
+ report = reportNode;
+ } else{
+ report = MylarBugzillaPlugin.getDefault().getStructureBridge().getObjectForHandle(node.getElementHandle());
+ }
+ return MylarBugzillaPlugin.getDefault().getStructureBridge().getName(report);
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ // don't need to worry about listeners
+ }
+
+ public void dispose() {
+ // don't care about dispose
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ // don't need to worry about listeners
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaStructureBridge.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaStructureBridge.java
new file mode 100644
index 000000000..3d49edeaf
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaStructureBridge.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on May 2, 2005
+ */
+package org.eclipse.mylar.bugzilla;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.mylar.bugzilla.core.BugReport;
+import org.eclipse.mylar.bugzilla.core.BugzillaRepository;
+import org.eclipse.mylar.bugzilla.core.BugzillaTools;
+import org.eclipse.mylar.bugzilla.core.IBugzillaBug;
+import org.eclipse.mylar.bugzilla.core.search.BugzillaSearchHit;
+import org.eclipse.mylar.bugzilla.ui.editor.AbstractBugEditor;
+import org.eclipse.mylar.bugzilla.ui.outline.BugzillaOutlineNode;
+import org.eclipse.mylar.bugzilla.ui.outline.BugzillaReportSelection;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaCacheFile;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+import org.eclipse.mylar.core.IMylarStructureBridge;
+import org.eclipse.mylar.core.MylarPlugin;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.progress.IProgressService;
+import org.eclipse.ui.views.markers.internal.ProblemMarker;
+
+
+public class BugzillaStructureBridge implements IMylarStructureBridge {
+
+ public final static String EXTENSION = "bugzilla";
+
+ public String getResourceExtension() {
+ return EXTENSION;
+ }
+
+ public BugzillaStructureBridge() {
+ super();
+ readCacheFile();
+ }
+
+ /**
+ * Handle format: <server-name:port>;<bug-id>;<comment#>
+ *
+ * Use: BugzillaTools ???
+ */
+ public String getHandleIdentifier(Object object) {
+ if(object instanceof BugzillaOutlineNode){
+ BugzillaOutlineNode n = (BugzillaOutlineNode)object;
+ return BugzillaTools.getHandle(n);
+ }
+ else if(object instanceof BugzillaReportSelection){
+ BugzillaReportSelection n = (BugzillaReportSelection)object;
+ return BugzillaTools.getHandle(n);
+ }
+ return null;
+ }
+
+ private BugReport result;
+
+ public Object getObjectForHandle(final String handle) {
+ result = null;
+
+ String [] parts = handle.split(";");
+ if (parts.length >= 2){
+ String server = parts[0];
+ final int id = Integer.parseInt(parts[1]);
+
+ String bugHandle = server + ";" + id;
+
+ int commentNumber = -1;
+ if(parts.length == 3){
+ commentNumber = Integer.parseInt(parts[2]);
+ }
+
+ // get the bugzillaOutlineNode for the element
+ IEditorPart editorPart = null;
+ try{
+ editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+ }catch(NullPointerException e){
+ // do nothing, this just means that there is no active page
+ }
+ if(editorPart != null && editorPart instanceof AbstractBugEditor){
+ AbstractBugEditor abe = ((AbstractBugEditor)editorPart);
+ BugzillaOutlineNode node = abe.getModel();
+ return findNode(node, commentNumber);
+ }
+
+ // try to get from the cache, if it doesn't exist, startup an operation to get it
+ result = getFromCache(bugHandle);
+ if(result == null){
+ WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
+ protected void execute(IProgressMonitor monitor) throws CoreException {
+ monitor.beginTask("Downloading Bug# " + id, IProgressMonitor.UNKNOWN);
+ try {
+ result = BugzillaRepository.getInstance().getCurrentBug(id);
+ }catch(Exception e){
+ result = null;
+ }
+ }};
+
+ // Use the progess service to execute the runnable
+ IProgressService service = PlatformUI.getWorkbench().getProgressService();
+ try {
+ service.run(false, false, op);
+ } catch (InvocationTargetException e) {
+ // Operation was canceled
+ } catch (InterruptedException e) {
+ // Handle the wrapped exception
+ }
+
+ if(result != null)
+ cache(bugHandle, result);
+ }
+
+ BugzillaOutlineNode node = BugzillaOutlineNode.parseBugReport(result);
+ return findNode(node, commentNumber);
+ }
+ else{
+ return null;
+ }
+ }
+
+ private BugzillaOutlineNode findNode(BugzillaOutlineNode startNode, int commentNumber){
+
+ if(commentNumber == -1){
+ return startNode;
+ }else if(startNode.getComment() != null && startNode.getComment().getNumber() == commentNumber -1){
+ return startNode;
+ } else if(startNode.isCommentHeader() && commentNumber == 1){
+ return startNode;
+ }else if(startNode.isDescription() && commentNumber == 0){
+ return startNode;
+ }
+
+ BugzillaOutlineNode[] children = startNode.getChildren();
+ for(int i = 0; i < children.length; i++){
+ BugzillaOutlineNode n = findNode(children[i], commentNumber);
+ if(n != null)
+ return n;
+ }
+ return null;
+ }
+
+ public String getParentHandle(String handle) {
+
+ //check so that we don't need to try to get the parent if we are already at the bug report
+ if(!handle.matches(".*;.*;.*"))
+ return null;
+
+ BugzillaOutlineNode bon = (BugzillaOutlineNode)getObjectForHandle(handle);
+ if(bon != null && bon.getParent() != null)
+ return BugzillaTools.getHandle(bon.getParent());
+ else
+ return null;
+// String [] parts = handle.split(";");
+// if (parts.length == 1){
+// return null;
+// }else if (parts.length > 2) {
+// String newHandle = "";
+// for(int i = 0; i < parts.length - 1; i++)
+// newHandle += parts[i] + ";";
+// return newHandle.substring(0, newHandle.length() - 1);
+//// return handle.substring(0, handle.lastIndexOf(";"));
+// }
+// return null;
+ }
+
+ public String getName(Object object) {
+ if(object instanceof BugzillaOutlineNode){
+ BugzillaOutlineNode b = (BugzillaOutlineNode)object;
+ return BugzillaTools.getName(b);
+ } else if (object instanceof BugzillaReportNode){
+ BugzillaSearchHit hit = ((BugzillaReportNode)object).getHit();
+ return hit.getServer() + ": Bug#: " + hit.getId() + ": " + hit.getDescription();
+ }
+ return "";
+ }
+
+ public boolean canBeLandmark(Object element) {
+ return false;
+ }
+
+ public boolean acceptsObject(Object object) {
+ return object instanceof BugzillaOutlineNode || object instanceof BugzillaReportSelection;
+ }
+
+ public boolean canFilter(Object element) {
+ return true;
+ }
+
+ public boolean isDocument(String handle) {
+ return (handle.indexOf(';') == handle.lastIndexOf(';') && handle.indexOf(";") != -1);
+ }
+
+ public String getHandleForMarker(ProblemMarker marker) {
+ return null;
+ }
+
+ public IProject getProjectForObject(Object object) {
+ // bugzilla objects do not yet sit in a project
+ return null;
+ }
+
+ public String getResourceExtension(String elementHandle) {
+ return getResourceExtension();
+ }
+
+ /*
+ *
+ * STUFF FOR CACHING BUG REPORTS
+ *
+ */
+
+ // bug report cache
+ private Map<String, BugReport> cache = new HashMap<String, BugReport>();
+
+ public void cache(String handle, BugReport report) {
+ cache.put(handle, report);
+ cacheFile.add(report);
+ }
+
+ public void clearCache(){
+ cache.clear();
+ cacheFile.removeAll();
+ }
+
+ private BugReport getFromCache(String bugHandle) {
+ return cache.get(bugHandle);
+ }
+
+ public Set<String> getCachedHandles(){
+ return cache.keySet();
+ }
+
+ private BugzillaCacheFile cacheFile;
+
+ private IPath getCacheFile() {
+ IPath stateLocation = Platform.getPluginStateLocation(MylarBugzillaPlugin.getDefault());
+ IPath configFile = stateLocation.append("offlineReports");
+ return configFile;
+ }
+
+ private void readCacheFile() {
+ IPath cachPath = getCacheFile();
+
+ try {
+ cacheFile = new BugzillaCacheFile(cachPath.toFile());
+ ArrayList<IBugzillaBug> cached = cacheFile.elements();
+ for(IBugzillaBug bug: cached){
+ if(bug instanceof BugReport)
+ cache.put(BugzillaTools.getHandle(bug), (BugReport)bug);
+ }
+ } catch (Exception e) {
+ MylarPlugin.log(e, "occurred while restoring saved offline Bugzilla reports.");
+ }
+ }
+
+ public BugReport getCached(String handle) {
+ return cache.get(handle);
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaUiBridge.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaUiBridge.java
new file mode 100644
index 000000000..9a340df45
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/BugzillaUiBridge.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Apr 6, 2005
+ */
+package org.eclipse.mylar.bugzilla;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.mylar.bugzilla.ui.BugzillaOpenStructure;
+import org.eclipse.mylar.bugzilla.ui.ViewBugzillaAction;
+import org.eclipse.mylar.bugzilla.ui.editor.AbstractBugEditor;
+import org.eclipse.mylar.bugzilla.ui.outline.BugzillaOutlinePage;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaTask;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaTaskEditor;
+import org.eclipse.mylar.core.model.ITaskscapeNode;
+import org.eclipse.mylar.tasks.ITask;
+import org.eclipse.mylar.tasks.MylarTasksPlugin;
+import org.eclipse.mylar.tasks.search.BugzillaReferencesProvider;
+import org.eclipse.mylar.ui.IMylarUiBridge;
+import org.eclipse.mylar.ui.MylarImages;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.Workbench;
+
+public class BugzillaUiBridge implements IMylarUiBridge {
+
+ protected BugzillaNodeLabelProvider labelProvider = new BugzillaNodeLabelProvider();
+
+ public void open(ITaskscapeNode node) {
+ String handle = node.getElementHandle();
+ String bugHandle = handle;
+ String server =handle.substring(0, handle.indexOf(";"));
+
+ handle = handle.substring(handle.indexOf(";") + 1);
+ int next = handle.indexOf(";");
+
+ int bugId;
+ int commentNumer = -1;
+ if(next == -1){
+ bugId = Integer.parseInt(handle);
+ }
+ else{
+ bugId = Integer.parseInt(handle.substring(0, handle.indexOf(";")));
+ commentNumer = Integer.parseInt(handle.substring(handle.indexOf(";") + 1));
+ bugHandle = bugHandle.substring(0, next);
+ }
+
+ List<BugzillaOpenStructure> l = new ArrayList<BugzillaOpenStructure>(1);
+ l.add(new BugzillaOpenStructure(server, bugId, commentNumer));
+
+ ITask task= MylarTasksPlugin.getTaskListManager().getTaskList().getTaskForId(bugHandle);
+ if (task != null && task instanceof BugzillaTask) {
+ BugzillaTask bugzillaTask = (BugzillaTask)task;
+ bugzillaTask.openTask(commentNumer);
+ } else {
+ // open the bug in the editor
+ ViewBugzillaAction viewBugs = new ViewBugzillaAction("Display bugs in editor", l);
+ viewBugs.schedule();
+ }
+ }
+
+ public ILabelProvider getLabelProvider() {
+ return labelProvider;
+ }
+
+ public void close(ITaskscapeNode node) {
+ IWorkbenchPage page = Workbench.getInstance().getActiveWorkbenchWindow().getActivePage();
+ if (page != null) {
+ IEditorReference[] references = page.getEditorReferences();
+ for (int i = 0; i < references.length; i++) {
+ IEditorPart part = references[i].getEditor(false);
+ if (part != null) {
+ if (part instanceof AbstractBugEditor) {
+ ((AbstractBugEditor)part).close();
+ } else if(part instanceof BugzillaTaskEditor){
+ ((BugzillaTaskEditor)part).close();
+ }
+ }
+ }
+ }
+ }
+
+ public boolean acceptsEditor(IEditorPart editorPart) {
+ return editorPart instanceof AbstractBugEditor;
+ }
+
+ public List<TreeViewer> getTreeViewers(IEditorPart editor) {
+ ArrayList<TreeViewer> outlines = new ArrayList<TreeViewer>(1);
+ TreeViewer outline = getOutlineTreeViewer(editor);
+ if (outline != null) {
+ outlines.add(outline);
+ return outlines;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ protected TreeViewer getOutlineTreeViewer(IEditorPart editor) {
+ if(editor instanceof AbstractBugEditor){
+ AbstractBugEditor abe = (AbstractBugEditor)editor;
+ BugzillaOutlinePage outline = abe.getOutline();
+ if(outline != null) return outline.getOutlineTreeViewer();
+ }
+ return null;
+ }
+
+ public void refreshOutline(Object element, boolean updateLabels) {
+ IEditorPart editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+ TreeViewer treeViewer = getOutlineTreeViewer(editorPart);
+ if (treeViewer != null) {
+ treeViewer.refresh(true);
+
+ treeViewer.expandAll();
+ }
+ }
+
+ public ImageDescriptor getIconForRelationship(String relationshipHandle) {
+ return MylarImages.EDGE_REF_BUGZILLA;
+
+ }
+
+ public String getNameForRelationship(String relationshipHandle) {
+ return BugzillaReferencesProvider.NAME;
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/MylarBugzillaPlugin.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/MylarBugzillaPlugin.java
new file mode 100644
index 000000000..6bcf64076
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/bugzilla/MylarBugzillaPlugin.java
@@ -0,0 +1,100 @@
+package org.eclipse.mylar.bugzilla;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.mylar.core.MylarPlugin;
+import org.eclipse.mylar.tasks.search.BugzillaReferencesProvider;
+import org.eclipse.mylar.ui.MylarUiPlugin;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.Workbench;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class MylarBugzillaPlugin extends AbstractUIPlugin implements IStartup {
+
+ private static BugzillaMylarBridge bridge = null;
+ private static BugzillaReferencesProvider referencesProvider = new BugzillaReferencesProvider();
+ private BugzillaStructureBridge structureBridge;
+
+ private static MylarBugzillaPlugin plugin;
+
+ public MylarBugzillaPlugin() {
+ plugin = this;
+ }
+
+ public void earlyStartup() {
+ final IWorkbench workbench = PlatformUI.getWorkbench();
+ workbench.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ structureBridge = new BugzillaStructureBridge();
+
+ MylarPlugin.getDefault().addBridge(structureBridge);
+ MylarPlugin.getTaskscapeManager().addListener(referencesProvider);
+ MylarUiPlugin.getDefault().addAdapter(BugzillaStructureBridge.EXTENSION, new BugzillaUiBridge());
+ MylarPlugin.getDefault().getSelectionMonitors().add(new BugzillaEditingMonitor());
+
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ if (window != null) {
+ // create a new bridge and initialize it
+ bridge = new BugzillaMylarBridge();
+ }
+ }
+ });
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static MylarBugzillaPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given
+ * plug-in relative path.
+ *
+ * @param path the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.mylar.bugzilla.bridge", path);
+ }
+
+ public static BugzillaMylarBridge getBridge() {
+ // make sure that the bridge initialized, if not, make a new one
+ if (bridge == null) {
+ bridge = new BugzillaMylarBridge();
+ }
+ return bridge;
+ }
+
+
+ public BugzillaStructureBridge getStructureBridge() {
+ return structureBridge;
+ }
+
+ public static BugzillaReferencesProvider getReferenceProvider() {
+ return referencesProvider;
+
+ }
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearch.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearch.java
new file mode 100644
index 000000000..0abfd8126
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearch.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Oct 13, 2004
+ */
+package org.eclipse.mylar.tasks.search;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+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.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.mylar.bugzilla.BugzillaMylarBridge;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+import org.eclipse.mylar.core.model.InterestComparator;
+import org.eclipse.mylar.core.search.IActiveSearchListener;
+import org.eclipse.mylar.core.search.IMylarSearchOperation;
+
+
+/**
+ * Used to facilitate bugzilla searches based on IJavaElements
+ *
+ * @author Shawn Minto
+ */
+public class BugzillaMylarSearch implements IMylarSearchOperation {
+
+ // scope identifiers
+ public static final int LOCAL_QUAL = 1; // local implies a bugzilla task, not just an offline report
+ public static final int LOCAL_UNQUAL = 2;
+ public static final int FULLY_QUAL = 3;
+ public static final int UNQUAL = 4;
+
+ private int scope;
+
+ private IJavaElement element;
+
+ private String handle = "";
+
+ /**
+ * Constructor
+ * @param scope The scope of this search
+ */
+ public BugzillaMylarSearch(int scope, IJavaElement element) {
+ this.scope = scope;
+ this.element = element;
+ }
+
+ public IStatus run(IProgressMonitor monitor) {
+ handle = element.getHandleIdentifier() + " " + scope;
+ List<IJavaElement> landmarks = new ArrayList<IJavaElement>();
+ landmarks.add(element);
+
+ if (!BugzillaMylarBridge.doesJobExist(handle)) {
+
+ // perform the bugzilla search
+ // get only the useful landmarks (IMember)
+ List<IMember> members = getMemberLandmarks(landmarks);
+
+ // go through all of the landmarks that we are given and perform a
+ // search on them
+ for(IMember m : members){
+
+ // FIXME: decide whether to do leave the caching of searches in for now or not
+ // check if we have the info cached
+// List<BugzillaReportNode> landmarkDoi = MylarTasksPlugin.getBridge()
+// .getFromLandmarksHash(m, scope);
+
+// if (landmarkDoi != null) {
+// //TODO decide when to queue up and do a refresh search
+// notifySearchCompleted(landmarkDoi);
+// continue;
+// }
+
+ // create a search operation so that we can search
+ BugzillaMylarSearchOperation op = new BugzillaMylarSearchOperation(
+ this, m, scope);
+
+ // create a new search job so that it can be scheduled and
+ // run as a background thread
+ Job searchJob = new BugzillaMylarSearchJob(
+ "Querying Bugzilla Server - Mylar - "
+ + op.getSearchMemberName(), op);
+
+ // schedule the new search job
+ searchJob.schedule();
+
+ // save this searchJobs handle so that we can cancel it if need be
+ BugzillaMylarBridge.addJob(handle, searchJob);
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ /** List of listeners wanting to know about the searches */
+ private List<IActiveSearchListener> listeners = new ArrayList<IActiveSearchListener>();
+
+ /**
+ * Add a listener for when the bugzilla search is completed
+ *
+ * @param l
+ * The listener to add
+ */
+ public void addListener(IActiveSearchListener l) {
+ // add the listener to the list
+ listeners.add(l);
+ }
+
+ /**
+ * Remove a listener for when the bugzilla search is completed
+ *
+ * @param l
+ * The listener to remove
+ */
+ public void removeListener(IActiveSearchListener l) {
+ // remove the listener from the list
+ listeners.remove(l);
+ }
+
+ /**
+ * Notify all of the listeners that the bugzilla search is completed
+ *
+ * @param doiList
+ * A list of BugzillaSearchHitDoiInfo
+ * @param member
+ * The IMember that the search was performed on
+ */
+ public void notifySearchCompleted(List<BugzillaReportNode> doiList) {
+ // go through all of the listeners and call searchCompleted(colelctor,
+ // member)
+ BugzillaMylarBridge.removeSearchJob(handle);
+ for (IActiveSearchListener listener : listeners) {
+ listener.searchCompleted(doiList);
+ }
+ }
+
+ /**
+ * Get only the landmarks that are IMember and sort them according to their
+ * DOI value (highest to lowest)
+ *
+ * @param landmarks
+ * The landmarks to check
+ * @return List of IMember landmarks sorted by DOI value
+ */
+ public static List<IMember> getMemberLandmarks(List<IJavaElement> landmarks) {
+ List<IMember> memberLandmarks = new ArrayList<IMember>();
+
+ for(IJavaElement je : landmarks) {
+
+ // keep only the IMember landmarks
+ if (je instanceof IMember) {
+ memberLandmarks.add((IMember)je);
+ }
+ }
+
+ // sort the landmarks
+ Collections.sort(memberLandmarks, new InterestComparator<IMember>());
+
+ return memberLandmarks;
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchJob.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchJob.java
new file mode 100644
index 000000000..b596f5536
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchJob.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Oct 6, 2004
+ */
+package org.eclipse.mylar.tasks.search;
+
+import javax.security.auth.login.LoginException;
+
+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.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.mylar.bugzilla.BugzillaMylarBridge;
+import org.eclipse.mylar.bugzilla.core.BugzillaPlugin;
+import org.eclipse.mylar.bugzilla.core.IBugzillaConstants;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * The bugzilla search job used to search a bugzilla site
+ *
+ * @author Shawn Minto
+ */
+public class BugzillaMylarSearchJob extends Job {
+
+ /** The search operation used to perform the query */
+ private BugzillaMylarSearchOperation operation;
+
+ /**
+ * Constructor
+ *
+ * @param name
+ * Job name
+ * @param operation
+ * The operation to perform the search query
+ */
+ public BugzillaMylarSearchJob(String name,
+ BugzillaMylarSearchOperation operation) {
+ super(name);
+ this.operation = operation;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ // create a new status
+ final IStatus[] status = new IStatus[1];
+
+ try {
+ // execute the search operation
+ operation.execute(monitor);
+
+ // get the status of the search operation
+ status[0] = operation.getStatus();
+
+ // determine if there was an error, if it was cancelled, or if it is
+ // ok
+ if ( status[0].getCode() == IStatus.CANCEL) {
+ // it was cancelled, so just return
+ status[0] = Status.OK_STATUS;
+
+ // make sure that we know this job is not running anymore
+ BugzillaMylarBridge.removeSearchJob(operation.getSearchMember().getHandleIdentifier()+" "+operation.getScope());//runningJobs.remove(operation.getSearchMember());
+ return status[0];
+ } else if (!status[0].isOK()) {
+ // there was an error, so display an error message
+ PlatformUI.getWorkbench().getDisplay().asyncExec(
+ new Runnable() {
+ public void run() {
+ ErrorDialog.openError(null,
+ "Bugzilla Search Error", null,
+ status[0]);
+ }
+ });
+ status[0] = Status.OK_STATUS;
+
+ // make sure we know that this job is not running anymore
+ BugzillaMylarBridge.removeSearchJob(operation.getSearchMember().getHandleIdentifier()+" "+operation.getScope());//runningJobs.remove(operation.getSearchMember());
+ return status[0];
+ }
+ } catch (LoginException e) {
+ // we had a problem while searching that seems like a login info
+ // problem
+ // thrown in BugzillaSearchOperation
+ MessageDialog
+ .openError(
+ null,
+ "Login Error",
+ "Bugzilla could not log you in to get the information you requested since login name or password is incorrect.\nPlease check your settings in the bugzilla preferences. ");
+ BugzillaPlugin.log(new Status(IStatus.ERROR,
+ IBugzillaConstants.PLUGIN_ID, IStatus.OK, "", e));
+ } finally {
+ // make sure that we know that this job is not running anymore
+ BugzillaMylarBridge.removeSearchJob(operation.getSearchMember().getHandleIdentifier()+" "+operation.getScope());//.runningJobs.remove(operation.getSearchMember());
+ }
+
+ return status[0];
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchOperation.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchOperation.java
new file mode 100644
index 000000000..d679c8bdd
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaMylarSearchOperation.java
@@ -0,0 +1,526 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Oct 14, 2004
+ */
+package org.eclipse.mylar.tasks.search;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.security.auth.login.LoginException;
+
+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.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.mylar.bugzilla.MylarBugzillaPlugin;
+import org.eclipse.mylar.bugzilla.core.BugReport;
+import org.eclipse.mylar.bugzilla.core.Comment;
+import org.eclipse.mylar.bugzilla.core.search.BugzillaSearchEngine;
+import org.eclipse.mylar.bugzilla.core.search.BugzillaSearchHit;
+import org.eclipse.mylar.bugzilla.core.search.BugzillaSearchQuery;
+import org.eclipse.mylar.bugzilla.core.search.IBugzillaSearchOperation;
+import org.eclipse.mylar.bugzilla.ui.search.BugzillaResultCollector;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaTask;
+import org.eclipse.mylar.bugzilla.ui.tasks.StackTrace;
+import org.eclipse.mylar.core.MylarPlugin;
+import org.eclipse.mylar.tasks.ITask;
+import org.eclipse.mylar.tasks.MylarTasksPlugin;
+import org.eclipse.mylar.tasks.TaskCategory;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+
+
+/**
+ * Bugzilla search operation for Mylar
+ *
+ * @author Shawn Minto
+ */
+public class BugzillaMylarSearchOperation extends WorkspaceModifyOperation
+ implements IBugzillaSearchOperation {
+ /** The IMember we are doing the search for */
+ private IMember javaElement;
+
+ /** The bugzilla collector for the search */
+ private BugzillaResultCollector collector = null;
+
+ /** The status of the search operation */
+ private IStatus status;
+
+ /** The LoginException that was thrown when trying to do the search */
+ private LoginException loginException = null;
+
+ /** The fully qualified name of the member we are searching for */
+ private String name;
+
+ /** The bugzilla search query */
+ private BugzillaSearchQuery query;
+
+ private BugzillaMylarSearch search;
+
+ private int scope;
+
+ /**
+ * Constructor
+ *
+ * @param m
+ * The member that we are doing the search for
+ */
+ public BugzillaMylarSearchOperation(BugzillaMylarSearch search, IMember m, int scope) {
+ this.javaElement = m;
+ this.search = search;
+ this.scope = scope;
+ name = getFullyQualifiedName(m);
+ }
+
+ /**
+ * Get the fully qualified name of a IMember
+ * TODO: move to a more central location so that others can use this, but don't want to add unecessary coupling
+ *
+ * @return String representing the fully qualified name
+ */
+ public static String getFullyQualifiedName(IJavaElement je) {
+ if(!(je instanceof IMember)) return null;
+
+ IMember m = (IMember)je;
+ if (m.getDeclaringType() == null)
+ return ((IType) m).getFullyQualifiedName();
+ else
+ return m.getDeclaringType().getFullyQualifiedName() + "."
+ + m.getElementName();
+ }
+
+ @Override
+ public void execute(IProgressMonitor monitor) {
+
+ BugzillaResultCollector searchCollector = null;
+
+ if(scope == BugzillaMylarSearch.FULLY_QUAL){
+ searchCollector = searchQualified(monitor);
+ }else if(scope == BugzillaMylarSearch.UNQUAL){
+ searchCollector = searchUnqualified(monitor);
+ }else if(scope == BugzillaMylarSearch.LOCAL_QUAL){
+ searchCollector = searchLocalQual(monitor);
+ }else if(scope == BugzillaMylarSearch.LOCAL_UNQUAL){
+ searchCollector = searchLocalUnQual(monitor);
+ }else{
+ return;
+ }
+
+ if(searchCollector == null){
+ search.notifySearchCompleted(
+ new ArrayList<BugzillaReportNode>());
+ return;
+ }
+
+ List<BugzillaSearchHit> l = searchCollector.getResults();
+
+ // get the list of doi elements
+ List<BugzillaReportNode> doiList = getDoiList(l);
+
+ // we completed the search, so notify all of the listeners
+ // that the search has been completed
+ MylarBugzillaPlugin.getBridge().addToLandmarksHash(doiList, javaElement, scope);
+ search.notifySearchCompleted(
+ doiList);
+ // MIK: commmented out logging
+// MonitorPlugin.log(this, "There were " + doiList.size() + " items found");
+ }
+
+ /**
+ * Search the local bugs for the member using the qualified name
+ * @param monitor The progress monitor to search with
+ * @return The BugzillaResultCollector with the results of the search
+ */
+ private BugzillaResultCollector searchLocalQual(IProgressMonitor monitor) {
+
+ //get the fully qualified name for searching
+ String elementName = getFullyQualifiedName(javaElement);
+
+ // setup the search result collector
+ collector = new BugzillaResultCollector();
+ collector.setOperation(this);
+ collector.setProgressMonitor(monitor);
+
+ // get all of the root tasks and start the search
+ List<ITask> tasks = MylarTasksPlugin.getTaskListManager().getTaskList().getRootTasks();
+ searchLocal(tasks, collector, elementName, monitor);
+ for (TaskCategory cat : MylarTasksPlugin.getTaskListManager().getTaskList().getTaskCategories()) {
+ searchLocal(cat.getChildren(), collector, elementName, monitor);
+ }
+
+ // return the collector
+ return collector;
+ }
+
+ /**
+ * Search the local bugs for the member using the unqualified name
+ * @param monitor The progress monitor to search with
+ * @return The BugzillaResultCollector with the results of the search
+ */
+ private BugzillaResultCollector searchLocalUnQual(IProgressMonitor monitor) {
+
+ // get the element name for searching
+ String elementName = javaElement.getElementName();
+
+ // setup the search result collector
+ collector = new BugzillaResultCollector();
+ collector.setOperation(this);
+ collector.setProgressMonitor(monitor);
+
+ // get all of the root tasks and start the search
+ List<ITask> tasks = MylarTasksPlugin.getTaskListManager().getTaskList().getRootTasks();
+ searchLocal(tasks, collector, elementName, monitor);
+ for (TaskCategory cat : MylarTasksPlugin.getTaskListManager().getTaskList().getTaskCategories()) {
+ searchLocal(cat.getChildren(), collector, elementName, monitor);
+ }
+ // return the collector
+ return collector;
+ }
+
+ /**
+ * Search the local bugs for the member
+ * @param tasks The tasks to search
+ * @param searchCollector The collector to add the results to
+ * @param elementName The name of the element that we are looking for
+ * @param monitor The progress monitor
+ */
+ private void searchLocal(List<ITask> tasks, BugzillaResultCollector searchCollector, String elementName, IProgressMonitor monitor) {
+ if(tasks == null) return;
+
+ // go through all of the tasks
+ for(ITask task : tasks){
+ monitor.worked(1);
+
+ // check what kind of task it is
+ if(task instanceof BugzillaTask){
+
+ // we have a bugzilla task, so get the bug report
+ BugzillaTask bugTask = (BugzillaTask)task;
+ BugReport bug = bugTask.getBugReport();
+
+ // parse the bug report for the element that we are searching for
+ boolean isHit = search(elementName, bug);
+
+ // determine if we have a hit or not
+ if(isHit){
+
+ // make a search hit from the bug and then add it to the collector
+ BugzillaSearchHit hit = new BugzillaSearchHit(bug.getId(), bug.getDescription(), "","","","","","","", bug.getServer());
+ try{
+ searchCollector.accept(hit);
+ }catch(CoreException e){
+ MylarPlugin.log(e, "bug search failed");
+ }
+ }
+ }
+ }
+ status = Status.OK_STATUS;
+ }
+
+ /**
+ * Search the bug for the given element name
+ * @param elementName The name of the element to search for
+ * @param bug The bug to search in
+ */
+ private boolean search(String elementName, BugReport bug) {
+
+ if (bug == null) return false; // MIK: added null check here
+ String description = bug.getDescription();
+ String summary = bug.getSummary();
+ List<Comment> comments = bug.getComments();
+
+ // search the description and the summary
+ if(Util.hasElementName(elementName, summary))
+ return true;
+
+ if(Util.hasElementName(elementName, description))
+ return true;
+
+ Iterator<Comment> comItr = comments.iterator();
+ while (comItr.hasNext()) {
+ Comment comment = comItr.next();
+ String commentText = comment.getText();
+ // search the text for a reference to the element
+ if(Util.hasElementName(elementName, commentText))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Perform the actual search on the Bugzilla server
+ * @param url The url to use for the search
+ * @param searchCollector The collector to put the search results into
+ * @param monitor The progress monitor to use for the search
+ * @return The BugzillaResultCollector with the search results
+ */
+ private BugzillaResultCollector search(String url, BugzillaResultCollector searchCollector, IProgressMonitor monitor){
+
+ // set the initial number of matches to 0
+ int matches = 0;
+ // setup the progress monitor and start the search
+ searchCollector.setProgressMonitor(monitor);
+ BugzillaSearchEngine engine = new BugzillaSearchEngine(url);
+ try {
+
+ // perform the search
+ status = engine.search(searchCollector, matches);
+
+ // check the status so that we don't keep searching if there
+ // is a problem
+ if (status.getCode() == IStatus.CANCEL) {
+ MylarPlugin.log("search cancelled", this);
+ return null;
+ } else if (!status.isOK()) {
+ MylarPlugin.log("search error", this);
+ MylarPlugin.log(status);
+ return null;
+ }
+ return searchCollector;
+ } catch (LoginException e) {
+ //save this exception to throw later
+ this.loginException = e;
+ }
+ return null;
+ }
+
+ /**
+ * Perform a search for qualified instances of the member
+ * @param monitor The progress monitor to use
+ * @return The BugzillaResultCollector with the search results
+ */
+ private BugzillaResultCollector searchQualified(IProgressMonitor monitor)
+ {
+ // create a new collector for the results
+ collector = new BugzillaResultCollector();
+ collector.setOperation(this);
+ collector.setProgressMonitor(monitor);
+
+ // get the search url
+ String url = Util.getExactSearchURL(javaElement);
+
+ // log the url that we are searching with
+ // MIK: commmented out logging
+// MonitorPlugin.log(this, url);
+
+ return search(url, collector, monitor);
+ }
+
+ /**
+ * Perform a search for unqualified instances of the member
+ * @param monitor The progress monitor to use
+ * @return The BugzillaResultCollector with the search results
+ */
+ private BugzillaResultCollector searchUnqualified(IProgressMonitor monitor)
+ {
+ // create a new collector for the results
+ collector = new BugzillaResultCollector();
+ collector.setOperation(this);
+ collector.setProgressMonitor(monitor);
+
+ // get the search url
+ String url = Util.getInexactSearchURL(javaElement);
+
+ // log the url that we are searching with
+ // MIK: commmented out logging
+// MonitorPlugin.log(this, url);
+
+ return search(url, collector, monitor);
+ }
+
+// /**
+// * Remove all of the duplicates
+// * @param compare The List of BugzillaSearchHits to compare with
+// * @param base The List of BugzillaSearchHits to remove the duplicates from
+// */
+// private void removeDuplicates(List<BugzillaSearchHit> compare, List<BugzillaSearchHit> base){
+//
+// for(BugzillaSearchHit h1 : compare){
+// Iterator itr2 = base.iterator();
+// while(itr2.hasNext()){
+// BugzillaSearchHit h2 = (BugzillaSearchHit)itr2.next();
+// if(h2.getId() == h1.getId()){
+// // we found a duplicate so remove it
+// itr2.remove();
+// break;
+// }
+// }
+// }
+// }
+//
+ /**
+ * Perform a second pass parse to determine if there are any stack traces in
+ * the bug - currently only used for the exact search results
+ *
+ * @param doiList -
+ * the list of BugzillaSearchHitDOI elements to parse
+ */
+ public static void secondPassBugzillaParser(List<BugzillaReportNode> doiList) {
+
+ // go through each of the items in the doiList
+ for(BugzillaReportNode info : doiList) {
+
+ // get the bug report so that we have all of the data
+ // - descriptions, comments, etc
+ BugReport b = null;
+ try{
+ b = info.getBug();
+ }catch(Exception e){
+ // don't care since null will be caught
+ }
+
+ // if the report could not be downloaded, try the next one
+ if (b == null)
+ continue;
+
+ // see if the description has a stack trace in it
+ StackTrace[] stackTrace = StackTrace.getStackTrace(b.getDescription(), b.getDescription());
+ if (stackTrace != null) {
+
+ // add the stack trace to the doi info
+ info.setExact(true);
+ info.addStackTraces(stackTrace);
+ }
+
+ // go through all of the comments for the bug
+ Iterator<Comment> comItr = b.getComments().iterator();
+ while (comItr.hasNext()) {
+ Comment comment = comItr.next();
+ String commentText = comment.getText();
+
+ // see if the comment has a stack trace in it
+ stackTrace = StackTrace.getStackTrace(commentText, comment);
+ if (stackTrace != null) {
+
+ // add the stack trace to the doi info
+ info.setExact(true);
+ info.addStackTraces(stackTrace);
+ }
+ }
+ }
+ }
+
+ /**
+ * Add the results returned to the Hash of landmarks
+ *
+ * @param results
+ * The list of results
+ * @param isExact
+ * whether the search was exact or not
+ */
+ private List<BugzillaReportNode> getDoiList(List<BugzillaSearchHit> results) {
+ List<BugzillaReportNode> doiList = new ArrayList<BugzillaReportNode>();
+
+ boolean isExact = (scope==BugzillaMylarSearch.FULLY_QUAL || scope==BugzillaMylarSearch.LOCAL_QUAL)?true:false;
+
+ BugzillaReportNode info = null;
+ // go through all of the results and create a DoiInfo list
+ for(BugzillaSearchHit hit : results){
+
+ try {
+ float value = 0;
+ info = new BugzillaReportNode(
+ value, hit, isExact);
+
+ // only download the bug for the exact matches
+ //downloading bugs kills the time - can we do this elsewhere? - different thread? persistant?
+// if(isExact){
+// // get the bug report for the doi info item
+// BugReport b = BugzillaRepository.getInstance().getBug(
+// hit.getId());
+// // add the bug to the doi info for future use
+// info.setBug(b);
+// }
+
+ } catch (Exception e) {
+ MylarPlugin.log(e, "search failed");
+ }
+ finally{
+ doiList.add(info);
+ }
+ }
+ return doiList;
+ }
+
+ /**
+ * @see org.eclipse.mylar.bugzilla.core.search.IBugzillaSearchOperation#getStatus()
+ */
+ public IStatus getStatus() throws LoginException {
+ // if a LoginException was thrown while trying to search, throw this
+ if (loginException == null)
+ return status;
+ else
+ throw loginException;
+ }
+
+ /**
+ * @see org.eclipse.mylar.bugzilla.core.search.IBugzillaSearchOperation#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ /**
+ * Get the member that we are performing the search for
+ *
+ * @return The member this search is being performed for
+ */
+ public IMember getSearchMember() {
+ return javaElement;
+ }
+
+ /**
+ * Get the name of the member that we are searching for
+ *
+ * @return The fully qualified name of the member
+ */
+ public String getSearchMemberName() {
+ return name;
+ }
+
+ /**
+ * @see org.eclipse.mylar.bugzilla.core.search.IBugzillaSearchOperation#getQuery()
+ */
+ public BugzillaSearchQuery getQuery() {
+ return query;
+ }
+
+ /**
+ * @see org.eclipse.mylar.bugzilla.core.search.IBugzillaSearchOperation#setQuery(org.eclipse.mylar.bugzilla.core.search.BugzillaSearchQuery)
+ */
+ public void setQuery(BugzillaSearchQuery newQuery) {
+ this.query = newQuery;
+ }
+
+ /**
+ * Get the name of the element that we are searching for
+ *
+ * @return The name of the element
+ */
+ public String getName(){
+ return name;
+ }
+
+ /**
+ * Get the scope of the search operation
+ * @return The scope - defined in BugzillaMylarSearch
+ */
+ public int getScope() {
+ return scope;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaReferencesProvider.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaReferencesProvider.java
new file mode 100644
index 000000000..7212b8995
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/BugzillaReferencesProvider.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Feb 2, 2005
+ */
+package org.eclipse.mylar.tasks.search;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.mylar.bugzilla.BugzillaStructureBridge;
+import org.eclipse.mylar.bugzilla.MylarBugzillaPlugin;
+import org.eclipse.mylar.bugzilla.ui.tasks.BugzillaReportNode;
+import org.eclipse.mylar.core.model.ITaskscapeNode;
+import org.eclipse.mylar.core.search.IActiveSearchListener;
+import org.eclipse.mylar.core.search.IMylarSearchOperation;
+import org.eclipse.mylar.core.search.RelationshipProvider;
+
+
+/**
+ * @author Shawn Minto
+ */
+public class BugzillaReferencesProvider extends RelationshipProvider {
+
+ public static final String ID = "org.eclipse.mylar.bugzilla.search.references";
+ public static final String NAME = "Bugilla report references";
+
+ public BugzillaReferencesProvider() {
+ super(BugzillaStructureBridge.EXTENSION, ID);
+ }
+
+ protected boolean acceptElement(IJavaElement javaElement) {
+ return javaElement != null
+ && (javaElement instanceof IMember || javaElement instanceof IType);
+ }
+
+ /**
+ * HACK: checking kind as string - don't want the dependancy to mylar.java
+ */
+ @Override
+ protected void findRelated(final ITaskscapeNode node, int degreeOfSeparation) {
+ if (!node.getStructureKind().equals("java")) return;
+ IJavaElement javaElement = JavaCore.create(node.getElementHandle());
+ if (!acceptElement(javaElement)) {
+ return;
+ }
+ runJob(node, degreeOfSeparation);
+
+ //XXX what if degreeOfSeparation is 5?
+ }
+
+ @Override
+ public IMylarSearchOperation getSearchOperation(ITaskscapeNode node, int limitTo, int degreeOfSepatation) {
+ IJavaElement javaElement = JavaCore.create(node.getElementHandle());
+ return new BugzillaMylarSearch(degreeOfSepatation, javaElement);
+ }
+
+ private void runJob(final ITaskscapeNode node, final int degreeOfSeparation) {
+ BugzillaMylarSearch search = (BugzillaMylarSearch)getSearchOperation(node, 0, degreeOfSeparation);
+
+ search.addListener(new IActiveSearchListener(){
+
+ private boolean gathered = false;
+
+ public void searchCompleted(List<?> nodes) {
+ Iterator<?> itr = nodes.iterator();
+
+ BugzillaStructureBridge bridge = MylarBugzillaPlugin.getDefault().getStructureBridge();
+
+ while(itr.hasNext()) {
+ Object o = itr.next();
+ if(o instanceof BugzillaReportNode){
+ BugzillaReportNode bugzillaNode = (BugzillaReportNode)o;
+ String handle = bugzillaNode.getElementHandle();
+ if(bridge.getCached(handle) == null)
+ cache(handle, bugzillaNode);
+ incrementInterest(degreeOfSeparation, BugzillaStructureBridge.EXTENSION, handle);
+ }
+ }
+ gathered = true;
+ }
+
+ public boolean resultsGathered() {
+ return gathered;
+ }
+
+ });
+ search.run(new NullProgressMonitor());
+ }
+
+ @Override
+ protected String getSourceId() {
+ return ID;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ /*
+ *
+ * STUFF FOR TEMPORARILY CACHING A PROXY REPORT
+ *
+ * TODO remove the proxys and update the BugzillaStructureBridge cache so that on restart,
+ * we dont have to get all of the bugs
+ *
+ */
+ private static final Map<String, BugzillaReportNode> reports = new HashMap<String, BugzillaReportNode>();
+
+ public BugzillaReportNode getCached(String handle){
+ return reports.get(handle);
+ }
+
+ protected void cache(String handle, BugzillaReportNode bugzillaNode) {
+ reports.put(handle, bugzillaNode);
+ }
+
+ public void clearCachedReports(){
+ reports.clear();
+ }
+
+ public Collection<? extends String> getCachedHandles() {
+ return reports.keySet();
+ }
+
+}
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/Util.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/Util.java
new file mode 100644
index 000000000..d883e90ea
--- /dev/null
+++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/search/Util.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2004 - 2005 University Of British Columbia 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:
+ * University Of British Columbia - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Nov 19, 2004
+ */
+package org.eclipse.mylar.tasks.search;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.mylar.bugzilla.core.BugzillaPlugin;
+import org.eclipse.mylar.bugzilla.core.BugzillaPreferences;
+import org.eclipse.mylar.bugzilla.core.IBugzillaConstants;
+
+
+/**
+ * Utilities methods for the BugzillaMylarBridge
+ *
+ * @author Shawn Minto
+ */
+public class Util {
+
+ /**
+ * List of all of the search operations that can be done <br> all words, any words, regex
+ */
+ private static final String[] patternOperationValues = { "allwordssubstr", "anywordssubstr", "regexp" };
+ /**
+ * Sugzilla preferences so that we can get the search params
+ */
+ private static IPreferenceStore prefs = BugzillaPlugin.getDefault().getPreferenceStore();
+ /**
+ * List of all of the resolutions that we can have <br> FIXED, INVALID, WONTFIX, LATER, REMIND, DUPLICATE, WORKSFORME, MOVED, ---
+ */
+ private static String[] resolutionValues = BugzillaPreferences.queryOptionsToArray(prefs.getString(IBugzillaConstants.RESOLUTION_VALUES));
+ /**
+ * List of all of the statuses that we can have <br> UNCONFIRMED, NEW, ASSIGNED, REOPENED, RESOLVED, VERIFIED, CLOSED
+ */
+ private static String[] statusValues = BugzillaPreferences.queryOptionsToArray(prefs.getString(IBugzillaConstants.STATUS_VALUES));
+
+ /**
+ * Get the bugzilla url used for searching for exact matches
+ *
+ * @param je
+ * The IMember to create the query string for
+ * @return A url string for the search
+ */
+ public static String getExactSearchURL(IMember je) {
+ StringBuffer sb = getQueryURLStart();
+
+ String long_desc = "";
+
+ // get the fully qualified name of the element
+ long_desc += BugzillaMylarSearchOperation.getFullyQualifiedName(je);
+
+ try{
+ // encode the string to be used as a url
+ sb.append(URLEncoder.encode(long_desc, Charset.defaultCharset().toString()));
+ } catch (UnsupportedEncodingException e)
+ {
+ // should never get here since we are using the default encoding
+ }
+ sb.append(getQueryURLEnd());
+
+ return sb.toString();
+ }
+
+ /**
+ * Get the bugzilla url used for searching for inexact matches
+ *
+ * @param je
+ * The IMember to create the query string for
+ * @return A url string for the search
+ */
+ public static String getInexactSearchURL(IMember je) {
+ StringBuffer sb = getQueryURLStart();
+
+
+ String long_desc = "";
+
+ // add the member, qualified with just its parents name
+ if (!(je instanceof IType))
+ long_desc += je.getParent().getElementName()+".";
+ long_desc += je.getElementName();
+
+ try{
+ // encode the string to be used as a url
+ sb.append(URLEncoder.encode(long_desc, Charset.defaultCharset().toString()));
+ } catch (UnsupportedEncodingException e)
+ {
+ // should never get here since we are using the default encoding
+ }
+ sb.append(getQueryURLEnd());
+
+ return sb.toString();
+ }
+
+ /**
+ * Create the end of the bugzilla query URL with all of the status' and resolutions that we want
+ * @return StringBuffer with the end of the query URL in it
+ */
+ public static StringBuffer getQueryURLEnd(){
+
+ StringBuffer sb = new StringBuffer();
+
+ // add the status and resolutions that we care about
+ sb.append("&bug_status=" + statusValues[0]); // UNCONFIRMED
+ sb.append("&bug_status=" + statusValues[1]); // NEW
+ sb.append("&bug_status=" + statusValues[2]); // ASSIGNED
+ sb.append("&bug_status=" + statusValues[3]); // REOPENED
+ sb.append("&bug_status=" + statusValues[4]); // RESOLVED
+ sb.append("&bug_status=" + statusValues[5]); // VERIFIED
+ sb.append("&bug_status=" + statusValues[6]); // CLOSED
+
+ sb.append("&resolution=" + resolutionValues[0]); // FIXED
+ sb.append("&resolution=" + resolutionValues[3]); // LATER
+ sb.append("&resolution=" + "---"); // ---
+ return sb;
+ }
+
+ /**
+ * Create the bugzilla query URL start.
+ *
+ * @return The start of the query url as a StringBuffer <br>
+ * Example: https://bugs.eclipse.org/bugs/buglist.cgi?long_desc_type=allwordssubstr&long_desc=
+ */
+ public static StringBuffer getQueryURLStart() {
+ StringBuffer sb = new StringBuffer(BugzillaPlugin.getDefault()
+ .getServerName());
+
+ if (sb.charAt(sb.length() - 1) != '/') {
+ sb.append('/');
+ }
+ sb.append("buglist.cgi?");
+
+ // use the username and password if we have it
+ if (BugzillaPreferences.getUserName() != null
+ && !BugzillaPreferences.getUserName().equals("")
+ && BugzillaPreferences.getPassword() != null
+ && !BugzillaPreferences.getPassword().equals("")) {
+ try{
+ sb.append("GoAheadAndLogIn=1&Bugzilla_login="
+ + URLEncoder.encode(BugzillaPreferences.getUserName(), Charset.defaultCharset().toString())
+ + "&Bugzilla_password="
+ + URLEncoder.encode(BugzillaPreferences.getPassword(), Charset.defaultCharset().toString())
+ + "&");
+ } catch (UnsupportedEncodingException e)
+ {
+ // should never get here since we are using the default encoding
+ }
+ }
+
+ // add the description search type
+ sb.append("long_desc_type=");
+ sb.append(patternOperationValues[0]); // search for all words
+ sb.append("&long_desc=");
+
+ return sb;
+ }
+
+ /**
+ * Search the given string for another string
+ * @param elementName The name of the element that we are looking for
+ * @param comment The text to search for this element name
+ * @return <code>true</code> if the element is found in the text else <code>false</code>
+ */
+ public static boolean hasElementName(String elementName, String comment) {
+
+ // setup a regex for the element name
+ String regexElement = ".*"+elementName+".*";
+
+ // get all of the individual lines for the string
+ String[] lines = comment.split("\n");
+
+ // go through each of the lines of the string
+ for (int i = 0; i < lines.length; i++) {
+
+ if (lines[i].matches(regexElement)){
+ return true;
+ }
+ }
+ return false;
+ }
+} \ No newline at end of file

Back to the top