package org.ntlab.traceanalyzer;
import java.io.File;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.ntlab.trace.ClassInfo;
import org.ntlab.trace.Trace;
public class CallTreeView extends ViewPart {
private TreeViewer viewer;
private IAction openAction;
private IAction markAction;
private IAction highlightAction;
private MarkedTrace markedTrace;
private Shell shell;
@Override
public void createPartControl(Composite parent) {
shell = parent.getShell();
viewer = new TreeViewer(parent);
viewer.setContentProvider(new CallTreeContentProvider());
viewer.setLabelProvider(new CallTreeLabelProvider());
viewer.setInput(null);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection sel = (IStructuredSelection)event.getSelection();
Object element = sel.getFirstElement();
if (element instanceof MarkedMethodExecution) {
String className = ((MarkedMethodExecution)element).getDeclaringClassName();
String methodSignature = ((MarkedMethodExecution)element).getSignature();
ClassInfo classInfo = markedTrace.getClassInfo(className);
if (classInfo == null) {
className = ((MarkedMethodExecution)element).getReceiverClassName();
classInfo = markedTrace.getClassInfo(className);
}
if (classInfo != null) {
String projectPath = classInfo.getLoaderPath();
IJavaProject javaProject = findJavaProject(projectPath);
if (javaProject != null) {
openInJavaEditor(javaProject, className, methodSignature);
}
}
}
}
});
getSite().setSelectionProvider(viewer);
createActions();
createToolBar();
createMenuBar();
}
/** アクションを作成 */
private void createActions(){
// トレースファイルを開くアクションを作成
ImageDescriptor openIcon = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJ_FOLDER);
openAction = new Action("Open Trace File...", openIcon){
public void run(){
// トレース出力先参照ウィザード
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
dialog.setText("Open Trace File");
dialog.setFilterExtensions(new String[]{"*.*"});
String path = dialog.open();
if (path == null) {
return;
}
markedTrace = new MarkedTrace(path);
viewer.setInput(markedTrace);
viewer.refresh();
highlightAction.setChecked(false);
}
};
// トレースにマークするアクションを作成
ImageDescriptor markIcon = PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OPEN_MARKER);
markAction = new Action("Mark Trace...", markIcon){
public void run(){
final Shell traceMarkShell = new Shell(SWT.TITLE | SWT.ON_TOP | SWT.CLOSE); // マーク指定画面
traceMarkShell.setText("Mark Trace");
traceMarkShell.setSize(250, 150);
traceMarkShell.setLayout(new FormLayout());
// 開始時間(ラベル)
Label startTimeLabel = new Label(traceMarkShell, SWT.NULL);
startTimeLabel.setText("Start Time:");
FormData startTimeLabelForm = new FormData();
startTimeLabelForm.top = new FormAttachment(10, 5);
startTimeLabelForm.left = new FormAttachment(5, 5);
startTimeLabel.setLayoutData(startTimeLabelForm);
// 開始時間(テキストボックス)
final Text startTimeText = new Text(traceMarkShell, SWT.BORDER | SWT.SINGLE | SWT.WRAP);
startTimeText.setText(Long.toString(markedTrace.getMarkStart()));
FormData startTimeTextForm = new FormData();
startTimeTextForm.top = new FormAttachment(10, 5);
startTimeTextForm.left = new FormAttachment(35, 10);
startTimeTextForm.right = new FormAttachment(95, -5);
startTimeText.setLayoutData(startTimeTextForm);
// 終了時間(ラベル)
Label endTimeLabel = new Label(traceMarkShell, SWT.NULL);
endTimeLabel.setText("End Time:");
FormData endTimeLabelForm = new FormData();
endTimeLabelForm.top = new FormAttachment(30, 5);
endTimeLabelForm.left = new FormAttachment(5, 5);
endTimeLabel.setLayoutData(endTimeLabelForm);
// 終了時間入力(テキストボックス)
final Text endTimeText = new Text(traceMarkShell, SWT.BORDER | SWT.SINGLE | SWT.WRAP);
endTimeText.setText(Long.toString(markedTrace.getMarkEnd()));
FormData endTimeTextForm = new FormData();
endTimeTextForm.top = new FormAttachment(30, 5);
endTimeTextForm.left = new FormAttachment(35, 10);
endTimeTextForm.right = new FormAttachment(95, -5);
endTimeText.setLayoutData(endTimeTextForm);
//OKボタン
Button okButton = new Button(traceMarkShell, SWT.PUSH);
okButton.setText("OK");
FormData okButtonForm = new FormData();
okButtonForm.bottom = new FormAttachment(100, -5);
okButtonForm.right = new FormAttachment(95, -5);
okButton.setLayoutData(okButtonForm);
okButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e){
if (markedTrace != null) {
String startText = startTimeText.getText();
String endText = endTimeText.getText();
try {
long start = Long.parseLong(startText);
long end = Long.parseLong(endText);
traceMarkShell.close();
markedTrace.mark(start, end);
viewer.setInput(markedTrace);
viewer.refresh();
highlightAction.setChecked(false);
} catch (NumberFormatException ex) {
}
} else {
traceMarkShell.close();
}
}
});
traceMarkShell.open();
}
};
// マーク固有のメソッドを強調するアクションを作成
ImageRegistry registry = Activator.getDefault().getImageRegistry();
ImageDescriptor highlightIcon = registry.getDescriptor("TraceAnalyzer.HIGHLIGHT_UNIQUE_IMAGE");
highlightAction = new Action("Highlight Unique Methods", Action.AS_CHECK_BOX){
public void run(){
if (markedTrace != null) {
if (isChecked()) {
markedTrace.setHighlightUniqueMethods(true);
viewer.setInput(markedTrace);
viewer.refresh();
} else {
markedTrace.setHighlightUniqueMethods(false);
viewer.setInput(markedTrace);
viewer.refresh();
}
}
}
};
highlightAction.setImageDescriptor(highlightIcon);
}
/** ツールバーにアクションを追加 */
private void createToolBar(){
IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
mgr.add(openAction);
mgr.add(markAction);
mgr.add(highlightAction);
}
/** メニューバーにアクションを追加 */
private void createMenuBar(){
IMenuManager mgr = getViewSite().getActionBars().getMenuManager();
mgr.add(openAction);
mgr.add(markAction);
}
public void setFocus() {
viewer.getTree().setFocus();
}
private IJavaProject findJavaProject(String projectPath) {
IJavaProject javaProject = null;
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IProject[] projects = root.getProjects();
for (IProject project: projects) {
if (projectPath.startsWith(project.getLocation().toString())) {
javaProject = JavaCore.create(project);
break;
}
}
return javaProject;
}
private void openInJavaEditor(IJavaProject javaProject, String className, String methodSignature) {
try {
IType type = javaProject.findType(className);
if (type != null) {
IEditorPart editor = JavaUI.openInEditor(type);
if (!type.isLocal() && !type.isMember()) {
for (IMethod method: type.getMethods()) {
if (methodSignature.contains(method.getElementName())) {
JavaUI.revealInEditor(editor, (IJavaElement)method);
}
}
}
}
} catch (PartInitException | JavaModelException e) {
e.printStackTrace();
}
}
}