blob: ad74da40667d23e5c749d43f92423b6bc9b05f1a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2014 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;
}
}