Source Code Cross Referenced for MainJVM.java in  » IDE » DrJava » edu » rice » cs » drjava » model » repl » newjvm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE » DrJava » edu.rice.cs.drjava.model.repl.newjvm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*BEGIN_COPYRIGHT_BLOCK
0002:         *
0003:         * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
0004:         * All rights reserved.
0005:         * 
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions are met:
0008:         *    * Redistributions of source code must retain the above copyright
0009:         *      notice, this list of conditions and the following disclaimer.
0010:         *    * Redistributions in binary form must reproduce the above copyright
0011:         *      notice, this list of conditions and the following disclaimer in the
0012:         *      documentation and/or other materials provided with the distribution.
0013:         *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
0014:         *      names of its contributors may be used to endorse or promote products
0015:         *      derived from this software without specific prior written permission.
0016:         * 
0017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0018:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0019:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0020:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0021:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0022:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0023:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0024:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0025:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0026:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0027:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0028:         *
0029:         * This software is Open Source Initiative approved Open Source Software.
0030:         * Open Source Initative Approved is a trademark of the Open Source Initiative.
0031:         * 
0032:         * This file is part of DrJava.  Download the current version of this project
0033:         * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
0034:         * 
0035:         * END_COPYRIGHT_BLOCK*/
0036:
0037:        package edu.rice.cs.drjava.model.repl.newjvm;
0038:
0039:        import java.rmi.*;
0040:        import java.io.*;
0041:        import java.net.MalformedURLException;
0042:
0043:        import java.util.List;
0044:        import java.util.ArrayList;
0045:
0046:        // NOTE: Do NOT import/use the config framework in this class!
0047:        //  (It seems to crash Eclipse...)
0048:        import edu.rice.cs.drjava.DrJava;
0049:        import edu.rice.cs.drjava.config.OptionConstants;
0050:        import edu.rice.cs.drjava.model.GlobalModel;
0051:        import edu.rice.cs.drjava.model.repl.*;
0052:        import edu.rice.cs.drjava.model.junit.JUnitError;
0053:        import edu.rice.cs.drjava.model.junit.JUnitModelCallback;
0054:        import edu.rice.cs.drjava.model.debug.DebugModelCallback;
0055:
0056:        import edu.rice.cs.util.ArgumentTokenizer;
0057:        import edu.rice.cs.util.FileOps;
0058:        import edu.rice.cs.util.Log;
0059:        import edu.rice.cs.util.StringOps;
0060:        import edu.rice.cs.util.UnexpectedException;
0061:        import edu.rice.cs.plt.io.IOUtil;
0062:        import edu.rice.cs.plt.iter.IterUtil;
0063:
0064:        import edu.rice.cs.util.newjvm.*;
0065:        import edu.rice.cs.util.classloader.ClassFileError;
0066:        import edu.rice.cs.util.swing.Utilities;
0067:        import edu.rice.cs.util.swing.ScrollableDialog;
0068:        import koala.dynamicjava.parser.wrapper.*;
0069:
0070:        import static edu.rice.cs.plt.debug.DebugUtil.debug;
0071:
0072:        /** Manages a remote JVM.
0073:         *  @version $Id: MainJVM.java 4255 2007-08-28 19:17:37Z mgricken $
0074:         */
0075:        public class MainJVM extends AbstractMasterJVM implements 
0076:                MainJVMRemoteI {
0077:            /** Name of the class to use in the remote JVM. */
0078:            private static final String SLAVE_CLASS_NAME = "edu.rice.cs.drjava.model.repl.newjvm.InterpreterJVM";
0079:
0080:            public static final String DEFAULT_INTERPRETER_NAME = "DEFAULT";
0081:
0082:            // _log is inherited from AbstractMasterJVM
0083:
0084:            /** Working directory for slave JVM */
0085:            private volatile File _workDir;
0086:
0087:            /** Listens to interactions-related events. */
0088:            private volatile InteractionsModelCallback _interactionsModel;
0089:
0090:            /** Listens to JUnit-related events. */
0091:            private volatile JUnitModelCallback _junitModel;
0092:
0093:            /** Listens to debug-related events */
0094:            private volatile DebugModelCallback _debugModel;
0095:
0096:            /** Used to protect interpreterJVM setting */
0097:            private final Object _interpreterLock = new Object();
0098:
0099:            /** Records state of slaveJVM (interpreterJVM); used to suppress restartInteractions on a fresh JVM */
0100:            private volatile boolean _slaveJVMUsed = false;
0101:
0102:            /** This flag is set to false to inhibit the automatic restart of the JVM. */
0103:            private volatile boolean _restart = true;
0104:
0105:            /** This flag is set to remember that the JVM is cleanly restarting, so that the replCalledSystemExit method
0106:             *  does not need to be called.
0107:             */
0108:            private volatile boolean _cleanlyRestarting = false;
0109:
0110:            /** Number of previous attempts to start slave JVM in this startup. */
0111:            private volatile int _numAttempts = 0;
0112:
0113:            /** Number of slave startup failures allowed before aborting the startup process. */
0114:            private static final int MAX_COUNT = 3;
0115:
0116:            /** Instance of inner class to handle interpret result. */
0117:            private final ResultHandler _handler = new ResultHandler();
0118:
0119:            /** Whether to allow "assert" statements to run in the remote JVM. */
0120:            private volatile boolean _allowAssertions = false;
0121:
0122:            /** Classpath to use for starting the interpreter JVM */
0123:            private volatile Iterable<File> _startupClassPath;
0124:
0125:            /** A list of user-defined arguments to pass to the interpreter. */
0126:            private volatile List<String> _optionArgs;
0127:
0128:            /** The name of the current interpreter. */
0129:            private volatile String _currentInterpreterName = DEFAULT_INTERPRETER_NAME;
0130:
0131:            /** Creates a new MainJVM to interface to another JVM;  the MainJVM has a link to the partially initialized 
0132:             *  global model.  The MainJVM but does not automatically start the Interpreter JVM.  Callers must set the
0133:             *  InteractionsModel and JUnitModel and then call startInterpreterJVM().
0134:             */
0135:            public MainJVM(File wd) throws RemoteException {
0136:                super (SLAVE_CLASS_NAME);
0137:                //    Utilities.show("Starting the slave JVM");
0138:                _workDir = wd;
0139:                _waitForQuitThreadName = "Wait for Interactions to Exit Thread";
0140:                //    _exportMasterThreadName = "Export DrJava to RMI Thread";
0141:
0142:                _interactionsModel = new DummyInteractionsModel();
0143:                _junitModel = new DummyJUnitModel();
0144:                _debugModel = new DummyDebugModel();
0145:                _startupClassPath = GlobalModel.RUNTIME_CLASS_PATH;
0146:                _optionArgs = new ArrayList<String>();
0147:            }
0148:
0149:            public boolean isInterpreterRunning() {
0150:                return _interpreterJVM() != null;
0151:            }
0152:
0153:            public boolean slaveJVMUsed() {
0154:                return _slaveJVMUsed;
0155:            }
0156:
0157:            /** Provides an object to listen to interactions-related events. */
0158:            public void setInteractionsModel(InteractionsModelCallback model) {
0159:                _interactionsModel = model;
0160:            }
0161:
0162:            /** Provides an object to listen to test-related events.*/
0163:            public void setJUnitModel(JUnitModelCallback model) {
0164:                _junitModel = model;
0165:            }
0166:
0167:            /** Provides an object to listen to debug-related events.
0168:             *  @param model the debug model
0169:             */
0170:            public void setDebugModel(DebugModelCallback model) {
0171:                _debugModel = model;
0172:            }
0173:
0174:            /** Sets whether the remote JVM will run "assert" statements after the next restart. */
0175:            public void setAllowAssertions(boolean allow) {
0176:                _allowAssertions = allow;
0177:            }
0178:
0179:            /** Sets the extra (optional) arguments to be passed to the interpreter.
0180:             *  @param argString the arguments as they would be typed at the command-line
0181:             */
0182:            public void setOptionArgs(String argString) {
0183:                _optionArgs = ArgumentTokenizer.tokenize(argString);
0184:            }
0185:
0186:            /** Interprets string s in slave JVM.  No masterJVMLock synchronization because reading _restart is the only
0187:             *  access.to master JVM state. */
0188:            public void interpret(final String s) {
0189:                // silently fail if disabled. see killInterpreter docs for details.
0190:                if (!_restart)
0191:                    return;
0192:
0193:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0194:
0195:                // Spawn thread on InterpreterJVM side
0196:                //  (will receive result in the interpretResult(...) method)
0197:                try {
0198:                    _log.log(this  + ".interpret(" + s + ")");
0199:                    _slaveJVMUsed = true;
0200:                    _interactionsModel.slaveJVMUsed();
0201:                    slave.interpret(s);
0202:                } catch (java.rmi.UnmarshalException ume) {
0203:                    // Could not receive result from interpret; system probably exited.
0204:                    // We will silently fail and let the interpreter restart.
0205:                    _log
0206:                            .log(this 
0207:                                    + ".interpret threw UnmarshalException, so interpreter is dead:\n"
0208:                                    + ume);
0209:                } catch (RemoteException re) {
0210:                    _threwException(re);
0211:                }
0212:            }
0213:
0214:            /** Gets the string representation of the value of a variable in the current interpreter.
0215:             *  @param var the name of the variable
0216:             */
0217:            public String getVariableToString(String var) {
0218:                // silently fail if disabled. see killInterpreter docs for details.
0219:                if (!_restart)
0220:                    return null;
0221:
0222:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0223:
0224:                try {
0225:                    return slave.getVariableToString(var);
0226:                } catch (RemoteException re) {
0227:                    _threwException(re);
0228:                    return null;
0229:                }
0230:            }
0231:
0232:            /** Gets the class name of a variable in the current interpreter.
0233:             *  @param var the name of the variable
0234:             */
0235:            public String getVariableClassName(String var) {
0236:                // silently fail if disabled. see killInterpreter docs for details.
0237:                if (!_restart)
0238:                    return null;
0239:
0240:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0241:
0242:                try {
0243:                    return slave.getVariableClassName(var);
0244:                } catch (RemoteException re) {
0245:                    _threwException(re);
0246:                    return null;
0247:                }
0248:            }
0249:
0250:            /** Called when a call to interpret has completed.
0251:             *  @param result The result of the interpretation
0252:             */
0253:            public void interpretResult(InterpretResult result)
0254:                    throws RemoteException {
0255:                try {
0256:                    _log.log(this  + ".interpretResult(" + result + ")");
0257:                    result.apply(getResultHandler());
0258:                } catch (Throwable t) {
0259:                    _log.log(this  + "interpretResult threw " + t.toString());
0260:                }
0261:            }
0262:
0263:            //  /**
0264:            //   * Adds a single path to the Interpreter's class path.
0265:            //   * This method <b>cannot</b> take multiple paths separated by
0266:            //   * a path separator; it must be called separately for each path.
0267:            //   * @param path Path to be added to classpath
0268:            //   */
0269:            //  public void addClassPath(String path) {
0270:            //    // silently fail if disabled. see killInterpreter docs for details.
0271:            //    if (! _restart) return;
0272:            //    
0273:            //    ensureInterpreterConnected();
0274:            //    
0275:            //    try {
0276:            //      //      System.err.println("addclasspath to " + _interpreterJVM() + ": " + path);
0277:            //      //      System.err.println("full classpath: " + getClasspath());
0278:            //      _interpreterJVM().addClassPath(path);
0279:            //    }
0280:            //    catch (RemoteException re) {
0281:            //      _threwException(re);
0282:            //    }
0283:            //  }
0284:
0285:            public void addProjectClassPath(File f) {
0286:                if (!_restart)
0287:                    return;
0288:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0289:
0290:                try {
0291:                    slave.addProjectClassPath(f);
0292:                } catch (RemoteException re) {
0293:                    _threwException(re);
0294:                }
0295:            }
0296:
0297:            public void addBuildDirectoryClassPath(File f) {
0298:                if (!_restart)
0299:                    return;
0300:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0301:
0302:                try {
0303:                    slave.addBuildDirectoryClassPath(f);
0304:                } catch (RemoteException re) {
0305:                    _threwException(re);
0306:                }
0307:            }
0308:
0309:            public void addProjectFilesClassPath(File f) {
0310:                if (!_restart)
0311:                    return;
0312:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0313:
0314:                try {
0315:                    slave.addProjectFilesClassPath(f);
0316:                } catch (RemoteException re) {
0317:                    _threwException(re);
0318:                }
0319:            }
0320:
0321:            public void addExternalFilesClassPath(File f) {
0322:                if (!_restart)
0323:                    return;
0324:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0325:
0326:                try {
0327:                    slave.addExternalFilesClassPath(f);
0328:                } catch (RemoteException re) {
0329:                    _threwException(re);
0330:                }
0331:            }
0332:
0333:            public void addExtraClassPath(File f) {
0334:                if (!_restart)
0335:                    return;
0336:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0337:
0338:                try {
0339:                    slave.addExtraClassPath(f);
0340:                } catch (RemoteException re) {
0341:                    _threwException(re);
0342:                }
0343:            }
0344:
0345:            /** Returns the current classpath of the interpreter as a list of
0346:             *  unique entries.  The list is empty if a remote exception occurs.
0347:             */
0348:            public Iterable<File> getClassPath() {
0349:                // silently fail if disabled. see killInterpreter docs for details.
0350:                if (_restart) {
0351:
0352:                    InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0353:
0354:                    try {
0355:                        return IterUtil.compose(slave.getAugmentedClassPath(),
0356:                                _startupClassPath);
0357:                    } catch (RemoteException re) {
0358:                        _threwException(re);
0359:                        return IterUtil.empty();
0360:                    }
0361:                } else {
0362:                    return IterUtil.empty();
0363:                }
0364:            }
0365:
0366:            /** Sets the Interpreter to be in the given package.
0367:             *  @param packageName Name of the package to enter.
0368:             */
0369:            public void setPackageScope(String packageName) {
0370:                // silently fail if disabled. see killInterpreter docs for details.
0371:                if (!_restart)
0372:                    return;
0373:
0374:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0375:
0376:                try {
0377:                    slave.setPackageScope(packageName);
0378:                } catch (RemoteException re) {
0379:                    _threwException(re);
0380:                }
0381:            }
0382:
0383:            /** @param show Whether to show a message if a reset operation fails. */
0384:            public void setShowMessageOnResetFailure(boolean show) {
0385:                // silently fail if disabled. see killInterpreter docs for details.
0386:                if (!_restart)
0387:                    return;
0388:
0389:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0390:
0391:                try {
0392:                    slave.setShowMessageOnResetFailure(show);
0393:                } catch (RemoteException re) {
0394:                    _threwException(re);
0395:                }
0396:            }
0397:
0398:            /** Forwards a call to System.err from InterpreterJVM to the local InteractionsModel.
0399:             *  @param s String that was printed in the other JVM
0400:             */
0401:            public void systemErrPrint(String s) throws RemoteException {
0402:                _interactionsModel.replSystemErrPrint(s);
0403:            }
0404:
0405:            /** Forwards a call to System.out from InterpreterJVM to the local InteractionsModel.
0406:             *  @param s String that was printed in the other JVM
0407:             */
0408:            public void systemOutPrint(String s) throws RemoteException {
0409:                _interactionsModel.replSystemOutPrint(s);
0410:            }
0411:
0412:            /** Sets up a JUnit test suite in the Interpreter JVM and finds which classes are really TestCases
0413:             *  classes (by loading them)
0414:             *  @param classNames the class names to run in a test
0415:             *  @param files the associated file
0416:             *  @return the class names that are actually test cases
0417:             */
0418:            public List<String> findTestClasses(List<String> classNames,
0419:                    List<File> files) throws RemoteException {
0420:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0421:                return slave.findTestClasses(classNames, files);
0422:            }
0423:
0424:            /** Runs the JUnit test suite already cached in the Interpreter JVM.
0425:             *  @return false if no test suite is cached; true otherwise
0426:             */
0427:            public boolean runTestSuite() throws RemoteException {
0428:                return _interpreterJVM().runTestSuite();
0429:            }
0430:
0431:            /** Called if JUnit is invoked on a non TestCase class.  Forwards from the other JVM to the local JUnit model.
0432:             *  @param isTestAll whether or not it was a use of the test all button
0433:             */
0434:            public void nonTestCase(boolean isTestAll) throws RemoteException {
0435:                _junitModel.nonTestCase(isTestAll);
0436:            }
0437:
0438:            /** Called if the slave JVM encounters an illegal class file in testing.  Forwards from
0439:             *  the other JVM to the local JUnit model.
0440:             *  @param e the ClassFileError describing the error when loading the class file
0441:             */
0442:            public void classFileError(ClassFileError e) throws RemoteException {
0443:                //    Utilities.showDebug("classFileError(" + e + ") called in MainJVM");
0444:                _junitModel.classFileError(e);
0445:            }
0446:
0447:            /** Called to indicate that a suite of tests has started running.
0448:             *  Forwards from the other JVM to the local JUnit model.
0449:             *  @param numTests The number of tests in the suite to be run.
0450:             */
0451:            public void testSuiteStarted(int numTests) throws RemoteException {
0452:                _slaveJVMUsed = true;
0453:                //    Utilities.show("MainJVM.testSuiteStarted(" + numTests + ") called");
0454:                _interactionsModel.slaveJVMUsed();
0455:                _junitModel.testSuiteStarted(numTests);
0456:            }
0457:
0458:            /** Called when a particular test is started.  Forwards from the slave JVM to the local JUnit model.
0459:             *  @param testName The name of the test being started.
0460:             */
0461:            public void testStarted(String testName) throws RemoteException {
0462:                //    Utilities.show("MainJVM.testStarted(" + testName + ") called");
0463:                _slaveJVMUsed = true;
0464:                //     Utilities.show("MainJVM.testStarted(" + testName + ") called");
0465:                _junitModel.testStarted(testName);
0466:            }
0467:
0468:            /** Called when a particular test has ended. Forwards from the other JVM to the local JUnit model.
0469:             *  @param testName The name of the test that has ended.
0470:             *  @param wasSuccessful Whether the test passed or not.
0471:             *  @param causedError If not successful, whether the test caused an error or simply failed.
0472:             */
0473:            public void testEnded(String testName, boolean wasSuccessful,
0474:                    boolean causedError) throws RemoteException {
0475:                _junitModel.testEnded(testName, wasSuccessful, causedError);
0476:            }
0477:
0478:            /** Called when a full suite of tests has finished running. Forwards from the other JVM to the local JUnit model.
0479:             *  @param errors The array of errors from all failed tests in the suite.
0480:             */
0481:            public void testSuiteEnded(JUnitError[] errors)
0482:                    throws RemoteException {
0483:                //    Utilities.showDebug("MainJVM.testSuiteEnded() called");
0484:                _junitModel.testSuiteEnded(errors);
0485:            }
0486:
0487:            /** Called when the JUnitTestManager wants to open a file that is not currently open.
0488:             *  @param className the name of the class for which we want to find the file
0489:             *  @return the file associated with the given class
0490:             */
0491:            public File getFileForClassName(String className)
0492:                    throws RemoteException {
0493:                return _junitModel.getFileForClassName(className);
0494:            }
0495:
0496:            /** Notifies the main jvm that an assignment has been made in the given debug interpreter.
0497:             *  Does not notify on declarations.
0498:             *
0499:             *  This method is not currently necessary, since we don't copy back values in a debug interpreter until the thread
0500:             *  has resumed.
0501:             *
0502:             * @param name the name of the debug interpreter
0503:             *
0504:             public void notifyDebugInterpreterAssignment(String name) {
0505:             }*/
0506:
0507:            /**Accessor for the remote interface to the Interpreter JVM; _slave is protected field of the supserclass. */
0508:            private InterpreterJVMRemoteI _interpreterJVM() {
0509:                return (InterpreterJVMRemoteI) _slave;
0510:            }
0511:
0512:            //  /** Updates the security manager in slave JVM */
0513:            //  public void enableSecurityManager() throws RemoteException {
0514:            //    _interpreterJVM().enableSecurityManager();
0515:            //  }
0516:            //  
0517:            //  /** Updates the security manager in slave JVM */
0518:            //  public void disableSecurityManager() throws RemoteException{
0519:            //    _interpreterJVM().disableSecurityManager();
0520:            //  }
0521:
0522:            /** Adds a named DynamicJavaAdapter to the list of interpreters.
0523:             *  @param name the unique name for the interpreter
0524:             *  @throws IllegalArgumentException if the name is not unique
0525:             */
0526:            public void addJavaInterpreter(String name) {
0527:                // silently fail if disabled. see killInterpreter docs for details.
0528:                if (!_restart)
0529:                    return;
0530:
0531:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0532:
0533:                try {
0534:                    slave.addJavaInterpreter(name);
0535:                } catch (RemoteException re) {
0536:                    _threwException(re);
0537:                }
0538:            }
0539:
0540:            /** Adds a named JavaDebugInterpreter to the list of interpreters.
0541:             *  @param name the unique name for the interpreter
0542:             *  @param className the fully qualified class name of the class the debug interpreter is in
0543:             *  @throws IllegalArgumentException if the name is not unique
0544:             */
0545:            public void addDebugInterpreter(String name, String className) {
0546:                // silently fail if disabled. see killInterpreter docs for details.
0547:                if (!_restart)
0548:                    return;
0549:
0550:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0551:
0552:                try {
0553:                    slave.addDebugInterpreter(name, className);
0554:                } catch (RemoteException re) {
0555:                    _threwException(re);
0556:                }
0557:            }
0558:
0559:            /** Removes the interpreter with the given name, if it exists.
0560:             *  @param name Name of the interpreter to remove
0561:             */
0562:            public void removeInterpreter(String name) {
0563:                // silently fail if disabled. see killInterpreter docs for details.
0564:                if (!_restart)
0565:                    return;
0566:
0567:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0568:
0569:                try {
0570:                    slave.removeInterpreter(name);
0571:                    if (name.equals(_currentInterpreterName))
0572:                        _currentInterpreterName = null;
0573:                } catch (RemoteException re) {
0574:                    _threwException(re);
0575:                }
0576:            }
0577:
0578:            /** Sets the current interpreter to the one specified by name
0579:             *  @param name the unique name of the interpreter to set active
0580:             *  @return Whether the new interpreter is currently processing an interaction (i.e., whether an interactionEnded
0581:             *          event will be fired)
0582:             */
0583:            public boolean setActiveInterpreter(String name) {
0584:                // silently fail if disabled. see killInterpreter docs for details.
0585:                if (!_restart)
0586:                    return false;
0587:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0588:
0589:                try {
0590:                    boolean result = slave.setActiveInterpreter(name);
0591:                    _currentInterpreterName = name;
0592:                    return result;
0593:                } catch (RemoteException re) {
0594:                    _threwException(re);
0595:                    return false;
0596:                }
0597:            }
0598:
0599:            /** Sets the default interpreter to be the current one.
0600:             *  @return Whether the new interpreter is currently in progress with an interaction (ie. whether an 
0601:             *          interactionEnded event will be fired)
0602:             */
0603:            public boolean setToDefaultInterpreter() {
0604:                // silently fail if disabled. see killInterpreter docs for details.
0605:                if (!_restart)
0606:                    return false;
0607:
0608:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0609:
0610:                try {
0611:                    boolean result = slave.setToDefaultInterpreter();
0612:                    _currentInterpreterName = DEFAULT_INTERPRETER_NAME;
0613:                    return result;
0614:                } catch (ConnectIOException ce) {
0615:                    _log
0616:                            .log(this 
0617:                                    + "could not connect to the interpreterJVM after killing it.  Threw "
0618:                                    + ce);
0619:                    return false;
0620:                } catch (RemoteException re) {
0621:                    _threwException(re);
0622:                    return false;
0623:                }
0624:            }
0625:
0626:            /** Accesses the cached current interpreter name. */
0627:            public String getCurrentInterpreterName() {
0628:                return _currentInterpreterName;
0629:            }
0630:
0631:            /** Kills the running interpreter JVM, and restarts with working directory wd if wd != null.  If wd == null, the
0632:             * interpreter is not restarted.  Note: If the interpreter is not restarted, all of the methods that delegate to the
0633:             * interpreter will silently fail!  Therefore, killing without restarting should be used with extreme care and only in 
0634:             * carefully controlled test cases or when DrJava is quitting anyway.
0635:             */
0636:
0637:            public void killInterpreter(File wd) {
0638:                boolean restart;
0639:                synchronized (_masterJVMLock) {
0640:                    _workDir = wd;
0641:                    _restart = (wd != null);
0642:                    _cleanlyRestarting = true;
0643:                    restart = _restart;
0644:                }
0645:
0646:                /* Dropping lock before performing operations on the interactions document/pane and making remote call. */
0647:                try {
0648:                    if (restart)
0649:                        _interactionsModel.interpreterResetting();
0650:                    quitSlave();
0651:                } // new slave JVM is restarted by call on startInterpreterJVM on death of current slave
0652:                catch (RemoteException e) {
0653:                    _log
0654:                            .log(this 
0655:                                    + "could not connect to the interpreterJVM while trying to kill it.  Threw "
0656:                                    + e);
0657:                }
0658:            }
0659:
0660:            /** Sets the classpath to use for starting the interpreter JVM. Must include the classes for the interpreter.
0661:             *  @param classPath Classpath for the interpreter JVM
0662:             */
0663:            public void setStartupClassPath(String classPath) {
0664:                _startupClassPath = IOUtil.attemptCanonicalFiles(IOUtil
0665:                        .parsePath(classPath));
0666:            }
0667:
0668:            /** Starts the interpreter if it's not running already. */
0669:            public void startInterpreterJVM() {
0670:                _log.log(this  + ".startInterpreterJVM() called");
0671:                //    synchronized(_masterJVMLock) {  // synch is unnecessary
0672:                if (isStartupInProgress() || isInterpreterRunning())
0673:                    return; // These predicates simply check volatile boolean flags
0674:                    //    }
0675:                // Pass assertion and debug port information as JVM arguments
0676:                ArrayList<String> jvmArgs = new ArrayList<String>();
0677:                if (allowAssertions())
0678:                    jvmArgs.add("-ea");
0679:                int debugPort = getDebugPort();
0680:                _log.log("Main JVM starting with debug port: " + debugPort);
0681:                if (debugPort > -1) {
0682:                    jvmArgs
0683:                            .add("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address="
0684:                                    + debugPort);
0685:                    jvmArgs.add("-Xdebug");
0686:                    jvmArgs.add("-Xnoagent");
0687:                    jvmArgs.add("-Djava.compiler=NONE");
0688:                }
0689:                // Cannot do the following line because it causes an error on Macs in the Eclipse plug-in.
0690:                // By instantiating the config, somehow the Apple JVM tries to start up AWT, which seems
0691:                // to be prohibited by Eclipse.  Badness ensues.
0692:                //    String optionArgString = DrJava.getConfig().getSetting(OptionConstants.JVM_ARGS);
0693:                //    List<String> optionArgs = ArgumentTokenizer.tokenize(optionArgString);
0694:                jvmArgs.addAll(_optionArgs);
0695:                String[] jvmArgsArray = new String[jvmArgs.size()];
0696:                for (int i = 0; i < jvmArgs.size(); i++) {
0697:                    jvmArgsArray[i] = jvmArgs.get(i);
0698:                }
0699:
0700:                // Create and invoke the Interpreter JVM
0701:                _numAttempts = 0;
0702:                try {
0703:                    // _startupClasspath is sent in as the interactions classpath
0704:                    //      Utilities.show("Calling invokeSlave(" + jvmArgs + ", " + _startupClassPath + ", " +  _workDir +")");
0705:                    invokeSlave(jvmArgsArray, IOUtil
0706:                            .pathToString(_startupClassPath), _workDir);
0707:                    _slaveJVMUsed = false;
0708:                } catch (RemoteException re) {
0709:                    _threwException(re);
0710:                } catch (IOException ioe) {
0711:                    _threwException(ioe);
0712:                }
0713:            }
0714:
0715:            /** React if the slave JVM quits.  Restarts the JVM unless _restart is false, and notifies the InteractionsModel
0716:             *  if the quit was unexpected.  Called from a thread within AbstractMasterJVM waiting for the death of the process
0717:             *  that starts and runs the slave JVM.
0718:             *  @param status Status returned by the dead process.
0719:             */
0720:            protected void handleSlaveQuit(int status) {
0721:                // Only restart the slave if _restart is true
0722:                //    Utilities.showDebug("MainJVM: slaveJVM has quit with status " + status + " _workDir = " + _workDir + 
0723:                //      " _cleanlyRestarting = " + _cleanlyRestarting);
0724:                if (_restart) {
0725:                    // We have already fired this event if we are cleanly restarting
0726:                    if (!_cleanlyRestarting)
0727:                        _interactionsModel.interpreterResetting();
0728:                    //      Utilities.showDebug("MainJVM: calling startInterpreterJVM()");
0729:                    startInterpreterJVM();
0730:                }
0731:
0732:                if (!_cleanlyRestarting)
0733:                    _interactionsModel.replCalledSystemExit(status);
0734:                _cleanlyRestarting = false;
0735:            }
0736:
0737:            /** Action to take if the slave JVM quits before registering.  Assumes _masterJVMLock is held.
0738:             *  @param status Status code of the JVM
0739:             *  TODO: revise the unit tests that kill the slave prematurely (by making them wait until the
0740:             *  slave registers) and remove the TEST_MODE escape.
0741:             */
0742:            protected void slaveQuitDuringStartup(int status) {
0743:                super .slaveQuitDuringStartup(status);
0744:                _numAttempts++; // no synchronization since this is the only place that _numAttempts is modified
0745:                if (Utilities.TEST_MODE || _numAttempts < MAX_COUNT)
0746:                    return; // Some tests kill the slave immediately after it starts.
0747:
0748:                // The slave JVM is not enabled after this to prevent an infinite loop of attempted startups
0749:                _restart = false;
0750:
0751:                // Signal that an internal error occurred
0752:                String msg = "Interpreter JVM exited before registering, status: "
0753:                        + status;
0754:                IllegalStateException e = new IllegalStateException(msg);
0755:                new edu.rice.cs.drjava.ui.DrJavaErrorHandler().handle(e);
0756:            }
0757:
0758:            /** Called if the slave JVM dies before it is able to register.
0759:             *  @param cause The Throwable which caused the slave to die.
0760:             */
0761:            public void errorStartingSlave(Throwable cause)
0762:                    throws RemoteException {
0763:                new edu.rice.cs.drjava.ui.DrJavaErrorHandler().handle(cause);
0764:            }
0765:
0766:            /** This method is called by the interpreter JVM if it cannot be exited.
0767:             *  @param th The Throwable thrown by System.exit
0768:             */
0769:            public void quitFailed(Throwable th) throws RemoteException {
0770:                _interactionsModel.interpreterResetFailed(th);
0771:                _cleanlyRestarting = false;
0772:            }
0773:
0774:            /** Returns whether a JVM is currently starting.  This override widens the visibility of the method. */
0775:            public boolean isStartupInProgress() {
0776:                return super .isStartupInProgress();
0777:            }
0778:
0779:            /** Called when Interpreter JVM connects to us after being started. Assumes that _masterJVMLock is already held. */
0780:            protected void handleSlaveConnected() {
0781:                // we reset the enabled flag since, unless told otherwise via
0782:                // killInterpreter(false), we want to automatically respawn
0783:                //    System.out.println("handleSlaveConnected() called in MainJVM");  // DEBUG
0784:                _restart = true;
0785:                _cleanlyRestarting = false;
0786:
0787:                Boolean allowAccess = DrJava.getConfig().getSetting(
0788:                        OptionConstants.ALLOW_PRIVATE_ACCESS);
0789:                setPrivateAccessible(allowAccess.booleanValue());
0790:
0791:                //    System.out.println("Calling interpreterReady(" + _workDir + ") called in MainJVM");  // DEBUG
0792:                _interactionsModel.interpreterReady(_workDir);
0793:                _junitModel.junitJVMReady();
0794:
0795:                _log.log("Main JVM Thread for slave connection is: "
0796:                        + Thread.currentThread());
0797:
0798:                // notify a thread that is waiting in ensureInterpreterConnected
0799:                synchronized (_interpreterLock) {
0800:                    _interpreterLock.notifyAll();
0801:                }
0802:            }
0803:
0804:            /** ReEnables restarting the slave if it has been turned off by repeated startup failures. */
0805:            public void enableRestart() {
0806:                _restart = true;
0807:            }
0808:
0809:            /** Returns the visitor to handle an InterpretResult. */
0810:            protected InterpretResultVisitor<Object> getResultHandler() {
0811:                return _handler;
0812:            }
0813:
0814:            /** Returns the debug port to use, as specified by the model. Returns -1 if no usable port could be found. */
0815:            protected int getDebugPort() {
0816:                int port = -1;
0817:                try {
0818:                    port = _interactionsModel.getDebugPort();
0819:                } catch (IOException ioe) {
0820:                    /* Can't find port; don't use debugger */
0821:                }
0822:                return port;
0823:            }
0824:
0825:            /** Return whether to allow assertions in the InterpreterJVM. */
0826:            protected boolean allowAssertions() {
0827:                String version = System.getProperty("java.version");
0828:                return (_allowAssertions && (version != null) && ("1.4.0"
0829:                        .compareTo(version) <= 0));
0830:            }
0831:
0832:            /** Lets the model know if any exceptions occur while communicating with the Interpreter JVM. */
0833:            private void _threwException(Throwable t) {
0834:                String shortMsg = null;
0835:                if ((t instanceof  ParseError)
0836:                        && ((ParseError) t).getParseException() != null)
0837:                    shortMsg = ((ParseError) t).getMessage(); // in this case, getMessage is equivalent to getShortMessage
0838:                _interactionsModel.replThrewException(t.getClass().getName(), t
0839:                        .getMessage(), StringOps.getStackTrace(t), shortMsg);
0840:                ;
0841:            }
0842:
0843:            /** Sets the interpreter to allow access to private members. TODO: synchronize? */
0844:            public void setPrivateAccessible(boolean allow) {
0845:                // silently fail if disabled. see killInterpreter docs for details.
0846:                if (!_restart)
0847:                    return;
0848:
0849:                InterpreterJVMRemoteI slave = ensureInterpreterConnected();
0850:                try {
0851:                    slave.setPrivateAccessible(allow);
0852:                } catch (RemoteException re) {
0853:                    _threwException(re);
0854:                }
0855:            }
0856:
0857:            /** If an interpreter has not registered itself, this method will block until one does.*/
0858:            public InterpreterJVMRemoteI ensureInterpreterConnected() {
0859:                //    _log.log("ensureInterpreterConnected called by Main JVM");
0860:                try {
0861:                    synchronized (_interpreterLock) {
0862:                        /* Now we silently fail if interpreter is disabled instead of throwing an exception. This situation
0863:                         * occurs only in test cases and when DrJava is about to quit. 
0864:                         */
0865:                        if (!_restart) {
0866:                            throw new IllegalStateException(
0867:                                    "Interpreter is disabled");
0868:                        }
0869:                        InterpreterJVMRemoteI slave = _interpreterJVM();
0870:                        while (slave == null) {
0871:                            //          _log.log("interpreter is null in Main JVM, waiting for it to register");
0872:                            _interpreterLock.wait();
0873:                            slave = _interpreterJVM();
0874:                        }
0875:
0876:                        //        _log.log("interpreter " + interp + " registered in Main JVM");
0877:                        return slave;
0878:                    }
0879:                } catch (InterruptedException ie) {
0880:                    throw new UnexpectedException(ie);
0881:                }
0882:            }
0883:
0884:            /** Asks the main jvm for input from the console.
0885:             * @return the console input
0886:             */
0887:            public String getConsoleInput() {
0888:                String s = _interactionsModel.getConsoleInput();
0889:                //    System.err.println("MainJVM.getConsoleInput() returns '" + s + "'");
0890:                return s;
0891:            }
0892:
0893:            /**
0894:             * Peforms the appropriate action to return any type of result
0895:             * from a call to interpret back to the GlobalModel.
0896:             */
0897:            private class ResultHandler implements 
0898:                    InterpretResultVisitor<Object> {
0899:                /** Lets the model know that void was returned.
0900:                 * @return null
0901:                 */
0902:                public Object forVoidResult(VoidResult that) {
0903:                    _interactionsModel.replReturnedVoid();
0904:                    return null;
0905:                }
0906:
0907:                /** Returns a value result (as a String) back to the model.
0908:                 *  @return null
0909:                 */
0910:                public Object forValueResult(ValueResult that) {
0911:                    String result = that.getValueStr();
0912:                    String style = that.getStyle();
0913:                    _interactionsModel.replReturnedResult(result, style);
0914:                    return null;
0915:                }
0916:
0917:                /** Returns an exception back to the model.
0918:                 *  @return null
0919:                 */
0920:                public Object forExceptionResult(ExceptionResult that) { /**/
0921:                    _interactionsModel.replThrewException(that
0922:                            .getExceptionClass(), that.getExceptionMessage(),
0923:                            that.getStackTrace(), that.getSpecialMessage());
0924:                    return null;
0925:                }
0926:
0927:                /** Indicates there was a syntax error to the model.
0928:                 *  @return null
0929:                 */
0930:                public Object forSyntaxErrorResult(SyntaxErrorResult that) {
0931:                    _interactionsModel.replReturnedSyntaxError(that
0932:                            .getErrorMessage(), that.getInteraction(), that
0933:                            .getStartRow(), that.getStartCol(), that
0934:                            .getEndRow(), that.getEndCol());
0935:                    return null;
0936:                }
0937:
0938:                public Object forInterpreterBusy(InterpreterBusy that) {
0939:                    throw new UnexpectedException(
0940:                            "MainJVM.interpret() called when InterpreterJVM was busy!");
0941:                }
0942:            }
0943:
0944:            /** InteractionsModel which does not react to events. */
0945:            public static class DummyInteractionsModel implements 
0946:                    InteractionsModelCallback {
0947:                public int getDebugPort() throws IOException {
0948:                    return -1;
0949:                }
0950:
0951:                public void replSystemOutPrint(String s) {
0952:                }
0953:
0954:                public void replSystemErrPrint(String s) {
0955:                }
0956:
0957:                public String getConsoleInput() {
0958:                    throw new IllegalStateException(
0959:                            "Cannot request input from dummy interactions model!");
0960:                }
0961:
0962:                public void setInputListener(InputListener il) {
0963:                    throw new IllegalStateException(
0964:                            "Cannot set the input listener of dummy interactions model!");
0965:                }
0966:
0967:                public void changeInputListener(InputListener from,
0968:                        InputListener to) {
0969:                    throw new IllegalStateException(
0970:                            "Cannot change the input listener of dummy interactions model!");
0971:                }
0972:
0973:                public void replReturnedVoid() {
0974:                }
0975:
0976:                public void replReturnedResult(String result, String style) {
0977:                }
0978:
0979:                public void replThrewException(String exceptionClass,
0980:                        String message, String stackTrace, String specialMessage) {
0981:                }
0982:
0983:                public void replReturnedSyntaxError(String errorMessage,
0984:                        String interaction, int startRow, int startCol,
0985:                        int endRow, int endCol) {
0986:                }
0987:
0988:                public void replCalledSystemExit(int status) {
0989:                }
0990:
0991:                public void interpreterResetting() {
0992:                }
0993:
0994:                public void interpreterResetFailed(Throwable th) {
0995:                }
0996:
0997:                public void interpreterReady(File wd) {
0998:                }
0999:
1000:                public void slaveJVMUsed() {
1001:                }
1002:            }
1003:
1004:            /** JUnitModel which does not react to events. */
1005:            public static class DummyJUnitModel implements  JUnitModelCallback {
1006:                public void nonTestCase(boolean isTestAll) {
1007:                }
1008:
1009:                public void classFileError(ClassFileError e) {
1010:                }
1011:
1012:                public void testSuiteStarted(int numTests) {
1013:                }
1014:
1015:                public void testStarted(String testName) {
1016:                }
1017:
1018:                public void testEnded(String testName, boolean wasSuccessful,
1019:                        boolean causedError) {
1020:                }
1021:
1022:                public void testSuiteEnded(JUnitError[] errors) {
1023:                }
1024:
1025:                public File getFileForClassName(String className) {
1026:                    return null;
1027:                }
1028:
1029:                public Iterable<File> getClassPath() {
1030:                    return IterUtil.empty();
1031:                }
1032:
1033:                public void junitJVMReady() {
1034:                }
1035:            }
1036:
1037:            /** DebugModelCallback which does not react to events. */
1038:            public static class DummyDebugModel implements  DebugModelCallback {
1039:                public void notifyDebugInterpreterAssignment(String name) {
1040:                }
1041:            }
1042:        }
w__w___w_.___j___ava_2___s.__co__m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.