Newer
Older
org.ntlab.reverseDebugger / org.ntlab.reverseDebugger / src / org / ntlab / reverseDebugger / CallStackModels.java
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();
			}
		}
	}	
}