1 /*
   2  * Copyright (c) 1998, 2012, 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 /**
  25  *
  26  */
  27 
  28 import java.io.*;
  29 
  30 /**
  31  * Pipe output of one stream into input of another.
  32  */
  33 public class StreamPipe extends Thread {
  34 
  35     private InputStream in;
  36     private OutputStream out;
  37     private String preamble;
  38     private JavaVM javaVM;
  39     private static Object lock = new Object();
  40     private static int count = 0;
  41 
  42 
  43     /* StreamPipe constructor : should only be called by plugTogether() method !!
  44      * If passed vm is not null :
  45      * -  This is StreamPipe usage when streams to pipe come from a given
  46      *    vm (JavaVM) process (the vm process must be started with a prefixed
  47      *    "-showversion" option to be able to determine as soon as possible when
  48      *    the vm process is started through the redirection of the streams).
  49      *    There must be a close connection between the StreamPipe instance and
  50      *    the JavaVM object on which a start() call has been done.
  51      *    run() method will flag distant JavaVM as started.
  52      * If passed vm is null :
  53      * -  We don't have control on the process which we want to redirect the passed
  54      *    streams.
  55      *    run() method will ignore distant process.
  56      */
  57     private StreamPipe(JavaVM vm, InputStream in, OutputStream out, String name) {
  58         super(name);
  59         this.in  = in;
  60         this.out = out;
  61         this.preamble = "# ";
  62         this.javaVM = vm;
  63     }
  64 
  65     // Install redirection of passed InputStream and OutputStream from passed JavaVM
  66     // to this vm standard output and input streams.
  67     public static void plugTogether(JavaVM vm, InputStream in, OutputStream out) {
  68         String name = null;
  69 
  70         synchronized (lock) {
  71             name = "TestLibrary: StreamPipe-" + (count ++ );
  72         }
  73 
  74         Thread pipe = new StreamPipe(vm, in, out, name);
  75         pipe.setDaemon(true);
  76         pipe.start();
  77     }
  78 
  79     /* Redirects the InputStream and OutputStream passed by caller to this
  80      * vm standard output and input streams.
  81      * (we just have to use fully parametered plugTogether() call with a null
  82      *  JavaVM input to do this).
  83      */
  84     public static void plugTogether(InputStream in, OutputStream out) {
  85         plugTogether(null, in, out);
  86     }
  87 
  88     // Starts redirection of streams.
  89     public void run() {
  90         BufferedReader r = new BufferedReader(new InputStreamReader(in), 1);
  91         BufferedWriter w = new BufferedWriter(new OutputStreamWriter(out));
  92         byte[] buf = new byte[256];
  93 
  94         try {
  95             String line;
  96 
  97             /* This is to check that the distant vm has started,
  98              * if such a vm has been provided at construction :
  99              * - As soon as we can read something from r BufferedReader,
 100              *   that means the distant vm is already started.
 101              * Thus we signal associated JavaVM object that it is now started.
 102              */
 103             if (((line = r.readLine()) != null) &&
 104                 (javaVM != null)) {
 105                 javaVM.setStarted();
 106             }
 107 
 108             // Redirects r on w.
 109             while (line != null) {
 110                 w.write(preamble);
 111                 w.write(line);
 112                 w.newLine();
 113                 w.flush();
 114                 line = r.readLine();
 115             }
 116         } catch (InterruptedIOException iioe) {
 117             // Thread interrupted during IO operation. Terminate StreamPipe.
 118             return;
 119         } catch (IOException e) {
 120             System.err.println("*** IOException in StreamPipe.run:");
 121             e.printStackTrace();
 122         }
 123     }
 124 
 125 }