001/*
002 * @(#)StreamRedirectThread.java        1.4 03/01/23
003 *
004 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
005 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
006 */
007/*
008 * Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
009 *
010 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
011 * modify and redistribute this software in source and binary code form,
012 * provided that i) this copyright notice and license appear on all copies of
013 * the software; and ii) Licensee does not utilize the software in a manner
014 * which is disparaging to Sun.
015 *
016 * This software is provided "AS IS," without a warranty of any kind. ALL
017 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
018 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
019 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
020 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
021 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
022 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
023 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
024 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
025 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
026 * POSSIBILITY OF SUCH DAMAGES.
027 *
028 * This software is not designed or intended for use in on-line control of
029 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
030 * the design, construction, operation or maintenance of any nuclear
031 * facility. Licensee represents and warrants that it will not use or
032 * redistribute the Software for such purposes.
033 */
034
035package daikon.chicory;
036
037import static java.nio.charset.StandardCharsets.UTF_8;
038
039import java.io.BufferedReader;
040import java.io.IOException;
041import java.io.InputStream;
042import java.io.InputStreamReader;
043import java.io.OutputStream;
044import java.io.OutputStreamWriter;
045import java.io.PrintStream;
046import java.io.Reader;
047import java.io.Writer;
048
049/**
050 * StreamRedirectThread is a thread that copies its input to its output and terminates when it
051 * completes.
052 *
053 * @version (#) StreamRedirectThread.java 1.4 03/01/23 16:33:15
054 * @author Robert Field
055 */
056public class StreamRedirectThread extends Thread {
057
058  private final Reader in;
059  private final Writer out;
060  private final PrintStream outWriter;
061
062  private boolean line_by_line = false;
063
064  private boolean debug = false;
065
066  private static final int BUFFER_SIZE = 2048;
067
068  // for debugging: private static final int BUFFER_SIZE = 1;
069
070  public StreamRedirectThread(String name, InputStream in, OutputStream out) {
071    this(name, in, out, false, false);
072  }
073
074  public StreamRedirectThread(String name, InputStream in, OutputStream out, boolean line_by_line) {
075    this(name, in, out, line_by_line, false);
076  }
077
078  /**
079   * Set up for copy.
080   *
081   * @param name name of the thread
082   * @param in stream to copy from
083   * @param out stream to copy to
084   * @param line_by_line whether to copy one line at a time
085   * @param debug whether to enable debugging
086   */
087  @SuppressWarnings("ThreadPriorityCheck")
088  public StreamRedirectThread(
089      String name, InputStream in, OutputStream out, boolean line_by_line, boolean debug) {
090    super(name);
091    if (debug) {
092      System.out.println(
093          "StreamRedirectThread("
094              + name
095              + ", "
096              + in
097              + ", "
098              + out
099              + ", "
100              + line_by_line
101              + ", "
102              + "true" // value of the `debug` variable
103              + ")");
104    }
105    if (in == null || out == null) {
106      System.out.println("bad arguments to StreamRedirectThread: " + in + " " + out);
107    }
108    this.in = new InputStreamReader(in, UTF_8);
109    this.out = new OutputStreamWriter(out, UTF_8);
110    this.outWriter = new PrintStream(out);
111    this.line_by_line = line_by_line;
112    this.debug = debug;
113
114    setPriority(Thread.MAX_PRIORITY - 1);
115  }
116
117  /** Copy. */
118  @Override
119  public void run() {
120    try {
121      if (line_by_line) {
122        BufferedReader br = new BufferedReader(in, BUFFER_SIZE);
123
124        String line;
125        while ((line = br.readLine()) != null) {
126          outWriter.println(line);
127        }
128      } else {
129        int nextChar;
130        while (true) {
131          // read() is a blocking call, but that's OK because
132          // this is running in its own thread.
133          nextChar = in.read();
134          if (nextChar == -1) {
135            break;
136          }
137
138          if (debug) {
139            System.out.println("[[[" + nextChar + "]]]");
140          }
141          out.write(nextChar);
142          out.flush();
143        }
144
145        out.flush();
146      }
147    } catch (IOException exc) {
148      System.err.println("Child I/O Transfer - " + exc);
149    }
150  }
151}