test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Binder.java
changeset 50317 cf71bff5f533
equal deleted inserted replaced
50316:60ebcc705421 50317:cf71bff5f533
       
     1 /*
       
     2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package nsk.share.jdwp;
       
    25 
       
    26 import nsk.share.*;
       
    27 import nsk.share.jpda.*;
       
    28 
       
    29 import java.io.*;
       
    30 
       
    31 /**
       
    32  * This class provides debugger with connection to debugee VM
       
    33  * using JDWP protocol.
       
    34  * <p>
       
    35  * This class provides abilities to launch and bind to debugee VM
       
    36  * as described for base <code>DebugeeBinder</code> class,
       
    37  * using raw JDWP protocol.
       
    38  * <p>
       
    39  * When <code>Binder</code> is asked to bind to debugee by invoking
       
    40  * <code>bindToBebugee()</code> method it launches process
       
    41  * with debugee VM and makes connection to it using JDWP transport
       
    42  * corresponding to value of command line options <code>-connector</code>
       
    43  * and <code>-transport</code>.
       
    44  * After debugee is launched and connection is established
       
    45  * <code>Binder</code> constructs <code>Debugee</code> object,
       
    46  * that provides abilities to interact with debugee VM.
       
    47  *
       
    48  * @see Debugee
       
    49  * @see DebugeeBinder
       
    50  */
       
    51 final public class Binder extends DebugeeBinder {
       
    52 
       
    53     /**
       
    54      * Default message prefix for <code>Binder</code> object.
       
    55      */
       
    56     public static final String LOG_PREFIX = "binder> ";
       
    57 
       
    58     /**
       
    59      * Get version string.
       
    60      */
       
    61     public static String getVersion () {
       
    62         return "@(#)Binder.java %I% %E%";
       
    63     }
       
    64 
       
    65     // -------------------------------------------------- //
       
    66 
       
    67     /**
       
    68      * Handler of command line arguments.
       
    69      */
       
    70     private ArgumentHandler argumentHandler = null;
       
    71 
       
    72     /**
       
    73      * Return <code>argumentHandler</code> of this binder.
       
    74      */
       
    75     public ArgumentHandler getArgumentHandler() {
       
    76         return argumentHandler;
       
    77     }
       
    78 
       
    79     // -------------------------------------------------- //
       
    80 
       
    81     /**
       
    82      * Make new <code>Binder</code> object with specified
       
    83      * <code>argumentHandler</code> and <code>log</code>.
       
    84      */
       
    85     public Binder (ArgumentHandler argumentHandler, Log log) {
       
    86         super(argumentHandler, log);
       
    87         this.argumentHandler = argumentHandler;
       
    88     }
       
    89 
       
    90     // -------------------------------------------------- //
       
    91 
       
    92     /**
       
    93      * Start debugee VM and establish JDWP connection to it.
       
    94      */
       
    95     public Debugee bindToDebugee (String classToExecute) {
       
    96 
       
    97         Debugee debugee = null;
       
    98 
       
    99         prepareForPipeConnection(argumentHandler);
       
   100 
       
   101         if (argumentHandler.isLaunchedRemotely()) {
       
   102             connectToBindServer(classToExecute);
       
   103             debugee = launchDebugee(classToExecute);
       
   104         } else {
       
   105             debugee = launchDebugee(classToExecute);
       
   106             debugee.redirectOutput(log);
       
   107         }
       
   108 
       
   109         Finalizer finalizer = new Finalizer(debugee);
       
   110         finalizer.activate();
       
   111 
       
   112         Transport transport = debugee.connect();
       
   113 
       
   114         return debugee;
       
   115     }
       
   116 
       
   117     /**
       
   118      * Launch debugee VM for specified class.
       
   119      */
       
   120     public Debugee launchDebugee (String classToExecute) {
       
   121 
       
   122         try {
       
   123 
       
   124             if (argumentHandler.isLaunchedLocally()) {
       
   125                 LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(this);
       
   126                 String address = debugee.prepareTransport(argumentHandler);
       
   127                 if (address == null)
       
   128                     address = makeTransportAddress();
       
   129                 String[] argsArray = makeCommandLineArgs(classToExecute, address);
       
   130                 debugee.launch(argsArray);
       
   131                 return debugee;
       
   132             }
       
   133 
       
   134             if (argumentHandler.isLaunchedRemotely()) {
       
   135                 RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
       
   136                 String address = debugee.prepareTransport(argumentHandler);
       
   137                 if (address == null)
       
   138                     address = makeTransportAddress();
       
   139                 String[] argsArray = makeCommandLineArgs(classToExecute, address);
       
   140                 debugee.launch(argsArray);
       
   141                 return debugee;
       
   142             }
       
   143 
       
   144             if (argumentHandler.isLaunchedManually()) {
       
   145                 ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
       
   146                 String address = debugee.prepareTransport(argumentHandler);
       
   147                 if (address == null)
       
   148                     address = makeTransportAddress();
       
   149                 String cmdLine = makeCommandLineString(classToExecute, address, "\"");
       
   150                 debugee.launch(cmdLine);
       
   151                 return debugee;
       
   152             }
       
   153 
       
   154             throw new TestBug("Unexpected launching mode: "
       
   155                             + argumentHandler.getLaunchMode());
       
   156         } catch (IOException e) {
       
   157             e.printStackTrace(log.getOutStream());
       
   158             throw new Failure("Caught exception while launching debugee:\n\t" + e);
       
   159         }
       
   160     }
       
   161 
       
   162 }
       
   163 
       
   164 /**
       
   165  * Mirror of locally launched debugee.
       
   166  */
       
   167 final class LocalLaunchedDebugee extends Debugee {
       
   168 
       
   169     /** Enwrap the existing <code>VM</code> mirror. */
       
   170     public LocalLaunchedDebugee (Binder binder) {
       
   171         super(binder);
       
   172         checkTermination = true;
       
   173     }
       
   174 
       
   175     // ---------------------------------------------- //
       
   176 
       
   177     public void launch(String[] args) throws IOException {
       
   178         String cmdLine = ArgumentHandler.joinArguments(args, "\"");
       
   179         display("Starting java process:\n" + cmdLine);
       
   180         process = binder.launchProcess(args);
       
   181     }
       
   182 
       
   183     /** Return exit status of the debugee VM. */
       
   184     public int getStatus () {
       
   185         return process.exitValue();
       
   186     }
       
   187 
       
   188     /** Check whether the debugee VM has been terminated. */
       
   189     public boolean terminated () {
       
   190         if (process == null)
       
   191             return true;
       
   192 
       
   193         try {
       
   194             int value = process.exitValue();
       
   195             return true;
       
   196         } catch (IllegalThreadStateException e) {
       
   197             return false;
       
   198         }
       
   199     }
       
   200 
       
   201     // ---------------------------------------------- //
       
   202 
       
   203     /** Kill the debugee VM. */
       
   204     protected void killDebugee () {
       
   205         super.killDebugee();
       
   206         if (!terminated()) {
       
   207             log.display("Killing debugee VM process");
       
   208             process.destroy();
       
   209         }
       
   210     }
       
   211 
       
   212     /** Wait until the debugee VM shutdown or crash. */
       
   213     protected int waitForDebugee () throws InterruptedException {
       
   214         return process.waitFor();
       
   215     }
       
   216 
       
   217     /** Get a pipe to write to the debugee's stdin stream. */
       
   218     protected OutputStream getInPipe () {
       
   219         return process.getOutputStream();
       
   220     }
       
   221 
       
   222     /** Get a pipe to read the debugee's stdout stream. */
       
   223     protected InputStream getOutPipe () {
       
   224         return process.getInputStream();
       
   225     }
       
   226 
       
   227     /** Get a pipe to read the debugee's stderr stream. */
       
   228     protected InputStream getErrPipe () {
       
   229         return process.getErrorStream();
       
   230     }
       
   231 }
       
   232 
       
   233 
       
   234 /**
       
   235  * Mirror of remotely launched debugee.
       
   236  */
       
   237 final class RemoteLaunchedDebugee extends Debugee {
       
   238 
       
   239     /** Enwrap the existing <code>VM</code> mirror. */
       
   240     public RemoteLaunchedDebugee (Binder binder) {
       
   241         super(binder);
       
   242     }
       
   243 
       
   244     // ---------------------------------------------- //
       
   245 
       
   246     public void launch(String[] args) throws IOException {
       
   247         String cmdLine = ArgumentHandler.joinArguments(args, "\"");
       
   248         display("Starting remote java process:\n" + cmdLine);
       
   249         binder.launchRemoteProcess(args);
       
   250     }
       
   251 
       
   252     /** Return exit status of the debugee VM. */
       
   253     public int getStatus () {
       
   254         return binder.getRemoteProcessStatus();
       
   255     }
       
   256 
       
   257     /** Check whether the debugee VM has been terminated. */
       
   258     public boolean terminated () {
       
   259         return binder.isRemoteProcessTerminated();
       
   260     }
       
   261 
       
   262     // ---------------------------------------------- //
       
   263 
       
   264     /** Kill the debugee VM. */
       
   265     protected void killDebugee () {
       
   266         super.killDebugee();
       
   267         if (!terminated()) {
       
   268             log.display("Killing debugee VM process");
       
   269             binder.killRemoteProcess();
       
   270         }
       
   271     }
       
   272 
       
   273     /** Wait until the debugee VM shutdown or crash. */
       
   274     protected int waitForDebugee () {
       
   275         return binder.waitForRemoteProcess();
       
   276     }
       
   277 
       
   278     /** Get a pipe to write to the debugee's stdin stream. */
       
   279     protected OutputStream getInPipe () {
       
   280         return null;
       
   281     }
       
   282 
       
   283     /** Get a pipe to read the debugee's stdout stream. */
       
   284     protected InputStream getOutPipe () {
       
   285         return null;
       
   286     }
       
   287 
       
   288     /** Get a pipe to read the debugee's stderr stream. */
       
   289     protected InputStream getErrPipe () {
       
   290         return null;
       
   291     }
       
   292 
       
   293     public void redirectStdout(OutputStream out) {
       
   294     }
       
   295 
       
   296     public void redirectStdout(Log log, String prefix) {
       
   297     }
       
   298 
       
   299     public void redirectStderr(OutputStream out) {
       
   300     }
       
   301 
       
   302     public void redirectStderr(Log log, String prefix) {
       
   303     }
       
   304 }
       
   305 
       
   306 
       
   307 /**
       
   308  * Mirror of manually launched debugee.
       
   309  */
       
   310 final class ManualLaunchedDebugee extends Debugee {
       
   311 
       
   312     private int exitCode = 0;
       
   313     private boolean finished = false;
       
   314     private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
       
   315 
       
   316     /** Enwrap the existing <code>VM</code> mirror. */
       
   317     public ManualLaunchedDebugee (Binder binder) {
       
   318         super(binder);
       
   319     }
       
   320 
       
   321     // ---------------------------------------------- //
       
   322 
       
   323     public void launch(String commandLine) throws IOException {
       
   324         putMessage("Launch target VM using such command line:\n"
       
   325                     + commandLine);
       
   326         String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
       
   327         for ( ; ; ) {
       
   328             if (answer.equals("yes"))
       
   329                 break;
       
   330             if (answer.equals("no"))
       
   331                 throw new Failure ("Unable to manually launch debugee VM");
       
   332             answer = askQuestion("Wrong answer. Please type yes or no", "yes");
       
   333         }
       
   334     }
       
   335 
       
   336     private void putMessage(String msg) {
       
   337         System.out.println("\n>>> " + msg);
       
   338     }
       
   339 
       
   340     private String askQuestion(String question, String defaultAnswer) {
       
   341         try {
       
   342             System.out.print("\n>>> " + question);
       
   343             System.out.print(" [" + defaultAnswer + "] ");
       
   344             System.out.flush();
       
   345             String answer = bin.readLine();
       
   346             if (answer.equals(""))
       
   347                 return defaultAnswer;
       
   348             return answer;
       
   349         } catch (IOException e) {
       
   350             e.printStackTrace(log.getOutStream());
       
   351             throw new Failure("Caught exception while reading answer:\n\t" + e);
       
   352         }
       
   353     }
       
   354 
       
   355     /** Return exit status of the debugee VM. */
       
   356     public int getStatus () {
       
   357         if (! terminated()) {
       
   358             throw new Failure("Unable to get status of debugee VM: process still alive");
       
   359         }
       
   360         return exitCode;
       
   361     }
       
   362 
       
   363     /** Check whether the debugee VM has been terminated. */
       
   364     public boolean terminated () {
       
   365         if(! finished) {
       
   366             String answer = askQuestion("Has the VM exited?", "no");
       
   367             for ( ; ; ) {
       
   368                 if (answer.equals("no"))
       
   369                     return false;
       
   370                 if (answer.equals("yes")) {
       
   371                     finished = true;
       
   372                     waitForDebugee();
       
   373                     break;
       
   374                 }
       
   375                 answer = askQuestion("Wrong answer. Please type yes or no", "yes");
       
   376             }
       
   377         }
       
   378         return finished;
       
   379     }
       
   380 
       
   381     // ---------------------------------------------- //
       
   382 
       
   383     /** Kill the debugee VM. */
       
   384     protected void killDebugee () {
       
   385         super.killDebugee();
       
   386         if (!terminated()) {
       
   387             putMessage("Kill launched VM");
       
   388             String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
       
   389             for ( ; ; ) {
       
   390                 if (answer.equals("yes")) {
       
   391                     finished = true;
       
   392                     break;
       
   393                 }
       
   394                 if (answer.equals("no"))
       
   395                     throw new Failure ("Unable to manually kill debugee VM");
       
   396                 answer = askQuestion("Wrong answer. Please type yes or no", "yes");
       
   397             }
       
   398         }
       
   399     }
       
   400 
       
   401     /** Wait until the debugee VM shutdown or crash. */
       
   402     protected int waitForDebugee () {
       
   403         putMessage("Wait for launched VM to exit.");
       
   404         String answer = askQuestion("What is VM exit code?", "95");
       
   405         for ( ; ; ) {
       
   406             try {
       
   407                 exitCode = Integer.parseInt(answer);
       
   408                 break;
       
   409             } catch (NumberFormatException e) {
       
   410                 answer = askQuestion("Wrong answer. Please type integer value", "95");
       
   411             }
       
   412         }
       
   413         finished = true;
       
   414         return exitCode;
       
   415     }
       
   416 
       
   417     /** Get a pipe to write to the debugee's stdin stream. */
       
   418     protected OutputStream getInPipe () {
       
   419         return null;
       
   420     }
       
   421 
       
   422     /** Get a pipe to read the debugee's stdout stream. */
       
   423     protected InputStream getOutPipe () {
       
   424         return null;
       
   425     }
       
   426 
       
   427     /** Get a pipe to read the debugee's stderr stream. */
       
   428     protected InputStream getErrPipe () {
       
   429         return null;
       
   430     }
       
   431 
       
   432     public void redirectStdout(OutputStream out) {
       
   433     }
       
   434 
       
   435     public void redirectStdout(Log log, String prefix) {
       
   436     }
       
   437 
       
   438     public void redirectStderr(OutputStream out) {
       
   439     }
       
   440 
       
   441     public void redirectStderr(Log log, String prefix) {
       
   442     }
       
   443 
       
   444     public void close() {
       
   445         try {
       
   446             bin.close();
       
   447         } catch (IOException e) {
       
   448             log.display("WARNING: Caught IOException while closing InputStream");
       
   449         }
       
   450         bin = null;
       
   451         super.close();
       
   452     }
       
   453 }