| /******************************************************************************* |
| * Copyright (c) 2004, 2008 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.tasks; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| 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.debug.ui.IDebugModelPresentation; |
| import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; |
| import org.eclipse.jdt.internal.debug.ui.actions.OpenTypeAction; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.hyperlink.IHyperlink; |
| import org.eclipse.mylyn.tasks.ui.IHighlightingHyperlink; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.progress.UIJob; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| import org.eclipse.ui.texteditor.IDocumentProvider; |
| import org.eclipse.ui.texteditor.ITextEditor; |
| |
| /** |
| * @author Rob Elves |
| */ |
| public class JavaStackTraceFileHyperlink implements IHyperlink, IHighlightingHyperlink { |
| |
| private static final String ID_PLUGIN = "org.eclipse.mylyn.java.tasks"; //$NON-NLS-1$ |
| |
| protected static boolean reflectionErrorLogged; |
| |
| private final IRegion region; |
| |
| private final String traceLine; |
| |
| private final IRegion highlightingRegion; |
| |
| public JavaStackTraceFileHyperlink(IRegion region, String traceLine, IRegion highlightingRegion) { |
| this.region = region; |
| this.traceLine = traceLine; |
| this.highlightingRegion = highlightingRegion; |
| } |
| |
| public IRegion getHyperlinkRegion() { |
| return region; |
| } |
| |
| public String getHyperlinkText() { |
| // ignore |
| return null; |
| } |
| |
| public String getTypeLabel() { |
| // ignore |
| return null; |
| } |
| |
| public void open() { |
| |
| try { |
| |
| String typeName = getTypeName(); |
| int lineNumber = getLineNumber(); |
| |
| // documents start at 0 |
| if (lineNumber > 0) { |
| lineNumber--; |
| } |
| |
| startSourceSearch(typeName, lineNumber); |
| |
| } catch (CoreException e1) { |
| MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| Messages.JavaStackTraceFileHyperlink_Open_Type, |
| Messages.JavaStackTraceFileHyperlink_Failed_to_open_type); |
| return; |
| } |
| |
| } |
| |
| /** |
| * Starts a search for the type with the given name. Reports back to 'searchCompleted(...)'. |
| * |
| * @param typeName |
| * the type to search for |
| */ |
| protected void startSourceSearch(final String typeName, final int lineNumber) { |
| Job search = new Job(Messages.JavaStackTraceFileHyperlink_Searching_) { |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| // search for the type in the workspace |
| Object result; |
| try { |
| // TODO e3.8 remove reflection |
| try { |
| // e3.7 and earlier: OpenTypeAction.findTypeInWorkspace(typeName); |
| Method findTypeInWorspace = OpenTypeAction.class.getDeclaredMethod("findTypeInWorkspace", //$NON-NLS-1$ |
| String.class); |
| result = findTypeInWorspace.invoke(null, typeName); |
| } catch (NoSuchMethodException e) { |
| // e3.8: OpenTypeAction.findTypeInWorkspace(typeName, false); |
| Method findTypeInWorspace = OpenTypeAction.class.getDeclaredMethod("findTypeInWorkspace", //$NON-NLS-1$ |
| String.class, boolean.class); |
| result = findTypeInWorspace.invoke(null, typeName, false); |
| } |
| } catch (InvocationTargetException e) { |
| if (e.getCause() instanceof CoreException) { |
| searchCompleted(null, typeName, lineNumber, ((CoreException) e.getCause()).getStatus()); |
| } |
| throw e; |
| } |
| searchCompleted(result, typeName, lineNumber, null); |
| } catch (Exception e) { |
| if (!reflectionErrorLogged) { |
| reflectionErrorLogged = true; |
| StatusManager.getManager().handle( |
| new Status(IStatus.ERROR, ID_PLUGIN, "Unexpected error searching for Java type", e), //$NON-NLS-1$ |
| StatusManager.LOG); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| }; |
| search.schedule(); |
| } |
| |
| protected void searchCompleted(final Object source, final String typeName, final int lineNumber, |
| final IStatus status) { |
| UIJob job = new UIJob(Messages.JavaStackTraceFileHyperlink_link_search_complete) { |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| if (source == null) { |
| // did not find source |
| MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| Messages.JavaStackTraceFileHyperlink_Open_Type, |
| Messages.JavaStackTraceFileHyperlink_Type_could_not_be_located); |
| } else { |
| processSearchResult(source, typeName, lineNumber); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| job.setSystem(true); |
| job.schedule(); |
| } |
| |
| /** |
| * The search succeeded with the given result |
| * |
| * @param source |
| * resolved source object for the search |
| * @param typeName |
| * type name searched for |
| * @param lineNumber |
| * line number on link |
| */ |
| protected void processSearchResult(Object source, String typeName, int lineNumber) { |
| IDebugModelPresentation presentation = JDIDebugUIPlugin.getDefault().getModelPresentation(); |
| IEditorInput editorInput = presentation.getEditorInput(source); |
| if (editorInput != null) { |
| String editorId = presentation.getEditorId(editorInput, source); |
| if (editorId != null) { |
| try { |
| IEditorPart editorPart = PlatformUI.getWorkbench() |
| .getActiveWorkbenchWindow() |
| .getActivePage() |
| .openEditor(editorInput, editorId); |
| if (editorPart instanceof ITextEditor && lineNumber >= 0) { |
| ITextEditor textEditor = (ITextEditor) editorPart; |
| IDocumentProvider provider = textEditor.getDocumentProvider(); |
| provider.connect(editorInput); |
| IDocument document = provider.getDocument(editorInput); |
| try { |
| IRegion line = document.getLineInformation(lineNumber); |
| textEditor.selectAndReveal(line.getOffset(), line.getLength()); |
| } catch (BadLocationException e) { |
| MessageDialog.openInformation(PlatformUI.getWorkbench() |
| .getActiveWorkbenchWindow() |
| .getShell(), Messages.JavaStackTraceFileHyperlink_Open_Type, |
| Messages.JavaStackTraceFileHyperlink_Line_not_found_in_type); |
| } |
| provider.disconnect(editorInput); |
| } |
| } catch (CoreException e) { |
| MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| Messages.JavaStackTraceFileHyperlink_Open_Type, |
| Messages.JavaStackTraceFileHyperlink_Failed_to_open_type); |
| } |
| } |
| } |
| } |
| |
| // adapted from JavaStackTraceHyperlink |
| private String getTypeName() { |
| int start = traceLine.indexOf('('); |
| int end = traceLine.indexOf(':'); |
| if (start >= 0 && end > start) { |
| |
| // get File name (w/o .java) |
| String typeName = traceLine.substring(start + 1, end); |
| typeName = typeName.substring(0, typeName.indexOf(".")); //$NON-NLS-1$ |
| |
| String qualifier = traceLine.substring(0, start); |
| // remove the method name |
| start = qualifier.lastIndexOf('.'); |
| |
| if (start >= 0) { |
| // remove the class name |
| start = (qualifier.subSequence(0, start).toString()).lastIndexOf('.'); |
| if (start == -1) { |
| start = 0; // default package |
| } |
| } |
| |
| if (start >= 0) { |
| qualifier = qualifier.substring(0, start); |
| } |
| |
| if (qualifier.length() > 0) { |
| typeName = qualifier + "." + typeName; //$NON-NLS-1$ |
| } |
| return typeName.trim(); |
| } |
| |
| return "error"; // TODO: Complain //$NON-NLS-1$ |
| } |
| |
| // adapted from JavaStackTraceHyperlink |
| private int getLineNumber() throws CoreException { |
| int index = traceLine.lastIndexOf(':'); |
| if (index >= 0) { |
| String numText = traceLine.substring(index + 1); |
| index = numText.indexOf(')'); |
| if (index >= 0) { |
| numText = numText.substring(0, index); |
| } |
| try { |
| return Integer.parseInt(numText); |
| } catch (NumberFormatException e) { |
| throw new CoreException(null); |
| } |
| } |
| |
| throw new CoreException(null); |
| } |
| |
| public IRegion getHighlightingRegion() { |
| return (highlightingRegion != null) ? highlightingRegion : region; |
| } |
| |
| } |