langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java
changeset 42272 82e273c4f2b3
parent 41941 a935ac3f5274
child 42969 a48d4f74d322
equal deleted inserted replaced
42271:2537564a3031 42272:82e273c4f2b3
    28 import jdk.jshell.spi.ExecutionControl;
    28 import jdk.jshell.spi.ExecutionControl;
    29 import java.io.ByteArrayInputStream;
    29 import java.io.ByteArrayInputStream;
    30 import java.io.InputStream;
    30 import java.io.InputStream;
    31 import java.io.InterruptedIOException;
    31 import java.io.InterruptedIOException;
    32 import java.io.PrintStream;
    32 import java.io.PrintStream;
       
    33 import java.net.InetAddress;
    33 import java.text.MessageFormat;
    34 import java.text.MessageFormat;
    34 import java.util.ArrayList;
    35 import java.util.ArrayList;
    35 import java.util.Arrays;
    36 import java.util.Arrays;
    36 import java.util.Collections;
    37 import java.util.Collections;
    37 import java.util.HashMap;
    38 import java.util.HashMap;
    90     final PrintStream err;
    91     final PrintStream err;
    91     final Supplier<String> tempVariableNameGenerator;
    92     final Supplier<String> tempVariableNameGenerator;
    92     final BiFunction<Snippet, Integer, String> idGenerator;
    93     final BiFunction<Snippet, Integer, String> idGenerator;
    93     final List<String> extraRemoteVMOptions;
    94     final List<String> extraRemoteVMOptions;
    94     final List<String> extraCompilerOptions;
    95     final List<String> extraCompilerOptions;
    95     final ExecutionControl.Generator executionControlGenerator;
       
    96 
    96 
    97     private int nextKeyIndex = 1;
    97     private int nextKeyIndex = 1;
    98 
    98 
    99     final Eval eval;
    99     final Eval eval;
   100     final ClassTracker classTracker;
   100     final ClassTracker classTracker;
   101     private final Map<Subscription, Consumer<JShell>> shutdownListeners = new HashMap<>();
   101     private final Map<Subscription, Consumer<JShell>> shutdownListeners = new HashMap<>();
   102     private final Map<Subscription, Consumer<SnippetEvent>> keyStatusListeners = new HashMap<>();
   102     private final Map<Subscription, Consumer<SnippetEvent>> keyStatusListeners = new HashMap<>();
   103     private boolean closed = false;
   103     private boolean closed = false;
   104 
   104 
   105     private ExecutionControl executionControl = null;
   105     private final ExecutionControl executionControl;
   106     private SourceCodeAnalysisImpl sourceCodeAnalysis = null;
   106     private SourceCodeAnalysisImpl sourceCodeAnalysis = null;
   107 
   107 
   108     private static final String L10N_RB_NAME    = "jdk.jshell.resources.l10n";
   108     private static final String L10N_RB_NAME    = "jdk.jshell.resources.l10n";
   109     private static ResourceBundle outputRB  = null;
   109     private static ResourceBundle outputRB  = null;
   110 
   110 
   111     JShell(Builder b) {
   111     JShell(Builder b) throws IllegalStateException {
   112         this.in = b.in;
   112         this.in = b.in;
   113         this.out = b.out;
   113         this.out = b.out;
   114         this.err = b.err;
   114         this.err = b.err;
   115         this.tempVariableNameGenerator = b.tempVariableNameGenerator;
   115         this.tempVariableNameGenerator = b.tempVariableNameGenerator;
   116         this.idGenerator = b.idGenerator;
   116         this.idGenerator = b.idGenerator;
   117         this.extraRemoteVMOptions = b.extraRemoteVMOptions;
   117         this.extraRemoteVMOptions = b.extraRemoteVMOptions;
   118         this.extraCompilerOptions = b.extraCompilerOptions;
   118         this.extraCompilerOptions = b.extraCompilerOptions;
   119         this.executionControlGenerator = b.executionControlGenerator==null
   119         ExecutionControl.Generator executionControlGenerator = b.executionControlGenerator==null
   120                 ? failOverExecutionControlGenerator(JdiDefaultExecutionControl.launch(),
   120                 ? failOverExecutionControlGenerator(
   121                         JdiDefaultExecutionControl.listen("localhost"),
   121                         JdiDefaultExecutionControl.listen(InetAddress.getLoopbackAddress().getHostAddress()),
   122                         JdiDefaultExecutionControl.listen(null))
   122                         JdiDefaultExecutionControl.launch(),
       
   123                         JdiDefaultExecutionControl.listen(null)
       
   124                   )
   123                 : b.executionControlGenerator;
   125                 : b.executionControlGenerator;
       
   126         try {
       
   127             executionControl = executionControlGenerator.generate(new ExecutionEnvImpl());
       
   128         } catch (Throwable ex) {
       
   129             throw new IllegalStateException("Launching JShell execution engine threw: " + ex.getMessage(), ex);
       
   130         }
   124 
   131 
   125         this.maps = new SnippetMaps(this);
   132         this.maps = new SnippetMaps(this);
   126         this.keyMap = new KeyMap(this);
   133         this.keyMap = new KeyMap(this);
   127         this.outerMap = new OuterWrapMap(this);
   134         this.outerMap = new OuterWrapMap(this);
   128         this.taskFactory = new TaskFactory(this);
   135         this.taskFactory = new TaskFactory(this);
   329         /**
   336         /**
   330          * Builds a JShell state engine. This is the entry-point to all JShell
   337          * Builds a JShell state engine. This is the entry-point to all JShell
   331          * functionality. This creates a remote process for execution. It is
   338          * functionality. This creates a remote process for execution. It is
   332          * thus important to close the returned instance.
   339          * thus important to close the returned instance.
   333          *
   340          *
       
   341          * @throws IllegalStateException if the {@code JShell} instance could not be created.
   334          * @return the state engine
   342          * @return the state engine
   335          */
   343          */
   336         public JShell build() {
   344         public JShell build() throws IllegalStateException {
   337             return new JShell(this);
   345             return new JShell(this);
   338         }
   346         }
   339     }
   347     }
   340 
   348 
   341     // --- public API ---
   349     // --- public API ---
   343     /**
   351     /**
   344      * Create a new JShell state engine.
   352      * Create a new JShell state engine.
   345      * That is, create an instance of {@code JShell}.
   353      * That is, create an instance of {@code JShell}.
   346      * <p>
   354      * <p>
   347      * Equivalent to {@link JShell#builder() JShell.builder()}{@link JShell.Builder#build() .build()}.
   355      * Equivalent to {@link JShell#builder() JShell.builder()}{@link JShell.Builder#build() .build()}.
       
   356      * @throws IllegalStateException if the {@code JShell} instance could not be created.
   348      * @return an instance of {@code JShell}.
   357      * @return an instance of {@code JShell}.
   349      */
   358      */
   350     public static JShell create() {
   359     public static JShell create() throws IllegalStateException {
   351         return builder().build();
   360         return builder().build();
   352     }
   361     }
   353 
   362 
   354     /**
   363     /**
   355      * Factory method for {@code JShell.Builder} which, in-turn, is used
   364      * Factory method for {@code JShell.Builder} which, in-turn, is used
   456     /**
   465     /**
   457      * The specified path is added to the end of the classpath used in eval().
   466      * The specified path is added to the end of the classpath used in eval().
   458      * Note that the unnamed package is not accessible from the package in which
   467      * Note that the unnamed package is not accessible from the package in which
   459      * {@link JShell#eval(String)} code is placed.
   468      * {@link JShell#eval(String)} code is placed.
   460      * @param path the path to add to the classpath.
   469      * @param path the path to add to the classpath.
       
   470      * @throws IllegalStateException if this {@code JShell} instance is closed.
   461      */
   471      */
   462     public void addToClasspath(String path) {
   472     public void addToClasspath(String path) {
   463         // Compiler
   473         // Compiler
   464         taskFactory.addToClasspath(path);
   474         taskFactory.addToClasspath(path);
   465         // Runtime
   475         // Runtime
   502      */
   512      */
   503     @Override
   513     @Override
   504     public void close() {
   514     public void close() {
   505         if (!closed) {
   515         if (!closed) {
   506             closeDown();
   516             closeDown();
   507             executionControl().close();
   517             try {
       
   518                 executionControl().close();
       
   519             } catch (Throwable ex) {
       
   520                 // don't care about exceptions on close
       
   521             }
   508             if (sourceCodeAnalysis != null) {
   522             if (sourceCodeAnalysis != null) {
   509                 sourceCodeAnalysis.close();
   523                 sourceCodeAnalysis.close();
   510             }
   524             }
   511         }
   525         }
   512     }
   526     }
   731         }
   745         }
   732 
   746 
   733     }
   747     }
   734 
   748 
   735     // --- private / package-private implementation support ---
   749     // --- private / package-private implementation support ---
       
   750 
   736     ExecutionControl executionControl() {
   751     ExecutionControl executionControl() {
   737         if (executionControl == null) {
       
   738             try {
       
   739                 executionControl =  executionControlGenerator.generate(new ExecutionEnvImpl());
       
   740             } catch (Throwable ex) {
       
   741                 throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex);
       
   742             }
       
   743         }
       
   744         return executionControl;
   752         return executionControl;
   745     }
   753     }
   746 
   754 
   747     void debug(int flags, String format, Object... args) {
   755     void debug(int flags, String format, Object... args) {
   748         InternalDebugControl.debug(this, err, flags, format, args);
   756         InternalDebugControl.debug(this, err, flags, format, args);