package org.ntlab.reverseDebugger; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.viewers.TreeNode; import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; import org.ntlab.onlineAccessor.JDIStaticMethodCaller; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.IncompatibleThreadStateException; import com.sun.jdi.IntegerValue; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.InvocationException; import com.sun.jdi.ObjectReference; import com.sun.jdi.ThreadReference; import com.sun.jdi.VirtualMachine; @SuppressWarnings("restriction") public class CallStackModels { private List<CallStackModel> callStackModels = new ArrayList<>(); public List<CallStackModel> getCallStackModels() { return callStackModels; } public TreeNode[] getCallStackModelsTreeNodes() { TreeNode[] roots = new TreeNode[1]; if (callStackModels.isEmpty()) { return roots; } CallStackModel callStackModel = callStackModels.get(0); roots[0] = new TreeNode(new JDIStaticMethodCaller(callStackModel.getVm(), callStackModel.getThread())); TreeNode parentNode = roots[0]; TreeNode[] childrenNode = new TreeNode[callStackModels.size()]; parentNode.setChildren(childrenNode); for (int i = 0; i < callStackModels.size(); i++) { TreeNode childNode = new TreeNode(callStackModels.get(i)); childNode.setParent(parentNode); childrenNode[i] = childNode; } return roots; } public void reset() { callStackModels.clear(); } public void updateByDebuggerStopMethodExecution(JDIInstanceMethodCaller me) { if (me == null) { return; } try { VirtualMachine vm = me.getVm(); ThreadReference thread = me.getThread(); int lineNo = thread.frame(0).location().lineNumber(); update(vm, thread, me.getReceiver(), lineNo); } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); } } public void updateByAlias(JDIInstanceMethodCaller alias) { if (alias == null) { return; } VirtualMachine vm = alias.getVm(); ThreadReference thread = alias.getThread(); try { ObjectReference me = (ObjectReference)alias.callInstanceMethod("getMethodExecution"); int lineNo = ((IntegerValue)alias.callInstanceMethod("getLineNo")).value(); update(vm, thread, me, lineNo); } catch (InvalidTypeException | ClassNotLoadedException | InvocationException | IncompatibleThreadStateException e) { e.printStackTrace(); } } private void update(VirtualMachine vm, ThreadReference thread, ObjectReference me, int topMethodCallLineNo) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { callStackModels.clear(); ObjectReference childMe = null; int callLineNo = topMethodCallLineNo; while (me != null) { CallStackModel callStackModel = new CallStackModel(vm, thread, me, callLineNo); callStackModels.add(callStackModel); childMe = me; me = (ObjectReference)callStackModel.callInstanceMethod("getParent"); if (me != null) { JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, me); ObjectReference callStatement = (ObjectReference)mc.callInstanceMethod("getMethodInvocation", childMe); callLineNo = ((IntegerValue)mc.changeReceiver(callStatement).callInstanceMethod("getLineNo")).value(); } } } }