001package net.bramp.ffmpeg.io;
002
003import java.io.FilterReader;
004import java.io.IOException;
005import java.io.Reader;
006import org.slf4j.Logger;
007
008/**
009 * Wraps a Reader, and logs full lines of input as it is read.
010 *
011 * @author bramp
012 */
013public class LoggingFilterReader extends FilterReader {
014
015  static final char LOG_CHAR = '\n';
016
017  final Logger logger;
018  final StringBuilder buffer = new StringBuilder();
019
020  /** Constructs a new LoggingFilterReader that logs lines read from the given reader. */
021  public LoggingFilterReader(Reader in, Logger logger) {
022    super(in);
023    this.logger = logger;
024  }
025
026  /** Logs the contents of the buffer and resets it. */
027  protected void log() {
028    if (buffer.length() > 0) {
029      // TODO Change from debug, to a user defined level
030      logger.debug(buffer.toString());
031      buffer.setLength(0);
032    }
033  }
034
035  private static int indexOf(char[] array, char c, int off, int len) {
036    for (int i = off; i < off + len; i++) {
037      if (array[i] == c) {
038        return i;
039      }
040    }
041    return -1;
042  }
043
044  @Override
045  public int read(char[] cbuf, int off, int len) throws IOException {
046    int ret = super.read(cbuf, off, len);
047    if (ret != -1) {
048      buffer.append(cbuf, off, ret);
049    }
050
051    // If end of stream, or contains new line
052    if (ret == -1 || indexOf(cbuf, LOG_CHAR, off, ret) != -1) {
053      // BUG this will log a unfinished line, if a string such as
054      // "line \n unfinished" is read.
055      log();
056    }
057
058    return ret;
059  }
060
061  @Override
062  public int read() throws IOException {
063    int ret = super.read();
064    if (ret != -1) {
065      buffer.append((char) ret);
066    }
067
068    // If end of stream, or contains new line
069    if (ret == -1 || ret == LOG_CHAR) {
070      log();
071    }
072    return ret;
073  }
074}