1 33 34 package edu.rice.cs.drjava.model.repl.newjvm; 35 36 import java.util.LinkedList ; 37 import java.util.ListIterator ; 38 import java.util.ArrayList ; 39 import java.util.Hashtable ; 40 import java.util.Enumeration ; 41 import java.util.List ; 42 import java.io.*; 43 44 import java.rmi.*; 45 import java.net.URL ; 46 import java.net.MalformedURLException ; 47 48 49 52 53 import edu.rice.cs.util.ClassPathVector; 54 import edu.rice.cs.util.Log; 55 import edu.rice.cs.util.OutputStreamRedirector; 56 import edu.rice.cs.util.InputStreamRedirector; 57 import edu.rice.cs.util.StringOps; 58 import edu.rice.cs.util.UnexpectedException; 59 import edu.rice.cs.util.classloader.ClassFileError; 60 import edu.rice.cs.util.newjvm.*; 61 62 import edu.rice.cs.drjava.platform.PlatformFactory; 63 import edu.rice.cs.drjava.model.junit.JUnitModelCallback; 64 import edu.rice.cs.drjava.model.junit.JUnitTestManager; 65 import edu.rice.cs.drjava.model.junit.JUnitError; 66 import edu.rice.cs.drjava.model.repl.*; 67 import edu.rice.cs.drjava.model.ClassPathEntry; 68 69 import javax.swing.JDialog ; 71 72 import koala.dynamicjava.parser.wrapper.*; 73 import koala.dynamicjava.parser.*; 74 75 82 public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRemoteI, JUnitModelCallback { 83 84 85 public static final InterpreterJVM ONLY = new InterpreterJVM(); 86 87 private static final Log _log = new Log("MasterSlave.txt", false); 88 private static final boolean printMessages = false; 89 90 91 public static final String EMPTY_TRACE_TEXT = ""; 92 93 94 private final InterpreterData _defaultInterpreter; 95 96 97 private final Hashtable <String ,InterpreterData> _interpreters; 98 99 100 private final ClassPathVector _classPath; 101 102 103 private final JUnitTestManager _junitTestManager; 104 105 106 private final ClassPathManager _classPathManager; 107 108 109 private volatile MainJVMRemoteI _mainJVM; 110 111 112 private volatile InterpreterData _activeInterpreter; 113 114 117 118 120 121 private volatile boolean _messageOnResetFailure; 122 123 124 private InterpreterJVM() { 125 126 _classPath = new ClassPathVector(); 127 _classPathManager = new ClassPathManager(); 128 _defaultInterpreter = new InterpreterData(new DynamicJavaAdapter(_classPathManager)); 129 _interpreters = new Hashtable <String ,InterpreterData>(); 130 _junitTestManager = new JUnitTestManager(this); 131 _messageOnResetFailure = true; 132 133 135 _quitSlaveThreadName = "Reset Interactions Thread"; 136 _pollMasterThreadName = "Poll DrJava Thread"; 137 _activeInterpreter = _defaultInterpreter; 138 139 try { _activeInterpreter.getInterpreter().interpret("0"); } 140 catch (ExceptionReturnedException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 141 } 142 143 private static void _dialog(String s) { 144 _log.log(s); 146 } 147 148 151 protected void handleStart(MasterRemote mainJVM) { 152 _mainJVM = (MainJVMRemoteI) mainJVM; 154 155 System.setIn(new InputStreamRedirector() { 157 protected String _getInput() { try { return _mainJVM.getConsoleInput(); } 159 catch(RemoteException re) { 160 _log.log("System.in: " + re.toString()); 162 throw new IllegalStateException ("Main JVM can't be reached for input.\n" + re); 163 } 164 } 165 }); 166 167 System.setOut(new PrintStream(new OutputStreamRedirector() { 169 public void print(String s) { try { 171 _mainJVM.systemOutPrint(s); 173 } 174 catch (RemoteException re) { 175 _log.log("System.out: " + re.toString()); 177 } 178 } 179 })); 180 181 System.setErr(new PrintStream(new OutputStreamRedirector() { 183 public void print(String s) { try { 185 _mainJVM.systemErrPrint(s); 187 } 188 catch (RemoteException re) { 189 _log.log("System.err: " + re.toString()); 191 } 192 } 193 })); 194 195 199 if (PlatformFactory.ONLY.isWindowsPlatform()) { 200 JDialog d = new JDialog (); 201 d.setSize(0,0); 202 d.setVisible(true); 203 d.setVisible(false); 204 } 205 } 207 208 212 public void interpret(String s) { interpret(s, _activeInterpreter); } 213 214 220 public void interpret(String s, String interpreterName) { interpret(s, getInterpreter(interpreterName)); } 221 222 227 public void interpret(final String input, final InterpreterData interpreter) { 228 _log.log(this + ".interpret(" + input + ") called"); 229 try { 230 synchronized(interpreter) { 231 if (interpreter.inProgress()) { 232 _mainJVM.interpretResult(new InterpreterBusy()); 233 return; 234 } 235 interpreter.setInProgress(true); } 238 Thread thread = new Thread ("interpret thread: " + input) { 241 public void run() { 242 String s = input; 243 try { try { 245 _log.log("Interpreter thread for " + input + " has started"); 246 248 Object result = interpreter.getInterpreter().interpret(s); 250 String resultString = String.valueOf(result); 251 253 if (result == Interpreter.NO_RESULT) { 254 _mainJVM.interpretResult(new VoidResult()); 257 } 258 else { 259 String style = InteractionsDocument.OBJECT_RETURN_STYLE; 263 if (result instanceof String ) { 264 style = InteractionsDocument.STRING_RETURN_STYLE; 265 String possibleChar = (String )result; 267 268 if (possibleChar.startsWith("\'") && possibleChar.endsWith("\'") && possibleChar.length()==3) 269 style = InteractionsDocument.CHARACTER_RETURN_STYLE; 270 } 271 if (result instanceof Number ) style = InteractionsDocument.NUMBER_RETURN_STYLE; 272 _mainJVM.interpretResult(new ValueResult(resultString, style)); 273 } 274 } 275 catch (ExceptionReturnedException e) { 276 Throwable t = e.getContainedException(); 277 _dialog("interp exception: " + t); 279 if (t instanceof ParseException) 281 _mainJVM.interpretResult(new SyntaxErrorResult((ParseException) t, input)); 282 else if (t instanceof TokenMgrError) 283 _mainJVM.interpretResult(new SyntaxErrorResult((TokenMgrError) t, input)); 284 else if (t instanceof ParseError) 285 _mainJVM.interpretResult(new SyntaxErrorResult((ParseError) t, input)); 286 else { 287 290 _mainJVM.interpretResult(new ExceptionResult(t.getClass().getName(), t.getMessage(), 291 InterpreterJVM.getStackTrace(t), null)); 292 } 293 } 294 catch (Throwable t) { 295 _dialog("irregular interp exception: " + t); 297 String shortMsg = null; 299 if ((t instanceof ParseError) && ((ParseError) t).getParseException() != null) 300 shortMsg = ((ParseError) t).getMessage(); _mainJVM.interpretResult(new ExceptionResult(t.getClass().getName(), t.getMessage(), 302 InterpreterJVM.getStackTrace(t), shortMsg)); 303 } 304 } 305 catch(RemoteException re) { 306 _log.log("MainJVM.interpret threw " + re.toString()); 307 } 308 } 309 }; 311 thread.setDaemon(true); 312 thread.start(); 313 } catch(RemoteException re) { 315 _log.log("MainJVM.interpret threw" + re.toString()); 316 } 317 finally { interpreter.setInProgress(false); 320 } 321 } 322 323 private static String _processReturnValue(Object o) { 324 if (o instanceof String ) return "\"" + o + "\""; 325 if (o instanceof Character ) return "'" + o + "'"; 326 return o.toString(); 327 } 328 329 333 public synchronized String getVariableToString(String var) throws RemoteException { 334 Interpreter i = _activeInterpreter.getInterpreter(); 336 if (i instanceof JavaInterpreter) { 337 try { 338 Object value = ((JavaInterpreter)i).getVariable(var); 339 if (value == null) return "null"; 340 if (value instanceof koala.dynamicjava.interpreter.UninitializedObject) return null; 341 return _processReturnValue(value); 342 } 343 catch (IllegalStateException e) { return null; } } 345 return null; 346 } 347 348 351 public synchronized String getVariableClassName(String var) throws RemoteException { 352 Interpreter i = _activeInterpreter.getInterpreter(); 354 if (i instanceof JavaInterpreter) { 355 try { 356 Class c = ((JavaInterpreter)i).getVariableClass(var); 357 if (c == null) return "null"; 358 else return c.getName(); 359 } 360 catch (IllegalStateException e) { 361 return null; 363 } 364 } 365 else return null; 366 } 367 368 372 public synchronized void addJavaInterpreter(String name) { 373 JavaInterpreter interpreter = new DynamicJavaAdapter(_classPathManager); 374 _updateInterpreterClassPath(interpreter); 376 addInterpreter(name, interpreter); 377 } 378 379 384 public synchronized void addDebugInterpreter(String name, String className) { 385 JavaDebugInterpreter interpreter = new JavaDebugInterpreter(name, className); 386 interpreter.setPrivateAccessible(true); 387 _updateInterpreterClassPath(interpreter); 389 addInterpreter(name, interpreter); 390 } 391 392 397 public synchronized void addInterpreter(String name, Interpreter interpreter) { 398 if (_interpreters.containsKey(name)) { 399 throw new IllegalArgumentException ("'" + name + "' is not a unique interpreter name"); 400 } 401 _interpreters.put(name, new InterpreterData(interpreter)); 402 } 403 404 408 public void removeInterpreter(String name) { _interpreters.remove(name); } 409 410 414 InterpreterData getInterpreter(String name) { 415 InterpreterData interpreter = _interpreters.get(name); 416 if (interpreter != null) return interpreter; 417 else throw new IllegalArgumentException ("Interpreter '" + name + "' does not exist."); 418 } 419 420 425 public synchronized JavaInterpreter getJavaInterpreter(String name) { 426 if (printMessages) System.out.println("Getting interpreter data"); 427 InterpreterData interpreterData = getInterpreter(name); 428 if (printMessages) System.out.println("Getting interpreter instance"); 429 Interpreter interpreter = interpreterData.getInterpreter(); 430 if (printMessages) System.out.println("returning"); 431 432 if (interpreter instanceof JavaInterpreter) return (JavaInterpreter) interpreter; 433 else { 434 throw new IllegalArgumentException ("Interpreter '" + name + "' is not a JavaInterpreter."); 435 } 436 } 437 438 439 443 public synchronized boolean setActiveInterpreter(String name) { 444 _activeInterpreter = getInterpreter(name); 445 return _activeInterpreter.inProgress(); 446 } 447 448 451 public synchronized boolean setToDefaultInterpreter() { 452 _activeInterpreter = _defaultInterpreter; 453 return _activeInterpreter.inProgress(); 454 } 455 456 459 Hashtable <String ,InterpreterData> getInterpreters() { return _interpreters; } 460 461 462 Interpreter getActiveInterpreter() { return _activeInterpreter.getInterpreter(); } 463 464 468 public static String getStackTrace(Throwable t) { 469 BufferedReader reader = new BufferedReader(new StringReader(StringOps.getStackTrace(t))); 471 472 LinkedList <String > traceItems = new LinkedList <String >(); 474 try { 475 reader.readLine(); 479 481 String s; 482 while ((s = reader.readLine()) != null) { 483 traceItems.add(s); 485 } 486 } 487 catch (IOException ioe) { 488 return "Unable to get stack trace"; 489 } 490 491 493 int index = -1; 495 for (int i = 0; i < traceItems.size(); i++) { 496 String item = traceItems.get(i); 497 item = item.trim(); 498 if (item.startsWith("at edu.rice.cs.drjava.") || item.startsWith("at koala.dynamicjava.")) { 499 index = i; 500 break; 501 } 502 } 503 504 if (index > -1) { 506 while (traceItems.size() > index) traceItems.removeLast(); 507 } 508 509 if (traceItems.isEmpty()) traceItems.add(EMPTY_TRACE_TEXT); 511 512 final StringBuilder buf = new StringBuilder (); 514 final ListIterator itor = traceItems.listIterator(); 515 final String newLine = System.getProperty("line.separator"); 516 boolean first = true; 517 while (itor.hasNext()) { 518 if (first) first = false; else buf.append(newLine); 519 520 buf.append(" " + ((String ) itor.next()).trim()); 521 } 522 523 return buf.toString(); 524 } 525 526 528 529 public void setPackageScope(String s) { 530 Interpreter active = _activeInterpreter.getInterpreter(); 531 if (active instanceof JavaInterpreter) { 532 ((JavaInterpreter)active).setPackageScope(s); 533 } 534 } 535 536 537 public void setShowMessageOnResetFailure(boolean show) { _messageOnResetFailure = show; } 538 539 540 protected void quitFailed(Throwable th) { if (_messageOnResetFailure) { 542 String msg = "The interactions pane could not be reset:\n" + th; 543 javax.swing.JOptionPane.showMessageDialog(null, msg); 544 } 545 546 try { _mainJVM.quitFailed(th); } 547 catch (RemoteException re) { 548 _log.log("quitFailed: " + re.toString()); 550 } 551 } 552 553 554 public synchronized void setPrivateAccessible(boolean allow) { 555 Interpreter active = _activeInterpreter.getInterpreter(); 556 if (active instanceof JavaInterpreter) { 557 ((JavaInterpreter)active).setPrivateAccessible(allow); 558 } 559 } 560 561 568 public List <String > findTestClasses(List <String > classNames, List <File> files) throws RemoteException { 569 return _junitTestManager.findTestClasses(classNames, files); 571 } 572 573 577 public boolean runTestSuite() throws RemoteException { 578 return _junitTestManager.runTestSuite(); 580 } 581 582 586 public void nonTestCase(boolean isTestAll) { 587 try { _mainJVM.nonTestCase(isTestAll); } 588 catch (RemoteException re) { 589 _log.log("nonTestCase: " + re.toString()); 591 } 592 } 593 594 598 public void classFileError(ClassFileError e) { 599 try { _mainJVM.classFileError(e); } 600 catch (RemoteException re) { 601 _log.log("classFileError: " + re.toString()); 603 } 604 } 605 606 610 public void testSuiteStarted(int numTests) { 611 try { _mainJVM.testSuiteStarted(numTests); } 612 catch (RemoteException re) { 613 _log.log("testSuiteStarted: " + re.toString()); 615 } 616 } 617 618 622 public void testStarted(String testName) { 623 try { _mainJVM.testStarted(testName); } 624 catch (RemoteException re) { 625 _log.log("testStarted" + re.toString()); 627 } 628 } 629 630 635 public void testEnded(String testName, boolean wasSuccessful, boolean causedError) { 636 try { _mainJVM.testEnded(testName, wasSuccessful, causedError); } 637 catch (RemoteException re) { 638 _log.log("testEnded: " + re.toString()); 640 } 641 } 642 643 647 public void testSuiteEnded(JUnitError[] errors) { 648 try { _mainJVM.testSuiteEnded(errors); } 649 catch (RemoteException re) { 650 _log.log("testSuiteFinished: " + re.toString()); 652 } 653 } 654 655 660 public File getFileForClassName(String className) { 661 try { return _mainJVM.getFileForClassName(className); } 662 catch (RemoteException re) { 663 _log.log("getFileForClassName: " + re.toString()); 665 return null; 666 } 667 } 668 669 public void junitJVMReady() { } 670 671 675 678 protected void _updateInterpreterClassPath(JavaInterpreter interpreter) { 679 680 for (ClassPathEntry e: _classPathManager.getProjectCP()) 681 interpreter.addProjectClassPath(e.getEntry()); 682 683 for (ClassPathEntry e: _classPathManager.getBuildDirectoryCP()) 684 interpreter.addBuildDirectoryClassPath(e.getEntry()); 685 686 for (ClassPathEntry e: _classPathManager.getProjectFilesCP()) 687 interpreter.addProjectFilesClassPath(e.getEntry()); 688 689 for (ClassPathEntry e: _classPathManager.getExternalFilesCP()) 690 interpreter.addExternalFilesClassPath(e.getEntry()); 691 692 for (ClassPathEntry e: _classPathManager.getExtraCP()) 693 interpreter.addExtraClassPath(e.getEntry()); 694 } 695 696 700 public synchronized void addExtraClassPath(URL s) { 701 if (_classPath.contains(s)) return; 704 if (_defaultInterpreter.getInterpreter() instanceof JavaInterpreter) { 706 ((JavaInterpreter)_defaultInterpreter.getInterpreter()).addExtraClassPath(s); 707 } 708 709 Enumeration <InterpreterData> interpreters = _interpreters.elements(); 711 while (interpreters.hasMoreElements()) { 712 Interpreter interpreter = interpreters.nextElement().getInterpreter(); 713 if (interpreter instanceof JavaInterpreter) { 714 ((JavaInterpreter)interpreter).addExtraClassPath(s); 715 } 716 } 717 718 _classPath.add(s); 720 } 721 722 726 public synchronized void addProjectClassPath(URL s) { 727 if (_classPath.contains(s)) return; 730 if (_defaultInterpreter.getInterpreter() instanceof JavaInterpreter) { 732 ((JavaInterpreter)_defaultInterpreter.getInterpreter()).addProjectClassPath(s); 733 } 734 735 Enumeration <InterpreterData> interpreters = _interpreters.elements(); 737 while (interpreters.hasMoreElements()) { 738 Interpreter interpreter = interpreters.nextElement().getInterpreter(); 739 if (interpreter instanceof JavaInterpreter) { 740 ((JavaInterpreter)interpreter).addProjectClassPath(s); 741 } 742 } 743 744 _classPath.add(s); 746 } 747 748 752 public synchronized void addBuildDirectoryClassPath(URL s) { 753 if (_classPath.contains(s)) return; 756 if (_defaultInterpreter.getInterpreter() instanceof JavaInterpreter) { 758 ((JavaInterpreter)_defaultInterpreter.getInterpreter()).addBuildDirectoryClassPath(s); 759 } 760 761 Enumeration <InterpreterData> interpreters = _interpreters.elements(); 763 while (interpreters.hasMoreElements()) { 764 Interpreter interpreter = interpreters.nextElement().getInterpreter(); 765 if (interpreter instanceof JavaInterpreter) { 766 ((JavaInterpreter)interpreter).addBuildDirectoryClassPath(s); 767 } 768 } 769 770 _classPath.add(s); 772 } 773 774 775 779 public synchronized void addProjectFilesClassPath(URL s) { 780 if (_classPath.contains(s)) return; 783 if (_defaultInterpreter.getInterpreter() instanceof JavaInterpreter) { 785 ((JavaInterpreter)_defaultInterpreter.getInterpreter()).addProjectFilesClassPath(s); 786 } 787 788 Enumeration <InterpreterData> interpreters = _interpreters.elements(); 790 while (interpreters.hasMoreElements()) { 791 Interpreter interpreter = interpreters.nextElement().getInterpreter(); 792 if (interpreter instanceof JavaInterpreter) { 793 ((JavaInterpreter)interpreter).addProjectFilesClassPath(s); 794 } 795 } 796 797 _classPath.add(s); 799 } 800 801 805 public synchronized void addExternalFilesClassPath(URL s) { 806 if (_classPath.contains(s)) return; 809 if (_defaultInterpreter.getInterpreter() instanceof JavaInterpreter) { 811 ((JavaInterpreter)_defaultInterpreter.getInterpreter()).addExternalFilesClassPath(s); 812 } 813 814 Enumeration <InterpreterData> interpreters = _interpreters.elements(); 816 while (interpreters.hasMoreElements()) { 817 Interpreter interpreter = interpreters.nextElement().getInterpreter(); 818 if (interpreter instanceof JavaInterpreter) { 819 ((JavaInterpreter)interpreter).addExternalFilesClassPath(s); 820 } 821 } 822 823 _classPath.add(s); 825 } 826 827 831 public synchronized ClassPathVector getAugmentedClassPath() { 832 ClassPathVector ret = new ClassPathVector(); 833 834 for (ClassPathEntry e: _classPathManager.getProjectCP()) ret.add(e.getEntry().toString()); 835 836 for (ClassPathEntry e: _classPathManager.getBuildDirectoryCP()) 837 ret.add(e.getEntry().toString()); 838 839 for (ClassPathEntry e: _classPathManager.getProjectFilesCP()) 840 ret.add(e.getEntry().toString()); 841 842 for (ClassPathEntry e: _classPathManager.getExternalFilesCP()) 843 ret.add(e.getEntry().toString()); 844 845 for (ClassPathEntry e: _classPathManager.getExtraCP()) 846 ret.add(e.getEntry().toString()); 847 848 return ret; 849 } 850 851 855 public void addExtraClassPath(String s) { 856 try { addExtraClassPath(new URL (s)); } 857 catch(MalformedURLException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 858 } 859 860 public void addProjectClassPath(String s) { 861 try { addProjectClassPath(new URL (s)); } 862 catch(MalformedURLException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 863 } 864 865 public void addBuildDirectoryClassPath(String s) { 866 try { addBuildDirectoryClassPath(new URL (s)); } 867 catch(MalformedURLException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 868 } 869 870 public void addProjectFilesClassPath(String s) { 871 try { addProjectFilesClassPath(new URL (s)); } 872 catch(MalformedURLException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 873 } 874 875 public void addExternalFilesClassPath(String s) { 876 try { addExternalFilesClassPath(new URL (s)); } 877 catch(MalformedURLException e) { throw new edu.rice.cs.util.UnexpectedException(e); } 878 } 879 880 884 public synchronized ClassPathVector getClassPath() { 885 ClassPathVector ret = new ClassPathVector(); 886 887 for (ClassPathEntry e: _classPathManager.getProjectCP()) ret.add(e.getEntry()); 888 889 for (ClassPathEntry e: _classPathManager.getBuildDirectoryCP()) ret.add(e.getEntry()); 890 891 for (ClassPathEntry e: _classPathManager.getProjectFilesCP()) ret.add(e.getEntry()); 892 893 for (ClassPathEntry e: _classPathManager.getExternalFilesCP()) ret.add(e.getEntry()); 894 895 for (ClassPathEntry e: _classPathManager.getExtraCP()) ret.add(e.getEntry()); 896 897 return ret; 898 } 899 } 900 901 902 class InterpreterData { 903 protected final Interpreter _interpreter; 904 protected volatile boolean _inProgress; 905 906 InterpreterData(Interpreter interpreter) { 907 _interpreter = interpreter; 908 _inProgress = false; 909 } 910 911 913 914 public Interpreter getInterpreter() { return _interpreter; } 915 916 917 public boolean inProgress() { return _inProgress; } 918 919 920 public void setInProgress(boolean inProgress) { _inProgress = inProgress; } 921 } 922 | Popular Tags |