| package org.eclipse.dltk.rhino.dbgp; |
| |
| import java.util.ArrayList; |
| import java.util.Observer; |
| import java.util.WeakHashMap; |
| |
| import org.mozilla.javascript.Context; |
| |
| public class DBGPStackManager { |
| |
| protected static WeakHashMap map = new WeakHashMap(); |
| |
| private ArrayList stack = new ArrayList(); |
| |
| private static boolean breakpointsThreadLocal; |
| |
| private boolean needSuspend; |
| |
| private DBGPDebugger observer; |
| |
| private BreakPointManager manager = null; |
| |
| private static BreakPointManager gmanager = null; |
| |
| private boolean suspendOnExit; |
| |
| private boolean suspendOnEntry; |
| |
| private boolean suspenOnChangeLine; |
| |
| public BreakPointManager getManager() { |
| return manager; |
| } |
| |
| private DBGPStackManager() { |
| if (isBreakpointsThreadLocal()) { |
| manager = new BreakPointManager(); |
| } else { |
| synchronized (DBGPStackManager.class) { |
| if (gmanager == null) |
| gmanager = new BreakPointManager(); |
| } |
| manager = gmanager; |
| } |
| } |
| |
| public static DBGPStackManager getManager(Context cx) { |
| DBGPStackManager object = (DBGPStackManager) map.get(cx); |
| if (object != null) |
| return object; |
| object = new DBGPStackManager(); |
| map.put(cx, object); |
| return object; |
| } |
| |
| public static void removeManager(Context cx) { |
| map.remove(cx); |
| } |
| |
| public void enter(DBGPDebugFrame debugFrame) { |
| stack.add(debugFrame); |
| String sn = debugFrame.getWhere(); |
| |
| if (sn != null) { |
| BreakPoint hit = manager.hitEnter(sn); |
| if (hit != null) |
| checkBreakpoint(debugFrame, hit); |
| } |
| |
| if (suspendOnEntry) { |
| if (debugFrame.getWhere().equals("module")) { |
| observer.update(null, this); |
| waitForContinuation(); |
| } else |
| suspenOnChangeLine = true; |
| } |
| } |
| |
| public void exit(DBGPDebugFrame debugFrame) { |
| if (needSuspend || suspendOnExit) { |
| |
| observer.update(null, this); |
| waitForContinuation(); |
| } |
| String sn = debugFrame.getWhere(); |
| |
| if (sn != null) { |
| BreakPoint hit = manager.hitExit(sn); |
| if (hit != null) |
| checkBreakpoint(debugFrame, hit); |
| } |
| stack.remove(debugFrame); |
| |
| } |
| |
| public void changeLine(DBGPDebugFrame frame, int lineNumber) { |
| if (suspenOnChangeLine) { |
| suspenOnChangeLine = false; |
| observer.update(null, this); |
| waitForContinuation(); |
| } |
| if (frame.isSuspend()) { |
| needSuspend = true; |
| } |
| BreakPoint hit = manager.hit(frame.getSourceName(), lineNumber); |
| checkBreakpoint(frame, hit); |
| } |
| |
| private synchronized void waitForContinuation() { |
| try { |
| this.wait(); |
| } catch (InterruptedException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| |
| private void continueExecution() { |
| this.notify(); |
| } |
| |
| private void checkBreakpoint(DBGPDebugFrame frame, BreakPoint hit) { |
| |
| if (hit != null) { |
| if (hit.isEnabled()) { |
| if (hit.expression != null) { |
| Object eval = frame.eval(hit.expression); |
| if (eval != null) { |
| if (eval.equals(Boolean.TRUE)) { |
| needSuspend = true; |
| } else |
| needSuspend = false; |
| } else |
| needSuspend = false; |
| } else |
| needSuspend = true; |
| // observer.update(null, hit); |
| } |
| } |
| if (needSuspend) { |
| observer.update(null, this); |
| waitForContinuation(); |
| } |
| } |
| |
| public void exceptionThrown(Throwable ex) { |
| |
| } |
| |
| public void suspend() { |
| needSuspend = true; |
| } |
| |
| public int getStackDepth() { |
| return stack.size(); |
| } |
| |
| public DBGPDebugFrame getStackFrame(int parseInt) { |
| int stackCounter = stack.size() - parseInt - 1; |
| if (stackCounter >= 0) { |
| return (DBGPDebugFrame) stack.get(stackCounter); |
| } |
| return null; |
| } |
| |
| public int getLineNumber(String level) { |
| return getStackFrame(0).getLineNumber(); |
| } |
| |
| public void registerBreakPoint(BreakPoint p) { |
| manager.addBreakPoint(p); |
| } |
| |
| public void setDebugger(DBGPDebugger debugger) { |
| this.observer = debugger; |
| } |
| |
| public synchronized void resume() { |
| this.needSuspend = false; |
| for (int a = 0; a < this.getStackDepth(); a++) { |
| this.getStackFrame(a).setSuspend(false); |
| } |
| continueExecution(); |
| } |
| |
| public synchronized void stepOver() { |
| getStackFrame(0).setSuspend(true); |
| if (this.getStackDepth() > 1) { |
| getStackFrame(1).setSuspend(true); |
| } |
| this.needSuspend = false; |
| continueExecution(); |
| } |
| |
| public synchronized void stepIn() { |
| this.needSuspend = true; |
| continueExecution(); |
| } |
| |
| public synchronized void stepOut() { |
| getStackFrame(0).setSuspend(false); |
| this.needSuspend = false; |
| if (this.getStackDepth() > 1) { |
| getStackFrame(1).setSuspend(true); |
| } |
| continueExecution(); |
| } |
| |
| public void waitForNotify() { |
| waitForContinuation(); |
| } |
| |
| public void removeBreakpoint(String id) { |
| this.manager.removeBreakPoint(id); |
| } |
| |
| public void updateBreakpoint(String id, String newState, String newLine, |
| String hitValue, String hitCondition, String condExpr) { |
| this.manager.updateBreakpoint(id, newState, newLine, hitValue, |
| hitCondition, condExpr); |
| } |
| |
| public Observer getObserver() { |
| return observer; |
| } |
| |
| public BreakPoint getBreakpoint(String id) { |
| return this.manager.getBreakpoint(id); |
| } |
| |
| public void setSuspendOnExit(boolean parseBoolean) { |
| this.suspendOnExit = parseBoolean; |
| } |
| |
| public void setSuspendOnEntry(boolean parseBoolean) { |
| this.suspendOnEntry = parseBoolean; |
| } |
| |
| public static boolean isBreakpointsThreadLocal() { |
| return breakpointsThreadLocal; |
| } |
| |
| public static void setBreakpointsThreadLocal(boolean breakpointsThreadLocal) { |
| DBGPStackManager.breakpointsThreadLocal = breakpointsThreadLocal; |
| } |
| |
| } |