source: trunk/vnc/vnc_javasrc/SocketWrapper.java @ 233

Last change on this file since 233 was 233, checked in by ecprice, 16 years ago

Actually close the connection on disconnect, fixing #3.

  • Property svn:keywords set to Rev
File size: 9.1 KB
Line 
1/*
2 * Written by Dawid Kurzyniec and released to the public domain, as explained
3 * at http://creativecommons.org/licenses/publicdomain
4 */
5
6//package edu.emory.mathcs.util.net;
7
8import java.io.*;
9import java.net.*;
10import java.nio.channels.*;
11
12/**
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,
18 * as of JDK 1.4.
19 *
20 * @author Dawid Kurzyniec
21 * @version 1.4
22 */
23public abstract class SocketWrapper extends Socket {
24
25    /**
26     * the wrapped delegate socket.
27     */
28    protected final Socket delegate;
29
30    /**
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,
35     *                         or not connected
36     */
37    protected SocketWrapper(Socket delegate) throws SocketException {
38        super(new WrappingSocketImpl(delegate));
39        this.delegate = delegate;
40        System.out.println("Creating SocketWrapper $Rev: 233 $");
41    }
42
43    public SocketChannel getChannel() {
44        return delegate.getChannel();
45    }
46
47    /**
48     * Returns true, indicating that the socket is bound.
49     *
50     * @return true
51     */
52    public boolean isBound() {
53        return true;
54    }
55
56    public boolean isClosed() {
57        return super.isClosed() || delegate.isClosed();
58    }
59
60    /**
61     * Returns true, indicating that the socket is connected.
62     *
63     * @return true
64     */
65    public boolean isConnected() {
66        return true;
67    }
68
69    public boolean isInputShutdown() {
70        return super.isInputShutdown() || delegate.isInputShutdown();
71    }
72
73    public boolean isOutputShutdown() {
74        return super.isInputShutdown() || delegate.isOutputShutdown();
75    }
76
77    private static class WrappingSocketImpl extends SocketImpl {
78        private final Socket delegate;
79        WrappingSocketImpl(Socket delegate) throws SocketException {
80            if (delegate == null) {
81                throw new NullPointerException();
82            }
83            if (delegate.isClosed()) {
84                throw new SocketException("Delegate server socket is closed");
85            }
86            if (!(delegate.isBound())) {
87                throw new SocketException("Delegate server socket is not bound");
88            }
89            if (!(delegate.isConnected())) {
90                throw new SocketException("Delegate server socket is not connected");
91            }
92            this.delegate = delegate;
93        }
94
95        protected void create(boolean stream) {}
96
97        protected void connect(String host, int port) {
98            // delegate is always connected, thus this method is never called
99            throw new UnsupportedOperationException();
100        }
101
102        protected void connect(InetAddress address, int port) {
103            // delegate is always connected, thus this method is never called
104            throw new UnsupportedOperationException();
105        }
106
107        protected void connect(SocketAddress address, int timeout) {
108            // delegate is always connected, thus this method is never called
109            throw new UnsupportedOperationException();
110        }
111
112        protected void bind(InetAddress host, int port) {
113            // delegate is always bound, thus this method is never called
114            throw new UnsupportedOperationException();
115        }
116
117        protected void listen(int backlog) {
118            // this wrapper is never used by a ServerSocket
119            throw new UnsupportedOperationException();
120        }
121
122        protected void accept(SocketImpl s) {
123            // this wrapper is never used by a ServerSocket
124            throw new UnsupportedOperationException();
125        }
126
127        protected InputStream getInputStream() throws IOException {
128            return delegate.getInputStream();
129        }
130
131        protected OutputStream getOutputStream() throws IOException {
132            return delegate.getOutputStream();
133        }
134
135        protected int available() throws IOException {
136            return getInputStream().available();
137        }
138
139        protected void close() throws IOException {
140            System.out.println("Calling delegate.close");
141            delegate.close();
142        }
143
144        protected void shutdownInput() throws IOException {
145            delegate.shutdownInput();
146        }
147
148        protected void shutdownOutput() throws IOException {
149            delegate.shutdownOutput();
150        }
151
152        protected FileDescriptor getFileDescriptor() {
153            // this wrapper is never used by a ServerSocket
154            throw new UnsupportedOperationException();
155        }
156
157        protected InetAddress getInetAddress() {
158            return delegate.getInetAddress();
159        }
160
161        protected int getPort() {
162            return delegate.getPort();
163        }
164
165        protected boolean supportsUrgentData() {
166            return false; // must be overridden in sub-class
167        }
168
169        protected void sendUrgentData (int data) throws IOException {
170            delegate.sendUrgentData(data);
171        }
172
173        protected int getLocalPort() {
174            return delegate.getLocalPort();
175        }
176
177        public Object getOption(int optID) throws SocketException {
178            switch (optID) {
179                case SocketOptions.IP_TOS:
180                    return new Integer(delegate.getTrafficClass());
181                case SocketOptions.SO_BINDADDR:
182                    return delegate.getLocalAddress();
183                case SocketOptions.SO_KEEPALIVE:
184                    return Boolean.valueOf(delegate.getKeepAlive());
185                case SocketOptions.SO_LINGER:
186                    return new Integer(delegate.getSoLinger());
187                case SocketOptions.SO_OOBINLINE:
188                    return Boolean.valueOf(delegate.getOOBInline());
189                case SocketOptions.SO_RCVBUF:
190                    return new Integer(delegate.getReceiveBufferSize());
191                case SocketOptions.SO_REUSEADDR:
192                    return Boolean.valueOf(delegate.getReuseAddress());
193                case SocketOptions.SO_SNDBUF:
194                    return new Integer(delegate.getSendBufferSize());
195                case SocketOptions.SO_TIMEOUT:
196                    return new Integer(delegate.getSoTimeout());
197                case SocketOptions.TCP_NODELAY:
198                    return Boolean.valueOf(delegate.getTcpNoDelay());
199                case SocketOptions.SO_BROADCAST:
200                default:
201                    throw new IllegalArgumentException("Unsupported option type");
202            }
203        }
204
205        public void setOption(int optID, Object value) throws SocketException {
206            switch (optID) {
207                case SocketOptions.SO_BINDADDR:
208                    throw new IllegalArgumentException("Socket is bound");
209                case SocketOptions.SO_KEEPALIVE:
210                    delegate.setKeepAlive(((Boolean)value).booleanValue());
211                    break;
212                case SocketOptions.SO_LINGER:
213                    if (value instanceof Boolean) {
214                        delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
215                    }
216                    else {
217                        delegate.setSoLinger(true, ((Integer)value).intValue());
218                    }
219                    break;
220                case SocketOptions.SO_OOBINLINE:
221                    delegate.setOOBInline(((Boolean)value).booleanValue());
222                    break;
223                case SocketOptions.SO_RCVBUF:
224                    delegate.setReceiveBufferSize(((Integer)value).intValue());
225                    break;
226                case SocketOptions.SO_REUSEADDR:
227                    delegate.setReuseAddress(((Boolean)value).booleanValue());
228                    break;
229                case SocketOptions.SO_SNDBUF:
230                    delegate.setSendBufferSize(((Integer)value).intValue());
231                    break;
232                case SocketOptions.SO_TIMEOUT:
233                    delegate.setSoTimeout(((Integer)value).intValue());
234                    break;
235                case SocketOptions.TCP_NODELAY:
236                    delegate.setTcpNoDelay(((Boolean)value).booleanValue());
237                    break;
238                case SocketOptions.SO_BROADCAST:
239                default:
240                    throw new IllegalArgumentException("Unsupported option type");
241            }
242        }
243    }
244
245    public void close() throws IOException {
246        System.out.println("Calling SocketWrapper.delegate.close");
247        delegate.close();
248    }
249
250    public boolean equals(Object obj) {
251        if (!(obj instanceof SocketWrapper)) return false;
252        SocketWrapper that = (SocketWrapper)obj;
253        return this.delegate.equals(that.delegate);
254    }
255
256    public int hashCode() {
257        return delegate.hashCode() ^ 0x01010101;
258    }
259    public String toString() {
260        return "<SocketWrapper " + super.toString() + "(delegating to " + delegate.toString() +  ")" + ">";
261    }
262}
Note: See TracBrowser for help on using the repository browser.