2 * Written by Dawid Kurzyniec and released to the public domain, as explained
3 * at http://creativecommons.org/licenses/publicdomain
6 //package edu.emory.mathcs.util.net;
10 import java.nio.channels.*;
13 * Wrapper for sockets which enables to add functionality in subclasses
14 * on top of existing, connected sockets. It is useful when direct subclassing
15 * of delegate socket class is not possible, e.g. if the delegate socket is
16 * created by a library. Possible usage example is socket factory chaining.
17 * This class delegates all socket-related requests to the wrapped delegate,
20 * @author Dawid Kurzyniec
23 public abstract class SocketWrapper extends Socket {
26 * the wrapped delegate socket.
28 protected final Socket delegate;
31 * Creates new socket wrapper for a given socket. The delegate
32 * must be connected and bound and it must not be closed.
33 * @param delegate the delegate socket to wrap
34 * @throws SocketException if the delegate socket is closed, not bound,
37 protected SocketWrapper(Socket delegate) throws SocketException {
38 super(new WrappingSocketImpl(delegate));
39 this.delegate = delegate;
42 public SocketChannel getChannel() {
43 return delegate.getChannel();
47 * Returns true, indicating that the socket is bound.
51 public boolean isBound() {
55 public boolean isClosed() {
56 return super.isClosed() || delegate.isClosed();
60 * Returns true, indicating that the socket is connected.
64 public boolean isConnected() {
68 public boolean isInputShutdown() {
69 return super.isInputShutdown() || delegate.isInputShutdown();
72 public boolean isOutputShutdown() {
73 return super.isInputShutdown() || delegate.isOutputShutdown();
76 private static class WrappingSocketImpl extends SocketImpl {
77 private final Socket delegate;
78 WrappingSocketImpl(Socket delegate) throws SocketException {
79 if (delegate == null) {
80 throw new NullPointerException();
82 if (delegate.isClosed()) {
83 throw new SocketException("Delegate server socket is closed");
85 if (!(delegate.isBound())) {
86 throw new SocketException("Delegate server socket is not bound");
88 if (!(delegate.isConnected())) {
89 throw new SocketException("Delegate server socket is not connected");
91 this.delegate = delegate;
94 protected void create(boolean stream) {}
96 protected void connect(String host, int port) {
97 // delegate is always connected, thus this method is never called
98 throw new UnsupportedOperationException();
101 protected void connect(InetAddress address, int port) {
102 // delegate is always connected, thus this method is never called
103 throw new UnsupportedOperationException();
106 protected void connect(SocketAddress address, int timeout) {
107 // delegate is always connected, thus this method is never called
108 throw new UnsupportedOperationException();
111 protected void bind(InetAddress host, int port) {
112 // delegate is always bound, thus this method is never called
113 throw new UnsupportedOperationException();
116 protected void listen(int backlog) {
117 // this wrapper is never used by a ServerSocket
118 throw new UnsupportedOperationException();
121 protected void accept(SocketImpl s) {
122 // this wrapper is never used by a ServerSocket
123 throw new UnsupportedOperationException();
126 protected InputStream getInputStream() throws IOException {
127 return delegate.getInputStream();
130 protected OutputStream getOutputStream() throws IOException {
131 return delegate.getOutputStream();
134 protected int available() throws IOException {
135 return getInputStream().available();
138 protected void close() throws IOException {
142 protected void shutdownInput() throws IOException {
143 delegate.shutdownInput();
146 protected void shutdownOutput() throws IOException {
147 delegate.shutdownOutput();
150 protected FileDescriptor getFileDescriptor() {
151 // this wrapper is never used by a ServerSocket
152 throw new UnsupportedOperationException();
155 protected InetAddress getInetAddress() {
156 return delegate.getInetAddress();
159 protected int getPort() {
160 return delegate.getPort();
163 protected boolean supportsUrgentData() {
164 return false; // must be overridden in sub-class
167 protected void sendUrgentData (int data) throws IOException {
168 delegate.sendUrgentData(data);
171 protected int getLocalPort() {
172 return delegate.getLocalPort();
175 public Object getOption(int optID) throws SocketException {
177 case SocketOptions.IP_TOS:
178 return new Integer(delegate.getTrafficClass());
179 case SocketOptions.SO_BINDADDR:
180 return delegate.getLocalAddress();
181 case SocketOptions.SO_KEEPALIVE:
182 return Boolean.valueOf(delegate.getKeepAlive());
183 case SocketOptions.SO_LINGER:
184 return new Integer(delegate.getSoLinger());
185 case SocketOptions.SO_OOBINLINE:
186 return Boolean.valueOf(delegate.getOOBInline());
187 case SocketOptions.SO_RCVBUF:
188 return new Integer(delegate.getReceiveBufferSize());
189 case SocketOptions.SO_REUSEADDR:
190 return Boolean.valueOf(delegate.getReuseAddress());
191 case SocketOptions.SO_SNDBUF:
192 return new Integer(delegate.getSendBufferSize());
193 case SocketOptions.SO_TIMEOUT:
194 return new Integer(delegate.getSoTimeout());
195 case SocketOptions.TCP_NODELAY:
196 return Boolean.valueOf(delegate.getTcpNoDelay());
197 case SocketOptions.SO_BROADCAST:
199 throw new IllegalArgumentException("Unsupported option type");
203 public void setOption(int optID, Object value) throws SocketException {
205 case SocketOptions.SO_BINDADDR:
206 throw new IllegalArgumentException("Socket is bound");
207 case SocketOptions.SO_KEEPALIVE:
208 delegate.setKeepAlive(((Boolean)value).booleanValue());
210 case SocketOptions.SO_LINGER:
211 if (value instanceof Boolean) {
212 delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
215 delegate.setSoLinger(true, ((Integer)value).intValue());
218 case SocketOptions.SO_OOBINLINE:
219 delegate.setOOBInline(((Boolean)value).booleanValue());
221 case SocketOptions.SO_RCVBUF:
222 delegate.setReceiveBufferSize(((Integer)value).intValue());
224 case SocketOptions.SO_REUSEADDR:
225 delegate.setReuseAddress(((Boolean)value).booleanValue());
227 case SocketOptions.SO_SNDBUF:
228 delegate.setSendBufferSize(((Integer)value).intValue());
230 case SocketOptions.SO_TIMEOUT:
231 delegate.setSoTimeout(((Integer)value).intValue());
233 case SocketOptions.TCP_NODELAY:
234 delegate.setTcpNoDelay(((Boolean)value).booleanValue());
236 case SocketOptions.SO_BROADCAST:
238 throw new IllegalArgumentException("Unsupported option type");
243 public boolean equals(Object obj) {
244 if (!(obj instanceof SocketWrapper)) return false;
245 SocketWrapper that = (SocketWrapper)obj;
246 return this.delegate.equals(that.delegate);
249 public int hashCode() {
250 return delegate.hashCode() ^ 0x01010101;