1 55 56 package org.apache.bsf.engines.javascript; 57 58 import java.io.InputStream ; 59 import java.io.IOException ; 60 import java.io.StringReader ; 61 import java.io.Reader ; 62 import java.rmi.RemoteException ; 63 import java.util.Vector ; 64 import java.util.Enumeration ; 65 import java.util.Hashtable ; 66 import java.security.*; 67 68 import org.mozilla.javascript.*; 69 import org.mozilla.javascript.debug.*; 70 71 import org.apache.bsf.debug.util.DebugLog; 72 import org.apache.bsf.*; 73 import org.apache.bsf.util.*; 74 import org.apache.bsf.debug.*; 75 import org.apache.bsf.debug.jsdi.*; 76 77 public class RhinoEngineDebugger implements Debugger { 78 79 82 private Scriptable global; 83 private JsObject globalstub; 84 85 private RhinoContextProxy m_rcp; 86 private Scriptable undefined; 87 private JsObject undefinedStub; 88 89 97 private Hashtable stubs; 98 99 private JsCallbacks m_callbacks; 100 private JsEngineStub engineStub; 101 102 private FnOrScript m_compilingFnOrScript; 103 private JavaScriptEngine m_eng; 104 105 private Thread m_thread; 106 107 private Hashtable m_documents; 108 109 BSFDebugManagerImpl dbgmgr; 110 111 public RhinoEngineDebugger(JavaScriptEngine eng) 112 throws RemoteException { 113 super(); 114 m_thread = Thread.currentThread(); 115 m_eng = eng; 116 dbgmgr = eng.getDebugManager(); 117 118 m_documents = new Hashtable (); 119 120 stubs = new Hashtable (); 121 m_callbacks = null; 122 123 engineStub = new JsEngineStub(this); 124 125 } 126 127 130 public void disconnectedDebuggerNotify() { 131 m_callbacks = null; 132 } 133 134 void addStub(Context cx, RhinoContextProxy jscx) { 135 stubs.put(cx, jscx); 136 } 137 138 void addStub(DebugFrame frame, JsContextStub stub) { 139 stubs.put(frame, stub); 140 } 141 142 void addStub(Scriptable sobj, JsObject jsobj) { 143 stubs.put(sobj, jsobj); 144 } 145 146 void dropStub(Object key) { 147 stubs.remove(key); 148 } 149 150 public synchronized DocumentCell getDocumentCell(String name) { 151 return (DocumentCell) m_documents.get(name); 152 } 153 154 public synchronized DocumentCell loadDocumentNotify(String name) { 156 DocumentCell cell; 157 158 cell = (DocumentCell) m_documents.get(name); 159 if (cell == null) { 160 cell = new DocumentCell(this, name); 161 m_documents.put(name, cell); 162 if (dbgmgr!=null) 163 dbgmgr.loadDocumentNotify(m_eng, name); 164 } 165 return cell; 166 } 167 168 public synchronized void placeBreakpointAtLine(int brkptid, 169 String docname, 170 int lineno) { 171 172 DocumentCell cell; 173 cell = (DocumentCell) m_documents.get(docname); 174 cell.addBreakpointAtLine(brkptid, lineno); 175 } 176 177 public synchronized void placeBreakpointAtOffset(int brkptid, 178 String docname, 179 int offset) { 180 181 DocumentCell cell; 182 cell = (DocumentCell) m_documents.get(docname); 183 cell.addBreakpointAtOffset(brkptid, offset); 184 } 185 186 public void removeBreakpoint(String docname, int brkptid) 187 throws BSFException { 188 189 DocumentCell cell; 190 cell = (DocumentCell) m_documents.get(docname); 191 cell.removeBreakpoint(brkptid); 192 } 193 194 public void setEntryExit(String docname, boolean on) 195 throws BSFException { 196 197 DocumentCell cell; 198 cell = (DocumentCell) m_documents.get(docname); 199 cell.setEntryExit(on); 200 } 201 202 public Object eval(String docname, String fnOrScript, int lineno) 203 throws RemoteException { 204 Object retval; 205 try { 206 retval = m_eng.eval(docname, lineno, -1, fnOrScript); 207 return marshallProperty(retval); 208 } catch (BSFException ex) { 209 throw new RemoteException ("Failed eval", ex); 210 } 211 } 212 213 public JsContext getContext(int depth) { 214 if (m_rcp != null) return m_rcp.getContext(depth); 215 return null; 216 } 217 218 public int getContextCount() { 219 if (m_rcp != null) return m_rcp.getContextCount(); 220 return -1; 221 } 222 223 227 public JsCallbacks getDebugger() { 228 return m_callbacks; 229 } 230 231 public Object getDebugInterface() { 232 return engineStub; 233 } 234 235 public JsObject getGlobalObject() { 236 return globalstub; 237 } 238 239 public RhinoContextProxy getRhinoContextProxy() { 240 return m_rcp; 241 } 242 243 RhinoContextProxy getStub(Context cx) { 244 return (RhinoContextProxy) stubs.get(cx); 245 } 246 247 JsContextStub getStub(DebugFrame frame) { 248 return (JsContextStub) stubs.get(frame); 249 } 250 251 JsObject getStub(Scriptable sobj) { 252 return (JsObject) stubs.get(sobj); 253 } 254 255 public JsObject getUndefinedValue() { 256 return undefinedStub; 257 } 258 259 public String getThread() { 260 String resultstr = ""; 261 262 if (m_thread != null) { 263 try { 264 final String resultstrf = (String ) 265 AccessController.doPrivileged(new PrivilegedExceptionAction() { 266 public Object run() throws Exception { 267 return m_thread.getName(); 268 } 269 }); 270 resultstr = resultstrf; 271 } 272 catch (PrivilegedActionException prive) { 273 resultstr = "Security Exception triggered. " + 274 "Thread info unavailable"; 275 } 276 } 277 return resultstr; 278 } 279 280 public String getThreadGroup() { 281 String resultstr = ""; 282 283 if (m_thread != null) { 284 try { 285 final String resultstrf = (String ) 286 AccessController.doPrivileged(new PrivilegedExceptionAction() { 287 public Object run() throws Exception { 288 return m_thread.getThreadGroup().getName(); 289 } 290 }); 291 resultstr = resultstrf; 292 } 293 catch (PrivilegedActionException prive) { 294 resultstr = "Security Exception triggered. " + 295 "ThreadGroup info unavailable"; 296 } 297 } 298 return resultstr; 299 } 300 301 308 public void handleBreakpointHit(Context cx) { 309 JsCallbacks debugger; 310 BreakPoint bp; 311 Enumeration e; 312 DocumentCell cell; 313 boolean breakpointFound=false; 314 String name; 315 int lineno; 316 boolean suspend=false; 317 318 m_thread = Thread.currentThread(); 319 DebugLog.stdoutPrintln("**** Handling a breakpoint hit...", 320 DebugLog.BSF_LOG_L3); 321 m_rcp = getStub(cx); 322 if (m_rcp == null) { 323 m_rcp = new RhinoContextProxy(this, cx); 324 addStub(cx, m_rcp); 325 } 326 if (m_callbacks==null) { 330 DebugLog.stdoutPrintln(" No callbacks, resuming...", DebugLog.BSF_LOG_L3); 331 m_rcp.run(); 332 333 } else { 334 337 name = m_rcp.getSourceName(); 338 lineno = m_rcp.getLineNumber(); 339 340 DebugLog.stdoutPrintln(" in "+name+" at "+lineno, DebugLog.BSF_LOG_L3); 341 342 cell = getDocumentCell(name); 343 if (cell != null) 344 _handleBreakpointHit(cell,lineno); 345 } 346 m_rcp = null; 347 } 348 349 public void _handleBreakpointHit(DocumentCell cell, int lineno) { 350 351 JsCallbacks debugger; 352 BreakPoint bp; 353 Enumeration e; 354 JsContext stub=null; 355 boolean breakpointFound=false; 356 boolean suspend=false; 357 358 try { 359 bp = cell.findBreakpointAtLine(lineno); 360 } catch (BSFException bsfex) { 361 bp = null; 362 } 363 if (bp != null) { 364 breakpointFound = true; 365 try { 366 stub = m_rcp.hitBreakpoint(); 367 DebugLog.stdoutPrintln(" breakpoint callback...", DebugLog.BSF_LOG_L3); 368 m_callbacks.createFuture(m_rcp); 369 m_callbacks.handleBreakpointHit(stub); 370 suspend = true; 371 } catch (RemoteException rex) { 372 DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING BREAKPOINT CALLBACK", DebugLog.BSF_LOG_L0); 373 DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); 374 rex.printStackTrace(); 375 suspend = false; 376 } 377 } else { 378 DebugLog.stdoutPrintln(" didn't find a breakpoint...", DebugLog.BSF_LOG_L3); 379 breakpointFound = false; 380 } 381 382 if (!breakpointFound) { 383 try { 387 stub = m_rcp.stepping(); 388 FnOrScript current = cell.findFnOrScriptContaining(lineno); 389 if (stub != null) { 390 cell.setLastFnOrScript(current); 391 DebugLog.stdoutPrintln(" stepping-done callback...", 392 DebugLog.BSF_LOG_L3); 393 m_callbacks.createFuture(m_rcp); 394 m_callbacks.handleSteppingDone(stub); 395 suspend = true; 396 } 397 else if (cell.getEntryExit() && 398 (current != cell.getLastFnOrScript()) && 399 (m_rcp.getContextCount() == 0)) { 400 cell.setLastFnOrScript(current); 401 stub = m_rcp.entry_exit_mode(); 402 DebugLog.stdoutPrintln(" entry/exit mode...", 403 DebugLog.BSF_LOG_L3); 404 m_callbacks.createFuture(m_rcp); 405 m_callbacks.handleSteppingDone(stub); 406 suspend = true; 407 } 408 else { 409 DebugLog.stdoutPrintln(" No reason to suspend execution.", DebugLog.BSF_LOG_L3); 410 suspend = false; 411 } 412 } catch (RemoteException rex) { 413 DebugLog.stderrPrintln(" EXCEPTION OCCURED DURING STEPPING-DONE CALLBACK", DebugLog.BSF_LOG_L0); 414 DebugLog.stderrPrintln(rex.getMessage(), DebugLog.BSF_LOG_L0); 415 rex.printStackTrace(); 416 suspend = false; 417 } 418 } 419 if (suspend) { 420 try { 423 m_callbacks.suspendFuture(m_rcp); 424 } catch (Exception ex) { 425 DebugLog.stdoutPrintln("Future creation failed... releasing the engine", DebugLog.BSF_LOG_L3); 426 m_rcp.run(); 427 } 428 } 429 } 430 431 public void run(JsEngineStub eng) throws Exception { 432 DebugLog.stdoutPrintln("RhinoEngineDebugger::run()...", 433 DebugLog.BSF_LOG_L3); 434 m_rcp.run(); 435 m_callbacks.completeFuture(m_rcp); 436 } 437 438 public void stepIn(JsEngineStub eng) throws Exception { 439 DebugLog.stdoutPrintln("RhinoEngineDebugger::stepIn()...", 440 DebugLog.BSF_LOG_L3); 441 m_rcp.stepIn(); 442 m_callbacks.completeFuture(m_rcp); 443 } 444 445 public void stepOut(JsEngineStub eng) throws Exception { 446 DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOut()...", 447 DebugLog.BSF_LOG_L3); 448 m_rcp.stepOut(); 449 m_callbacks.completeFuture(m_rcp); 450 } 451 public void stepOver(JsEngineStub eng) throws Exception { 452 453 DebugLog.stdoutPrintln("RhinoEngineDebugger::stepOver()...", 454 DebugLog.BSF_LOG_L3); 455 m_rcp.stepOver(); 456 m_callbacks.completeFuture(m_rcp); 457 } 458 459 public void handleCompilationDone(Context cx, 460 DebuggableScript fnOrScript, 461 StringBuffer source) { 462 463 m_thread = Thread.currentThread(); 464 m_compilingFnOrScript.addCompilationUnit(cx, fnOrScript, source); 465 } 466 467 public void handleExceptionThrown(Context cx, Object exceptionThrown) { 468 JsContext stub; 469 JsCallbacks debugger; 470 BreakPoint bp; 471 Enumeration e; 472 DocumentCell cell; 473 String name,msg; 474 Exception ex; 475 int lineno; 476 NativeError error; 477 478 m_thread = Thread.currentThread(); 479 m_rcp = getStub(cx); 480 if (m_rcp == null) { 481 m_rcp = new RhinoContextProxy(this, cx); 482 addStub(cx, m_rcp); 483 } 484 try { 485 if (m_callbacks==null) { 489 m_rcp.run(); 490 return; 491 } 492 493 name = m_rcp.getSourceName(); 496 lineno = m_rcp.getLineNumber(); 497 try { 498 error = (NativeError)exceptionThrown; 499 msg = error.getName() + ": " + error.getMessage(); 500 } catch (ClassCastException ccex) { 501 msg = "Unknown JavaScript Exception"; 502 } 503 ex = new Exception (msg); 504 505 cell = getDocumentCell(name); 506 if (cell == null) return; 507 508 try { 509 stub = m_rcp.exceptionThrown(); 510 m_callbacks.createFuture(m_rcp); 511 m_callbacks.handleExceptionThrown(stub,ex); 512 513 m_callbacks.suspendFuture(m_rcp); 516 517 } catch (Exception ex2) { 518 m_rcp.run(); 519 520 } 521 } finally { 522 m_rcp = null; 523 } 524 } 525 526 Object marshallProperty(Object prop) throws RemoteException { 527 if (prop == null) 528 return null; 529 if (prop == Scriptable.NOT_FOUND) 530 return null; 531 if (prop == Context.getUndefinedValue()) 532 return undefinedStub; 533 if (prop instanceof Scriptable) { 534 JsObject stub; 535 Scriptable sprop = (Scriptable) prop; 536 stub = getStub(sprop); 537 if (stub == null) { 538 stub = new JsObjectStub(this, sprop); 539 this.addStub(sprop, stub); 540 } 541 return stub; 542 } 543 return prop; 544 } 545 546 JsObject marshallScriptable(Scriptable prop) throws RemoteException { 547 if (prop == null) 548 return null; 549 if (prop == Scriptable.NOT_FOUND) 550 return null; 551 if (prop == Context.getUndefinedValue()) 552 return undefinedStub; 553 554 JsObject stub; 555 Scriptable sprop = (Scriptable) prop; 556 stub = getStub(sprop); 557 if (stub == null) { 558 stub = new JsObjectStub(this, sprop); 559 this.addStub(sprop, stub); 560 } 561 return stub; 562 } 563 564 574 public void setBreakNextLine(JsContext context, boolean isLineStep) { 575 } 576 577 void setCompilingFnOrScript(FnOrScript fnOrScript) { 578 m_compilingFnOrScript = fnOrScript; 579 } 580 581 586 public void setDebugger(JsCallbacks debugger) { 587 m_callbacks = debugger; 588 } 589 } 590 | Popular Tags |