X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-vnc-client.git/blobdiff_plain/a824f7ccc88825c5ba5a3f990cfaf3530b9d88a6..46a087a65293d806d15601a775010670baecd066:/SocketWrapper.java diff --git a/SocketWrapper.java b/SocketWrapper.java new file mode 100644 index 0000000..2920732 --- /dev/null +++ b/SocketWrapper.java @@ -0,0 +1,252 @@ +/* + * Written by Dawid Kurzyniec and released to the public domain, as explained + * at http://creativecommons.org/licenses/publicdomain + */ + +//package edu.emory.mathcs.util.net; + +import java.io.*; +import java.net.*; +import java.nio.channels.*; + +/** + * Wrapper for sockets which enables to add functionality in subclasses + * on top of existing, connected sockets. It is useful when direct subclassing + * of delegate socket class is not possible, e.g. if the delegate socket is + * created by a library. Possible usage example is socket factory chaining. + * This class delegates all socket-related requests to the wrapped delegate, + * as of JDK 1.4. + * + * @author Dawid Kurzyniec + * @version 1.4 + */ +public abstract class SocketWrapper extends Socket { + + /** + * the wrapped delegate socket. + */ + protected final Socket delegate; + + /** + * Creates new socket wrapper for a given socket. The delegate + * must be connected and bound and it must not be closed. + * @param delegate the delegate socket to wrap + * @throws SocketException if the delegate socket is closed, not bound, + * or not connected + */ + protected SocketWrapper(Socket delegate) throws SocketException { + super(new WrappingSocketImpl(delegate)); + this.delegate = delegate; + } + + public SocketChannel getChannel() { + return delegate.getChannel(); + } + + /** + * Returns true, indicating that the socket is bound. + * + * @return true + */ + public boolean isBound() { + return true; + } + + public boolean isClosed() { + return super.isClosed() || delegate.isClosed(); + } + + /** + * Returns true, indicating that the socket is connected. + * + * @return true + */ + public boolean isConnected() { + return true; + } + + public boolean isInputShutdown() { + return super.isInputShutdown() || delegate.isInputShutdown(); + } + + public boolean isOutputShutdown() { + return super.isInputShutdown() || delegate.isOutputShutdown(); + } + + private static class WrappingSocketImpl extends SocketImpl { + private final Socket delegate; + WrappingSocketImpl(Socket delegate) throws SocketException { + if (delegate == null) { + throw new NullPointerException(); + } + if (delegate.isClosed()) { + throw new SocketException("Delegate server socket is closed"); + } + if (!(delegate.isBound())) { + throw new SocketException("Delegate server socket is not bound"); + } + if (!(delegate.isConnected())) { + throw new SocketException("Delegate server socket is not connected"); + } + this.delegate = delegate; + } + + protected void create(boolean stream) {} + + protected void connect(String host, int port) { + // delegate is always connected, thus this method is never called + throw new UnsupportedOperationException(); + } + + protected void connect(InetAddress address, int port) { + // delegate is always connected, thus this method is never called + throw new UnsupportedOperationException(); + } + + protected void connect(SocketAddress address, int timeout) { + // delegate is always connected, thus this method is never called + throw new UnsupportedOperationException(); + } + + protected void bind(InetAddress host, int port) { + // delegate is always bound, thus this method is never called + throw new UnsupportedOperationException(); + } + + protected void listen(int backlog) { + // this wrapper is never used by a ServerSocket + throw new UnsupportedOperationException(); + } + + protected void accept(SocketImpl s) { + // this wrapper is never used by a ServerSocket + throw new UnsupportedOperationException(); + } + + protected InputStream getInputStream() throws IOException { + return delegate.getInputStream(); + } + + protected OutputStream getOutputStream() throws IOException { + return delegate.getOutputStream(); + } + + protected int available() throws IOException { + return getInputStream().available(); + } + + protected void close() throws IOException { + delegate.close(); + } + + protected void shutdownInput() throws IOException { + delegate.shutdownInput(); + } + + protected void shutdownOutput() throws IOException { + delegate.shutdownOutput(); + } + + protected FileDescriptor getFileDescriptor() { + // this wrapper is never used by a ServerSocket + throw new UnsupportedOperationException(); + } + + protected InetAddress getInetAddress() { + return delegate.getInetAddress(); + } + + protected int getPort() { + return delegate.getPort(); + } + + protected boolean supportsUrgentData() { + return false; // must be overridden in sub-class + } + + protected void sendUrgentData (int data) throws IOException { + delegate.sendUrgentData(data); + } + + protected int getLocalPort() { + return delegate.getLocalPort(); + } + + public Object getOption(int optID) throws SocketException { + switch (optID) { + case SocketOptions.IP_TOS: + return new Integer(delegate.getTrafficClass()); + case SocketOptions.SO_BINDADDR: + return delegate.getLocalAddress(); + case SocketOptions.SO_KEEPALIVE: + return Boolean.valueOf(delegate.getKeepAlive()); + case SocketOptions.SO_LINGER: + return new Integer(delegate.getSoLinger()); + case SocketOptions.SO_OOBINLINE: + return Boolean.valueOf(delegate.getOOBInline()); + case SocketOptions.SO_RCVBUF: + return new Integer(delegate.getReceiveBufferSize()); + case SocketOptions.SO_REUSEADDR: + return Boolean.valueOf(delegate.getReuseAddress()); + case SocketOptions.SO_SNDBUF: + return new Integer(delegate.getSendBufferSize()); + case SocketOptions.SO_TIMEOUT: + return new Integer(delegate.getSoTimeout()); + case SocketOptions.TCP_NODELAY: + return Boolean.valueOf(delegate.getTcpNoDelay()); + case SocketOptions.SO_BROADCAST: + default: + throw new IllegalArgumentException("Unsupported option type"); + } + } + + public void setOption(int optID, Object value) throws SocketException { + switch (optID) { + case SocketOptions.SO_BINDADDR: + throw new IllegalArgumentException("Socket is bound"); + case SocketOptions.SO_KEEPALIVE: + delegate.setKeepAlive(((Boolean)value).booleanValue()); + break; + case SocketOptions.SO_LINGER: + if (value instanceof Boolean) { + delegate.setSoLinger(((Boolean)value).booleanValue(), 0); + } + else { + delegate.setSoLinger(true, ((Integer)value).intValue()); + } + break; + case SocketOptions.SO_OOBINLINE: + delegate.setOOBInline(((Boolean)value).booleanValue()); + break; + case SocketOptions.SO_RCVBUF: + delegate.setReceiveBufferSize(((Integer)value).intValue()); + break; + case SocketOptions.SO_REUSEADDR: + delegate.setReuseAddress(((Boolean)value).booleanValue()); + break; + case SocketOptions.SO_SNDBUF: + delegate.setSendBufferSize(((Integer)value).intValue()); + break; + case SocketOptions.SO_TIMEOUT: + delegate.setSoTimeout(((Integer)value).intValue()); + break; + case SocketOptions.TCP_NODELAY: + delegate.setTcpNoDelay(((Boolean)value).booleanValue()); + break; + case SocketOptions.SO_BROADCAST: + default: + throw new IllegalArgumentException("Unsupported option type"); + } + } + } + + public boolean equals(Object obj) { + if (!(obj instanceof SocketWrapper)) return false; + SocketWrapper that = (SocketWrapper)obj; + return this.delegate.equals(that.delegate); + } + + public int hashCode() { + return delegate.hashCode() ^ 0x01010101; + } +} \ No newline at end of file