package sockslib.common.net;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Youchao Feng
* @version 1.0
* @date Sep 21, 2015 2:31 PM
*/
public class MonitorInputStreamWrapper extends InputStream {
private InputStream originalInputStream;
private List<InputStreamMonitor> monitors;
public MonitorInputStreamWrapper(InputStream inputStream) {
this.originalInputStream = inputStream;
}
public MonitorInputStreamWrapper(InputStream inputStream, InputStreamMonitor... monitors) {
this.originalInputStream = checkNotNull(inputStream);
this.monitors = new ArrayList<>(monitors.length);
Collections.addAll(this.monitors, monitors);
}
public MonitorInputStreamWrapper(InputStream inputStream, List<InputStreamMonitor> monitors) {
this.originalInputStream = checkNotNull(inputStream);
this.monitors = checkNotNull(monitors);
}
public static InputStream wrap(InputStream inputStream, InputStreamMonitor... monitors) {
return new MonitorInputStreamWrapper(inputStream, monitors);
}
public static InputStream wrap(InputStream inputStream, List<InputStreamMonitor> monitors) {
return new MonitorInputStreamWrapper(inputStream, monitors);
}
public InputStream getOriginalInputStream() {
return originalInputStream;
}
public MonitorInputStreamWrapper addMonitor(InputStreamMonitor monitor) {
if (monitors == null) {
monitors = new ArrayList<>(1);
}
monitors.add(monitor);
return this;
}
public MonitorInputStreamWrapper removeMonitor(InputStreamMonitor monitor) {
if (monitors != null) {
monitors.remove(monitor);
}
return this;
}
@Override
public int read() throws IOException {
int b = originalInputStream.read();
byte[] array = {(byte) b};
informMonitor(array);
return b;
}
public List<InputStreamMonitor> getMonitors() {
return monitors;
}
public void setMonitors(List<InputStreamMonitor> monitors) {
this.monitors = checkNotNull(monitors);
}
@Override
public void close() throws IOException {
originalInputStream.close();
}
@Override
public int available() throws IOException {
return originalInputStream.available();
}
@Override
public long skip(long n) throws IOException {
return originalInputStream.skip(n);
}
@Override
public synchronized void reset() throws IOException {
originalInputStream.reset();
}
@Override
public synchronized void mark(int readLimit) {
originalInputStream.mark(readLimit);
}
@Override
public boolean markSupported() {
return originalInputStream.markSupported();
}
@Override
public int read(byte[] b) throws IOException {
int length = originalInputStream.read(b);
if (length > 0) {
informMonitor(b, 0, length);
}
return length;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int length = originalInputStream.read(b, off, len);
if (length > 0) {
informMonitor(b, off, length);
}
return length;
}
private void informMonitor(byte[] bytes) {
if (monitors != null) {
for (InputStreamMonitor monitor : monitors) {
monitor.onRead(bytes);
}
}
}
private void informMonitor(byte[] bytes, int off, int len) {
if (monitors != null) {
for (InputStreamMonitor monitor : monitors) {
monitor.onRead(Arrays.copyOfRange(bytes, off, off + len));
}
}
}
}