langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java
changeset 42272 82e273c4f2b3
parent 41995 1ac75bf2dc3a
child 42969 a48d4f74d322
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java	Tue Nov 22 16:31:03 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java	Tue Nov 22 19:24:02 2016 -0800
@@ -63,7 +63,10 @@
  */
 public class JdiDefaultExecutionControl extends JdiExecutionControl {
 
-    private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
+    /**
+     * Default time-out expressed in milliseconds.
+     */
+    private static final int DEFAULT_TIMEOUT = 5000;
 
     private VirtualMachine vm;
     private Process process;
@@ -73,24 +76,60 @@
 
     /**
      * Creates an ExecutionControl instance based on a JDI
-     * {@code LaunchingConnector}.
+     * {@code LaunchingConnector}. Same as
+     * {@code JdiDefaultExecutionControl.create(defaultRemoteAgent(), true, null, defaultTimeout())}.
      *
      * @return the generator
      */
     public static ExecutionControl.Generator launch() {
-        return env -> create(env, true, null);
+        return create(defaultRemoteAgent(), true, null, defaultTimeout());
     }
 
     /**
      * Creates an ExecutionControl instance based on a JDI
-     * {@code ListeningConnector}.
+     * {@code ListeningConnector}. Same as
+     * {@code JdiDefaultExecutionControl.create(defaultRemoteAgent(), false, host, defaultTimeout())}.
      *
      * @param host explicit hostname to use, if null use discovered
      * hostname, applies to listening only (!isLaunch)
      * @return the generator
      */
     public static ExecutionControl.Generator listen(String host) {
-        return env -> create(env, false, host);
+        return create(defaultRemoteAgent(), false, host, defaultTimeout());
+    }
+
+    /**
+     * Creates a JDI based ExecutionControl instance.
+     *
+     * @param remoteAgent the remote agent to launch
+     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
+     * otherwise we start explicitly and use ListeningConnector
+     * @param host explicit hostname to use, if null use discovered
+     * hostname, applies to listening only (!isLaunch)
+     * @param timeout the start-up time-out in milliseconds
+     * @return the generator
+     */
+    public static ExecutionControl.Generator create(String remoteAgent,
+            boolean isLaunch, String host, int timeout) {
+        return env -> create(env, remoteAgent, isLaunch, host, timeout);
+    }
+
+    /**
+     * Default remote agent.
+     *
+     * @return the name of the standard remote agent
+     */
+    public static String defaultRemoteAgent() {
+        return RemoteExecutionControl.class.getName();
+    }
+
+    /**
+     * Default remote connection time-out
+     *
+     * @return time to wait for connection before failing, expressed in milliseconds.
+     */
+    public static int defaultTimeout() {
+        return DEFAULT_TIMEOUT;
     }
 
     /**
@@ -103,6 +142,7 @@
      *
      * @param env the context passed by
      * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+     * @param remoteAgent the remote agent to launch
      * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
      * otherwise we start explicitly and use ListeningConnector
      * @param host explicit hostname to use, if null use discovered
@@ -110,16 +150,16 @@
      * @return the channel
      * @throws IOException if there are errors in set-up
      */
-    private static ExecutionControl create(ExecutionEnv env,
-            boolean isLaunch, String host) throws IOException {
+    private static ExecutionControl create(ExecutionEnv env, String remoteAgent,
+            boolean isLaunch, String host, int timeout) throws IOException {
         try (final ServerSocket listener = new ServerSocket(0, 1, InetAddress.getLoopbackAddress())) {
-            // timeout after 60 seconds
-            listener.setSoTimeout(60000);
+            // timeout on I/O-socket
+            listener.setSoTimeout(timeout);
             int port = listener.getLocalPort();
 
             // Set-up the JDI connection
             JdiInitiator jdii = new JdiInitiator(port,
-                    env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
+                    env.extraRemoteVMOptions(), remoteAgent, isLaunch, host, timeout);
             VirtualMachine vm = jdii.vm();
             Process process = jdii.process();
 
@@ -197,7 +237,7 @@
                 for (ThreadReference thread : vm().allThreads()) {
                     // could also tag the thread (e.g. using name), to find it easier
                     for (StackFrame frame : thread.frames()) {
-                        if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
+                        if (defaultRemoteAgent().equals(frame.location().declaringType().name()) &&
                                 (    "invoke".equals(frame.location().method().name())
                                 || "varValue".equals(frame.location().method().name()))) {
                             ObjectReference thiz = frame.thisObject();