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; } }