001package com.streamconverter.util;
002
003import java.io.IOException;
004import java.io.InputStream;
005
006/**
007 * 入力ストリームのデータサイズを測定するラッパークラス
008 *
009 * <p>このクラスは、InputStreamをラップして読み取ったバイト数を自動的に計測します。 自動ログ出力機能でパフォーマンス測定に使用されます。
010 */
011public class MeasuredInputStream extends InputStream {
012  private final InputStream delegate;
013  private long bytesRead;
014  private boolean closed;
015
016  /**
017   * コンストラクタ
018   *
019   * @param delegateStream ラップ対象のInputStream
020   */
021  public MeasuredInputStream(final InputStream delegateStream) {
022    super();
023    this.delegate =
024        java.util.Objects.requireNonNull(delegateStream, "delegate InputStream cannot be null");
025  }
026
027  @Override
028  public int read() throws IOException {
029    int result = -1;
030    if (!closed) {
031      result = delegate.read();
032      if (result != -1) {
033        bytesRead++;
034      }
035    }
036    return result;
037  }
038
039  @Override
040  public int read(final byte[] buffer) throws IOException {
041    int result = -1;
042    if (!closed) {
043      result = delegate.read(buffer);
044      if (result > 0) {
045        bytesRead += result;
046      }
047    }
048    return result;
049  }
050
051  @Override
052  public int read(final byte[] buffer, final int offset, final int length) throws IOException {
053    int result = -1;
054    if (!closed) {
055      result = delegate.read(buffer, offset, length);
056      if (result > 0) {
057        bytesRead += result;
058      }
059    }
060    return result;
061  }
062
063  @Override
064  public long skip(final long numBytes) throws IOException {
065    long result = 0;
066    if (!closed) {
067      result = delegate.skip(numBytes);
068      if (result > 0) {
069        bytesRead += result;
070      }
071    }
072    return result;
073  }
074
075  @Override
076  public int available() throws IOException {
077    int result = 0;
078    if (!closed) {
079      result = delegate.available();
080    }
081    return result;
082  }
083
084  @Override
085  public void close() throws IOException {
086    if (!closed) {
087      closed = true;
088      delegate.close();
089    }
090  }
091
092  @Override
093  public synchronized void mark(final int readLimit) {
094    if (!closed) {
095      delegate.mark(readLimit);
096    }
097  }
098
099  @Override
100  public synchronized void reset() throws IOException {
101    if (!closed) {
102      delegate.reset();
103    }
104  }
105
106  @Override
107  public boolean markSupported() {
108    return !closed && delegate.markSupported();
109  }
110
111  /**
112   * 現在までに読み取ったバイト数を取得
113   *
114   * @return 読み取ったバイト数
115   */
116  public long getBytesRead() {
117    return bytesRead;
118  }
119
120  /**
121   * ストリームがクローズされているかどうかを確認
122   *
123   * @return クローズされている場合true
124   */
125  public boolean isClosed() {
126    return closed;
127  }
128}