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)); } } } }