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

Last change on this file since 196 was 143, checked in by quentin, 17 years ago

SSL support for VNC proxy

File size: 8.7 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    }
41
42    public SocketChannel getChannel() {
43        return delegate.getChannel();
44    }
45
46    /**
47     * Returns true, indicating that the socket is bound.
48     *
49     * @return true
50     */
51    public boolean isBound() {
52        return true;
53    }
54
55    public boolean isClosed() {
56        return super.isClosed() || delegate.isClosed();
57    }
58
59    /**
60     * Returns true, indicating that the socket is connected.
61     *
62     * @return true
63     */
64    public boolean isConnected() {
65        return true;
66    }
67
68    public boolean isInputShutdown() {
69        return super.isInputShutdown() || delegate.isInputShutdown();
70    }
71
72    public boolean isOutputShutdown() {
73        return super.isInputShutdown() || delegate.isOutputShutdown();
74    }
75
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();
81            }
82            if (delegate.isClosed()) {
83                throw new SocketException("Delegate server socket is closed");
84            }
85            if (!(delegate.isBound())) {
86                throw new SocketException("Delegate server socket is not bound");
87            }
88            if (!(delegate.isConnected())) {
89                throw new SocketException("Delegate server socket is not connected");
90            }
91            this.delegate = delegate;
92        }
93
94        protected void create(boolean stream) {}
95
96        protected void connect(String host, int port) {
97            // delegate is always connected, thus this method is never called
98            throw new UnsupportedOperationException();
99        }
100
101        protected void connect(InetAddress address, int port) {
102            // delegate is always connected, thus this method is never called
103            throw new UnsupportedOperationException();
104        }
105
106        protected void connect(SocketAddress address, int timeout) {
107            // delegate is always connected, thus this method is never called
108            throw new UnsupportedOperationException();
109        }
110
111        protected void bind(InetAddress host, int port) {
112            // delegate is always bound, thus this method is never called
113            throw new UnsupportedOperationException();
114        }
115
116        protected void listen(int backlog) {
117            // this wrapper is never used by a ServerSocket
118            throw new UnsupportedOperationException();
119        }
120
121        protected void accept(SocketImpl s) {
122            // this wrapper is never used by a ServerSocket
123            throw new UnsupportedOperationException();
124        }
125
126        protected InputStream getInputStream() throws IOException {
127            return delegate.getInputStream();
128        }
129
130        protected OutputStream getOutputStream() throws IOException {
131            return delegate.getOutputStream();
132        }
133
134        protected int available() throws IOException {
135            return getInputStream().available();
136        }
137
138        protected void close() throws IOException {
139            delegate.close();
140        }
141
142        protected void shutdownInput() throws IOException {
143            delegate.shutdownInput();
144        }
145
146        protected void shutdownOutput() throws IOException {
147            delegate.shutdownOutput();
148        }
149
150        protected FileDescriptor getFileDescriptor() {
151            // this wrapper is never used by a ServerSocket
152            throw new UnsupportedOperationException();
153        }
154
155        protected InetAddress getInetAddress() {
156            return delegate.getInetAddress();
157        }
158
159        protected int getPort() {
160            return delegate.getPort();
161        }
162
163        protected boolean supportsUrgentData() {
164            return false; // must be overridden in sub-class
165        }
166
167        protected void sendUrgentData (int data) throws IOException {
168            delegate.sendUrgentData(data);
169        }
170
171        protected int getLocalPort() {
172            return delegate.getLocalPort();
173        }
174
175        public Object getOption(int optID) throws SocketException {
176            switch (optID) {
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:
198                default:
199                    throw new IllegalArgumentException("Unsupported option type");
200            }
201        }
202
203        public void setOption(int optID, Object value) throws SocketException {
204            switch (optID) {
205                case SocketOptions.SO_BINDADDR:
206                    throw new IllegalArgumentException("Socket is bound");
207                case SocketOptions.SO_KEEPALIVE:
208                    delegate.setKeepAlive(((Boolean)value).booleanValue());
209                    break;
210                case SocketOptions.SO_LINGER:
211                    if (value instanceof Boolean) {
212                        delegate.setSoLinger(((Boolean)value).booleanValue(), 0);
213                    }
214                    else {
215                        delegate.setSoLinger(true, ((Integer)value).intValue());
216                    }
217                    break;
218                case SocketOptions.SO_OOBINLINE:
219                    delegate.setOOBInline(((Boolean)value).booleanValue());
220                    break;
221                case SocketOptions.SO_RCVBUF:
222                    delegate.setReceiveBufferSize(((Integer)value).intValue());
223                    break;
224                case SocketOptions.SO_REUSEADDR:
225                    delegate.setReuseAddress(((Boolean)value).booleanValue());
226                    break;
227                case SocketOptions.SO_SNDBUF:
228                    delegate.setSendBufferSize(((Integer)value).intValue());
229                    break;
230                case SocketOptions.SO_TIMEOUT:
231                    delegate.setSoTimeout(((Integer)value).intValue());
232                    break;
233                case SocketOptions.TCP_NODELAY:
234                    delegate.setTcpNoDelay(((Boolean)value).booleanValue());
235                    break;
236                case SocketOptions.SO_BROADCAST:
237                default:
238                    throw new IllegalArgumentException("Unsupported option type");
239            }
240        }
241    }
242
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);
247    }
248
249    public int hashCode() {
250        return delegate.hashCode() ^ 0x01010101;
251    }
252}
Note: See TracBrowser for help on using the repository browser.