sipb-xen-vnc-client -> invirt-vnc-client
[invirt/packages/invirt-vnc-client.git] / SocketWrapper.java
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
8 import java.io.*;
9 import java.net.*;
10 import 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  */
23 public 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$");
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 }