package sockslib.common.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The class <code>MonitorSocketWrapper</code> is wrapper of {@link java.net.Socket}.
*
* @author Youchao Feng
* @version 1.0
* @date Sep 21, 2015 11:40 AM
*/
public class MonitorSocketWrapper extends Socket {
private Socket originalSocket;
private List<SocketMonitor> monitors;
private InputStream inputStream = null;
private OutputStream outputStream = null;
public MonitorSocketWrapper(Socket socket, SocketMonitor... monitors) {
this.originalSocket = checkNotNull(socket, "Argument [socket] may not be null");
this.monitors = new ArrayList<>(monitors.length);
Collections.addAll(this.monitors, monitors);
}
public MonitorSocketWrapper(Socket socket, List<SocketMonitor> monitors) {
this.originalSocket = checkNotNull(socket, "Argument [socket] may not be null");
this.monitors = checkNotNull(monitors, "Arugment [monitors] may not be null");
}
public MonitorSocketWrapper(Socket socket) {
this.originalSocket = checkNotNull(socket, "Argument [socket] may not be null");
}
public static Socket wrap(Socket socket, SocketMonitor... monitors) {
return new MonitorSocketWrapper(socket, monitors);
}
public static Socket wrap(Socket socket, List<SocketMonitor> monitors) {
return new MonitorSocketWrapper(socket, monitors);
}
public MonitorSocketWrapper addMonitor(SocketMonitor monitor) {
if (monitors == null) {
monitors = new ArrayList<>(1);
}
monitors.add(monitor);
return this;
}
public MonitorSocketWrapper removeMonitor(SocketMonitor monitor) {
if (monitors != null) {
monitors.remove(monitor);
}
return this;
}
public Socket getOriginalSocket() {
return originalSocket;
}
public void setOriginalSocket(Socket originalSocket) {
this.originalSocket = originalSocket;
}
public List<SocketMonitor> getMonitors() {
return monitors;
}
public void setMonitors(List<SocketMonitor> monitors) {
this.monitors = monitors;
}
@Override
public void connect(SocketAddress endpoint) throws IOException {
originalSocket.connect(endpoint);
}
@Override
public void connect(SocketAddress endpoint, int timeout) throws IOException {
originalSocket.connect(endpoint, timeout);
}
@Override
public void bind(SocketAddress bindpoint) throws IOException {
originalSocket.bind(bindpoint);
}
@Override
public InetAddress getInetAddress() {
return originalSocket.getInetAddress();
}
@Override
public InetAddress getLocalAddress() {
return originalSocket.getLocalAddress();
}
@Override
public int getPort() {
return originalSocket.getPort();
}
@Override
public int getLocalPort() {
return originalSocket.getLocalPort();
}
@Override
public SocketAddress getRemoteSocketAddress() {
return originalSocket.getRemoteSocketAddress();
}
@Override
public SocketAddress getLocalSocketAddress() {
return originalSocket.getLocalSocketAddress();
}
@Override
public SocketChannel getChannel() {
return originalSocket.getChannel();
}
@Override
public InputStream getInputStream() throws IOException {
if (inputStream == null) {
inputStream = getInputStreamFromSocket();
}
return inputStream;
}
public InputStream getInputStreamFromSocket() throws IOException {
List<InputStreamMonitor> inputStreamMonitors = new ArrayList<>(monitors.size());
if (monitors != null) {
for (SocketMonitor socketMonitor : monitors) {
inputStreamMonitors.add(socketMonitor);
}
}
return MonitorInputStreamWrapper.wrap(originalSocket.getInputStream(), inputStreamMonitors);
}
@Override
public OutputStream getOutputStream() throws IOException {
if (outputStream == null) {
outputStream = getOutputStreamFromSocket();
}
return outputStream;
}
public OutputStream getOutputStreamFromSocket() throws IOException {
List<OutputStreamMonitor> outputStreamMonitors = new ArrayList<>(monitors.size());
if (monitors != null) {
for (SocketMonitor socketMonitor : monitors) {
outputStreamMonitors.add(socketMonitor);
}
}
return MonitorOutputStreamWrapper.wrap(originalSocket.getOutputStream(), outputStreamMonitors);
}
@Override
public boolean getTcpNoDelay() throws SocketException {
return originalSocket.getTcpNoDelay();
}
@Override
public void setTcpNoDelay(boolean on) throws SocketException {
originalSocket.setTcpNoDelay(on);
}
@Override
public void setSoLinger(boolean on, int linger) throws SocketException {
originalSocket.setSoLinger(on, linger);
}
@Override
public int getSoLinger() throws SocketException {
return originalSocket.getSoLinger();
}
@Override
public void sendUrgentData(int data) throws IOException {
originalSocket.sendUrgentData(data);
}
@Override
public boolean getOOBInline() throws SocketException {
return originalSocket.getOOBInline();
}
@Override
public void setOOBInline(boolean on) throws SocketException {
originalSocket.setOOBInline(on);
}
@Override
public synchronized int getSoTimeout() throws SocketException {
return originalSocket.getSoTimeout();
}
@Override
public synchronized void setSoTimeout(int timeout) throws SocketException {
originalSocket.setSoTimeout(timeout);
}
@Override
public synchronized int getSendBufferSize() throws SocketException {
return originalSocket.getSendBufferSize();
}
@Override
public synchronized void setSendBufferSize(int size) throws SocketException {
originalSocket.setSendBufferSize(size);
}
@Override
public synchronized int getReceiveBufferSize() throws SocketException {
return originalSocket.getReceiveBufferSize();
}
@Override
public synchronized void setReceiveBufferSize(int size) throws SocketException {
originalSocket.setReceiveBufferSize(size);
}
@Override
public boolean getKeepAlive() throws SocketException {
return originalSocket.getKeepAlive();
}
@Override
public void setKeepAlive(boolean on) throws SocketException {
originalSocket.setKeepAlive(on);
}
@Override
public int getTrafficClass() throws SocketException {
return originalSocket.getTrafficClass();
}
@Override
public void setTrafficClass(int tc) throws SocketException {
originalSocket.setTrafficClass(tc);
}
@Override
public boolean getReuseAddress() throws SocketException {
return originalSocket.getReuseAddress();
}
@Override
public void setReuseAddress(boolean on) throws SocketException {
originalSocket.setReuseAddress(on);
}
@Override
public synchronized void close() throws IOException {
originalSocket.close();
}
@Override
public void shutdownInput() throws IOException {
originalSocket.shutdownInput();
}
@Override
public void shutdownOutput() throws IOException {
originalSocket.shutdownOutput();
}
@Override
public String toString() {
return originalSocket.toString();
}
@Override
public boolean isConnected() {
return originalSocket.isConnected();
}
@Override
public boolean isBound() {
return originalSocket.isBound();
}
@Override
public boolean isClosed() {
return originalSocket.isClosed();
}
@Override
public boolean isInputShutdown() {
return originalSocket.isInputShutdown();
}
@Override
public boolean isOutputShutdown() {
return originalSocket.isOutputShutdown();
}
@Override
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
originalSocket.setPerformancePreferences(connectionTime, latency, bandwidth);
}
@Override
public int hashCode() {
return originalSocket.hashCode();
}
@Override
public boolean equals(Object obj) {
return originalSocket.equals(obj);
}
}