langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java
changeset 41995 1ac75bf2dc3a
parent 41994 e43f670394ca
child 42272 82e273c4f2b3
equal deleted inserted replaced
41994:e43f670394ca 41995:1ac75bf2dc3a
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 package jdk.jshell.execution;
    25 package jdk.jshell.execution;
    26 
    26 
    27 import java.io.ByteArrayOutputStream;
       
    28 import java.io.IOException;
    27 import java.io.IOException;
    29 import java.io.InputStream;
    28 import java.io.InputStream;
    30 import java.io.ObjectInput;
    29 import java.io.ObjectInput;
    31 import java.io.ObjectOutput;
    30 import java.io.ObjectOutput;
    32 import java.io.OutputStream;
    31 import java.io.OutputStream;
    33 import java.net.InetAddress;
    32 import java.net.InetAddress;
    34 import java.net.ServerSocket;
    33 import java.net.ServerSocket;
    35 import java.net.Socket;
    34 import java.net.Socket;
    36 import java.security.SecureRandom;
       
    37 import java.util.ArrayList;
    35 import java.util.ArrayList;
    38 import java.util.Arrays;
       
    39 import java.util.HashMap;
    36 import java.util.HashMap;
    40 import java.util.List;
    37 import java.util.List;
    41 import java.util.Map;
    38 import java.util.Map;
    42 import java.util.function.Consumer;
    39 import java.util.function.Consumer;
    43 
       
    44 import com.sun.jdi.BooleanValue;
    40 import com.sun.jdi.BooleanValue;
    45 import com.sun.jdi.ClassNotLoadedException;
    41 import com.sun.jdi.ClassNotLoadedException;
    46 import com.sun.jdi.Field;
    42 import com.sun.jdi.Field;
    47 import com.sun.jdi.IncompatibleThreadStateException;
    43 import com.sun.jdi.IncompatibleThreadStateException;
    48 import com.sun.jdi.InvalidTypeException;
    44 import com.sun.jdi.InvalidTypeException;
   125             JdiInitiator jdii = new JdiInitiator(port,
   121             JdiInitiator jdii = new JdiInitiator(port,
   126                     env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
   122                     env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
   127             VirtualMachine vm = jdii.vm();
   123             VirtualMachine vm = jdii.vm();
   128             Process process = jdii.process();
   124             Process process = jdii.process();
   129 
   125 
   130             OutputStream processOut = process.getOutputStream();
       
   131             SecureRandom rng = new SecureRandom();
       
   132             byte[] randomBytes = new byte[VERIFY_HASH_LEN];
       
   133 
       
   134             rng.nextBytes(randomBytes);
       
   135             processOut.write(randomBytes);
       
   136             processOut.flush();
       
   137 
       
   138             List<Consumer<String>> deathListeners = new ArrayList<>();
   126             List<Consumer<String>> deathListeners = new ArrayList<>();
   139             deathListeners.add(s -> env.closeDown());
   127             deathListeners.add(s -> env.closeDown());
   140             Util.detectJdiExitEvent(vm, s -> {
   128             Util.detectJdiExitEvent(vm, s -> {
   141                 for (Consumer<String> h : deathListeners) {
   129                 for (Consumer<String> h : deathListeners) {
   142                     h.accept(s);
   130                     h.accept(s);
   143                 }
   131                 }
   144             });
   132             });
   145 
       
   146             ByteArrayOutputStream receivedRandomBytes = new ByteArrayOutputStream();
       
   147 
   133 
   148             // Set-up the commands/reslts on the socket.  Piggy-back snippet
   134             // Set-up the commands/reslts on the socket.  Piggy-back snippet
   149             // output.
   135             // output.
   150             Socket socket = listener.accept();
   136             Socket socket = listener.accept();
   151             // out before in -- match remote creation so we don't hang
   137             // out before in -- match remote creation so we don't hang
   152             OutputStream out = socket.getOutputStream();
   138             OutputStream out = socket.getOutputStream();
   153             Map<String, OutputStream> outputs = new HashMap<>();
   139             Map<String, OutputStream> outputs = new HashMap<>();
   154             outputs.put("out", env.userOut());
   140             outputs.put("out", env.userOut());
   155             outputs.put("err", env.userErr());
   141             outputs.put("err", env.userErr());
   156             outputs.put("echo", new OutputStream() {
       
   157                 @Override public void write(int b) throws IOException {
       
   158                     synchronized (receivedRandomBytes) {
       
   159                         receivedRandomBytes.write(b);
       
   160                         receivedRandomBytes.notify();
       
   161                     }
       
   162                 }
       
   163             });
       
   164             Map<String, InputStream> input = new HashMap<>();
   142             Map<String, InputStream> input = new HashMap<>();
   165             input.put("in", env.userIn());
   143             input.put("in", env.userIn());
   166             return remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> {
   144             return remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new JdiDefaultExecutionControl(objOut, objIn, vm, process, deathListeners));
   167                 synchronized (receivedRandomBytes) {
   145         }
   168                     while (receivedRandomBytes.size() < randomBytes.length) {
   146     }
   169                         try {
       
   170                             receivedRandomBytes.wait();
       
   171                         } catch (InterruptedException ex) {
       
   172                             //ignore
       
   173                         }
       
   174                     }
       
   175                     if (!Arrays.equals(receivedRandomBytes.toByteArray(), randomBytes)) {
       
   176                         throw new IllegalStateException("Invalid connection!");
       
   177                     }
       
   178                 }
       
   179                 return new JdiDefaultExecutionControl(objOut, objIn, vm, process, deathListeners);
       
   180             });
       
   181         }
       
   182     }
       
   183     //where:
       
   184         private static final int VERIFY_HASH_LEN = 20;
       
   185 
   147 
   186     /**
   148     /**
   187      * Create an instance.
   149      * Create an instance.
   188      *
   150      *
   189      * @param cmdout the output for commands
   151      * @param cmdout the output for commands