Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java
+++ new/src/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java
1 1 /*
2 2 * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25 package sun.rmi.transport.proxy;
26 26
27 27 import java.io.*;
28 28 import java.net.*;
29 29
30 30 import sun.rmi.runtime.Log;
31 31
32 32 /**
33 33 * The HttpSendSocket class extends the java.net.Socket class
34 34 * by enclosing the data output stream in, then extracting the input
35 35 * stream from, an HTTP protocol transmission.
36 36 *
37 37 * NOTES:
38 38 *
39 39 * Since the length of the output request must be known before the
40 40 * HTTP header can be completed, all of the output is buffered by
41 41 * an HttpOutputStream object until either an attempt is made to
42 42 * read from this socket, or the socket is explicitly closed.
43 43 *
44 44 * On the first read attempt to read from this socket, the buffered
45 45 * output is sent to the destination as the body of an HTTP POST
46 46 * request. All reads will then acquire data from the body of
47 47 * the response. A subsequent attempt to write to this socket will
48 48 * throw an IOException.
49 49 */
50 50 class HttpSendSocket extends Socket implements RMISocketInfo {
51 51
52 52 /** the host to connect to */
53 53 protected String host;
54 54
55 55 /** the port to connect to */
56 56 protected int port;
57 57
58 58 /** the URL to forward through */
59 59 protected URL url;
60 60
61 61 /** the object managing this connection through the URL */
62 62 protected URLConnection conn = null;
63 63
64 64 /** internal input stream for this socket */
65 65 protected InputStream in = null;
66 66
67 67 /** internal output stream for this socket */
68 68 protected OutputStream out = null;
69 69
70 70 /** the notifying input stream returned to users */
71 71 protected HttpSendInputStream inNotifier;
72 72
73 73 /** the notifying output stream returned to users */
74 74 protected HttpSendOutputStream outNotifier;
75 75
76 76 /**
77 77 * Line separator string. This is the value of the line.separator
78 78 * property at the moment that the socket was created.
79 79 */
80 80 private String lineSeparator =
81 81 java.security.AccessController.doPrivileged(
82 82 new sun.security.action.GetPropertyAction("line.separator"));
83 83
84 84 /**
85 85 * Create a stream socket and connect it to the specified port on
86 86 * the specified host.
87 87 * @param host the host
88 88 * @param port the port
89 89 */
90 90 public HttpSendSocket(String host, int port, URL url) throws IOException
91 91 {
92 92 super((SocketImpl)null); // no underlying SocketImpl for this object
93 93
94 94 if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) {
95 95 RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
96 96 "host = " + host + ", port = " + port + ", url = " + url);
97 97 }
98 98
99 99 this.host = host;
100 100 this.port = port;
101 101 this.url = url;
102 102
103 103 inNotifier = new HttpSendInputStream(null, this);
104 104 outNotifier = new HttpSendOutputStream(writeNotify(), this);
105 105 }
106 106
107 107 /**
108 108 * Create a stream socket and connect it to the specified port on
109 109 * the specified host.
110 110 * @param host the host
111 111 * @param port the port
112 112 */
113 113 public HttpSendSocket(String host, int port) throws IOException
114 114 {
115 115 this(host, port, new URL("http", host, port, "/"));
116 116 }
117 117
118 118 /**
119 119 * Create a stream socket and connect it to the specified address on
120 120 * the specified port.
121 121 * @param address the address
122 122 * @param port the port
123 123 */
124 124 public HttpSendSocket(InetAddress address, int port) throws IOException
125 125 {
126 126 this(address.getHostName(), port);
127 127 }
128 128
129 129 /**
130 130 * Indicate that this socket is not reusable.
131 131 */
132 132 public boolean isReusable()
133 133 {
134 134 return false;
135 135 }
136 136
137 137 /**
138 138 * Create a new socket connection to host (or proxy), and prepare to
139 139 * send HTTP transmission.
140 140 */
141 141 public synchronized OutputStream writeNotify() throws IOException
142 142 {
143 143 if (conn != null) {
144 144 throw new IOException("attempt to write on HttpSendSocket after " +
145 145 "request has been sent");
146 146 }
147 147
148 148 conn = url.openConnection();
149 149 conn.setDoOutput(true);
150 150 conn.setUseCaches(false);
151 151 conn.setRequestProperty("Content-type", "application/octet-stream");
152 152
153 153 inNotifier.deactivate();
154 154 in = null;
155 155
156 156 return out = conn.getOutputStream();
157 157 }
158 158
159 159 /**
160 160 * Send HTTP output transmission and prepare to receive response.
161 161 */
162 162 public synchronized InputStream readNotify() throws IOException
163 163 {
164 164 RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE,
165 165 "sending request and activating input stream");
166 166
167 167 outNotifier.deactivate();
168 168 out.close();
169 169 out = null;
170 170
171 171 try {
172 172 in = conn.getInputStream();
173 173 } catch (IOException e) {
174 174 RMIMasterSocketFactory.proxyLog.log(Log.BRIEF,
175 175 "failed to get input stream, exception: ", e);
176 176
177 177 throw new IOException("HTTP request failed");
178 178 }
179 179
180 180 /*
181 181 * If an HTTP error response is returned, sometimes an IOException
182 182 * is thrown, which is handled above, and other times it isn't, and
183 183 * the error response body will be available for reading.
184 184 * As a safety net to catch any such unexpected HTTP behavior, we
185 185 * verify that the content type of the response is what the
186 186 * HttpOutputStream generates: "application/octet-stream".
187 187 * (Servers' error responses will generally be "text/html".)
188 188 * Any error response body is printed to the log.
189 189 */
190 190 String contentType = conn.getContentType();
191 191 if (contentType == null ||
192 192 !conn.getContentType().equals("application/octet-stream"))
193 193 {
194 194 if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) {
195 195 String message;
↓ open down ↓ |
195 lines elided |
↑ open up ↑ |
196 196 if (contentType == null) {
197 197 message = "missing content type in response" +
198 198 lineSeparator;
199 199 } else {
200 200 message = "invalid content type in response: " +
201 201 contentType + lineSeparator;
202 202 }
203 203
204 204 message += "HttpSendSocket.readNotify: response body: ";
205 205 try {
206 - DataInputStream din = new DataInputStream(in);
206 + BufferedReader din = new BufferedReader(new InputStreamReader(in));
207 207 String line;
208 208 while ((line = din.readLine()) != null)
209 209 message += line + lineSeparator;
210 210 } catch (IOException e) {
211 211 }
212 212 RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message);
213 213 }
214 214
215 215 throw new IOException("HTTP request failed");
216 216 }
217 217
218 218 return in;
219 219 }
220 220
221 221 /**
222 222 * Get the address to which the socket is connected.
223 223 */
224 224 public InetAddress getInetAddress()
225 225 {
226 226 try {
227 227 return InetAddress.getByName(host);
228 228 } catch (UnknownHostException e) {
229 229 return null; // null if couldn't resolve destination host
230 230 }
231 231 }
232 232
233 233 /**
234 234 * Get the local address to which the socket is bound.
235 235 */
236 236 public InetAddress getLocalAddress()
237 237 {
238 238 try {
239 239 return InetAddress.getLocalHost();
240 240 } catch (UnknownHostException e) {
241 241 return null; // null if couldn't determine local host
242 242 }
243 243 }
244 244
245 245 /**
246 246 * Get the remote port to which the socket is connected.
247 247 */
248 248 public int getPort()
249 249 {
250 250 return port;
251 251 }
252 252
253 253 /**
254 254 * Get the local port to which the socket is connected.
255 255 */
256 256 public int getLocalPort()
257 257 {
258 258 return -1; // request not applicable to this socket type
259 259 }
260 260
261 261 /**
262 262 * Get an InputStream for this socket.
263 263 */
264 264 public InputStream getInputStream() throws IOException
265 265 {
266 266 return inNotifier;
267 267 }
268 268
269 269 /**
270 270 * Get an OutputStream for this socket.
271 271 */
272 272 public OutputStream getOutputStream() throws IOException
273 273 {
274 274 return outNotifier;
275 275 }
276 276
277 277 /**
278 278 * Enable/disable TCP_NODELAY.
279 279 * This operation has no effect for an HttpSendSocket.
280 280 */
281 281 public void setTcpNoDelay(boolean on) throws SocketException
282 282 {
283 283 }
284 284
285 285 /**
286 286 * Retrieve whether TCP_NODELAY is enabled.
287 287 */
288 288 public boolean getTcpNoDelay() throws SocketException
289 289 {
290 290 return false; // imply option is disabled
291 291 }
292 292
293 293 /**
294 294 * Enable/disable SO_LINGER with the specified linger time.
295 295 * This operation has no effect for an HttpSendSocket.
296 296 */
297 297 public void setSoLinger(boolean on, int val) throws SocketException
298 298 {
299 299 }
300 300
301 301 /**
302 302 * Retrive setting for SO_LINGER.
303 303 */
304 304 public int getSoLinger() throws SocketException
305 305 {
306 306 return -1; // imply option is disabled
307 307 }
308 308
309 309 /**
310 310 * Enable/disable SO_TIMEOUT with the specified timeout
311 311 * This operation has no effect for an HttpSendSocket.
312 312 */
313 313 public synchronized void setSoTimeout(int timeout) throws SocketException
314 314 {
315 315 }
316 316
317 317 /**
318 318 * Retrive setting for SO_TIMEOUT.
319 319 */
320 320 public synchronized int getSoTimeout() throws SocketException
321 321 {
322 322 return 0; // imply option is disabled
323 323 }
324 324
325 325 /**
326 326 * Close the socket.
327 327 */
328 328 public synchronized void close() throws IOException
329 329 {
330 330 if (out != null) // push out transmission if not done
331 331 out.close();
332 332 }
333 333
334 334 /**
335 335 * Return string representation of this pseudo-socket.
336 336 */
337 337 public String toString()
338 338 {
339 339 return "HttpSendSocket[host=" + host +
340 340 ",port=" + port +
341 341 ",url=" + url + "]";
342 342 }
343 343 }
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX