62 import sun.net.www.http.ChunkedOutputStream; |
62 import sun.net.www.http.ChunkedOutputStream; |
63 import java.text.SimpleDateFormat; |
63 import java.text.SimpleDateFormat; |
64 import java.util.TimeZone; |
64 import java.util.TimeZone; |
65 import java.net.MalformedURLException; |
65 import java.net.MalformedURLException; |
66 import java.nio.ByteBuffer; |
66 import java.nio.ByteBuffer; |
67 import java.nio.channels.ReadableByteChannel; |
|
68 import java.nio.channels.WritableByteChannel; |
|
69 import java.nio.channels.Selector; |
|
70 import java.nio.channels.SelectionKey; |
|
71 import java.nio.channels.SelectableChannel; |
|
72 import java.lang.reflect.*; |
67 import java.lang.reflect.*; |
73 |
68 |
74 /** |
69 /** |
75 * A class to represent an HTTP connection to a remote object. |
70 * A class to represent an HTTP connection to a remote object. |
76 */ |
71 */ |
822 * - get input, [read input] |
817 * - get input, [read input] |
823 * Disallowed: |
818 * Disallowed: |
824 * - get input, [read input,] get output, [write output] |
819 * - get input, [read input,] get output, [write output] |
825 */ |
820 */ |
826 |
821 |
|
822 @Override |
827 public synchronized OutputStream getOutputStream() throws IOException { |
823 public synchronized OutputStream getOutputStream() throws IOException { |
828 |
824 |
829 try { |
825 try { |
830 if (!doOutput) { |
826 if (!doOutput) { |
831 throw new ProtocolException("cannot write to a URLConnection" |
827 throw new ProtocolException("cannot write to a URLConnection" |
906 // remove old Cookie header before setting new one. |
902 // remove old Cookie header before setting new one. |
907 requests.remove("Cookie"); |
903 requests.remove("Cookie"); |
908 |
904 |
909 URI uri = ParseUtil.toURI(url); |
905 URI uri = ParseUtil.toURI(url); |
910 if (uri != null) { |
906 if (uri != null) { |
911 Map cookies = cookieHandler.get(uri, requests.getHeaders(EXCLUDE_HEADERS)); |
907 Map<String, List<String>> cookies = cookieHandler.get(uri, requests.getHeaders(EXCLUDE_HEADERS)); |
912 if (!cookies.isEmpty()) { |
908 if (!cookies.isEmpty()) { |
913 Set s = cookies.entrySet(); |
909 for (Map.Entry<String, List<String>> entry : cookies.entrySet()) { |
914 Iterator k_itr = s.iterator(); |
910 String key = entry.getKey(); |
915 while (k_itr.hasNext()) { |
|
916 Map.Entry entry = (Map.Entry)k_itr.next(); |
|
917 String key = (String)entry.getKey(); |
|
918 // ignore all entries that don't have "Cookie" |
911 // ignore all entries that don't have "Cookie" |
919 // or "Cookie2" as keys |
912 // or "Cookie2" as keys |
920 if (!"Cookie".equalsIgnoreCase(key) && |
913 if (!"Cookie".equalsIgnoreCase(key) && |
921 !"Cookie2".equalsIgnoreCase(key)) { |
914 !"Cookie2".equalsIgnoreCase(key)) { |
922 continue; |
915 continue; |
923 } |
916 } |
924 List l = (List)entry.getValue(); |
917 List<String> l = entry.getValue(); |
925 if (l != null && !l.isEmpty()) { |
918 if (l != null && !l.isEmpty()) { |
926 Iterator v_itr = l.iterator(); |
|
927 StringBuilder cookieValue = new StringBuilder(); |
919 StringBuilder cookieValue = new StringBuilder(); |
928 while (v_itr.hasNext()) { |
920 for (String value : l) { |
929 String value = (String)v_itr.next(); |
921 cookieValue.append(value).append("; "); |
930 cookieValue.append(value).append(';'); |
|
931 } |
922 } |
932 // strip off the ending ;-sign |
923 // strip off the trailing '; ' |
933 try { |
924 try { |
934 requests.add(key, cookieValue.substring(0, cookieValue.length() - 1)); |
925 requests.add(key, cookieValue.substring(0, cookieValue.length() - 2)); |
935 } catch (StringIndexOutOfBoundsException ignored) { |
926 } catch (StringIndexOutOfBoundsException ignored) { |
936 // no-op |
927 // no-op |
937 } |
928 } |
938 } |
929 } |
939 } |
930 } |
1384 } catch (Exception ignored) { |
1377 } catch (Exception ignored) { |
1385 return rememberedException; |
1378 return rememberedException; |
1386 } |
1379 } |
1387 } |
1380 } |
1388 |
1381 |
|
1382 @Override |
1389 public InputStream getErrorStream() { |
1383 public InputStream getErrorStream() { |
1390 if (connected && responseCode >= 400) { |
1384 if (connected && responseCode >= 400) { |
1391 // Client Error 4xx and Server Error 5xx |
1385 // Client Error 4xx and Server Error 5xx |
1392 if (errorStream != null) { |
1386 if (errorStream != null) { |
1393 return errorStream; |
1387 return errorStream; |
2220 /** |
2218 /** |
2221 * Sets request property. If a property with the key already |
2219 * Sets request property. If a property with the key already |
2222 * exists, overwrite its value with the new value. |
2220 * exists, overwrite its value with the new value. |
2223 * @param value the value to be set |
2221 * @param value the value to be set |
2224 */ |
2222 */ |
|
2223 @Override |
2225 public void setRequestProperty(String key, String value) { |
2224 public void setRequestProperty(String key, String value) { |
2226 if (connected) |
2225 if (connected) |
2227 throw new IllegalStateException("Already connected"); |
2226 throw new IllegalStateException("Already connected"); |
2228 if (key == null) |
2227 if (key == null) |
2229 throw new NullPointerException ("key is null"); |
2228 throw new NullPointerException ("key is null"); |
2241 * (e.g., "<code>accept</code>"). |
2240 * (e.g., "<code>accept</code>"). |
2242 * @param value the value associated with it. |
2241 * @param value the value associated with it. |
2243 * @see #getRequestProperties(java.lang.String) |
2242 * @see #getRequestProperties(java.lang.String) |
2244 * @since 1.4 |
2243 * @since 1.4 |
2245 */ |
2244 */ |
|
2245 @Override |
2246 public void addRequestProperty(String key, String value) { |
2246 public void addRequestProperty(String key, String value) { |
2247 if (connected) |
2247 if (connected) |
2248 throw new IllegalStateException("Already connected"); |
2248 throw new IllegalStateException("Already connected"); |
2249 if (key == null) |
2249 if (key == null) |
2250 throw new NullPointerException ("key is null"); |
2250 throw new NullPointerException ("key is null"); |
2260 void setAuthenticationProperty(String key, String value) { |
2260 void setAuthenticationProperty(String key, String value) { |
2261 checkMessageHeader(key, value); |
2261 checkMessageHeader(key, value); |
2262 requests.set(key, value); |
2262 requests.set(key, value); |
2263 } |
2263 } |
2264 |
2264 |
|
2265 @Override |
2265 public String getRequestProperty (String key) { |
2266 public String getRequestProperty (String key) { |
2266 // don't return headers containing security sensitive information |
2267 // don't return headers containing security sensitive information |
2267 if (key != null) { |
2268 if (key != null) { |
2268 for (int i=0; i < EXCLUDE_HEADERS.length; i++) { |
2269 for (int i=0; i < EXCLUDE_HEADERS.length; i++) { |
2269 if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) { |
2270 if (key.equalsIgnoreCase(EXCLUDE_HEADERS[i])) { |
2284 * |
2285 * |
2285 * @return a Map of the general request properties for this connection. |
2286 * @return a Map of the general request properties for this connection. |
2286 * @throws IllegalStateException if already connected |
2287 * @throws IllegalStateException if already connected |
2287 * @since 1.4 |
2288 * @since 1.4 |
2288 */ |
2289 */ |
|
2290 @Override |
2289 public Map getRequestProperties() { |
2291 public Map getRequestProperties() { |
2290 if (connected) |
2292 if (connected) |
2291 throw new IllegalStateException("Already connected"); |
2293 throw new IllegalStateException("Already connected"); |
2292 |
2294 |
2293 // exclude headers containing security-sensitive info |
2295 // exclude headers containing security-sensitive info |
2294 return requests.getHeaders(EXCLUDE_HEADERS); |
2296 return requests.getHeaders(EXCLUDE_HEADERS); |
2295 } |
2297 } |
2296 |
2298 |
|
2299 @Override |
2297 public void setConnectTimeout(int timeout) { |
2300 public void setConnectTimeout(int timeout) { |
2298 if (timeout < 0) |
2301 if (timeout < 0) |
2299 throw new IllegalArgumentException("timeouts can't be negative"); |
2302 throw new IllegalArgumentException("timeouts can't be negative"); |
2300 connectTimeout = timeout; |
2303 connectTimeout = timeout; |
2301 } |
2304 } |
2311 * value in milliseconds |
2314 * value in milliseconds |
2312 * @see java.net.URLConnection#setConnectTimeout(int) |
2315 * @see java.net.URLConnection#setConnectTimeout(int) |
2313 * @see java.net.URLConnection#connect() |
2316 * @see java.net.URLConnection#connect() |
2314 * @since 1.5 |
2317 * @since 1.5 |
2315 */ |
2318 */ |
|
2319 @Override |
2316 public int getConnectTimeout() { |
2320 public int getConnectTimeout() { |
2317 return (connectTimeout < 0 ? 0 : connectTimeout); |
2321 return (connectTimeout < 0 ? 0 : connectTimeout); |
2318 } |
2322 } |
2319 |
2323 |
2320 /** |
2324 /** |
2335 * |
2339 * |
2336 * @see java.net.URLConnectiongetReadTimeout() |
2340 * @see java.net.URLConnectiongetReadTimeout() |
2337 * @see java.io.InputStream#read() |
2341 * @see java.io.InputStream#read() |
2338 * @since 1.5 |
2342 * @since 1.5 |
2339 */ |
2343 */ |
|
2344 @Override |
2340 public void setReadTimeout(int timeout) { |
2345 public void setReadTimeout(int timeout) { |
2341 if (timeout < 0) |
2346 if (timeout < 0) |
2342 throw new IllegalArgumentException("timeouts can't be negative"); |
2347 throw new IllegalArgumentException("timeouts can't be negative"); |
2343 readTimeout = timeout; |
2348 readTimeout = timeout; |
2344 } |
2349 } |
2352 * |
2357 * |
2353 * @see java.net.URLConnection#setReadTimeout(int) |
2358 * @see java.net.URLConnection#setReadTimeout(int) |
2354 * @see java.io.InputStream#read() |
2359 * @see java.io.InputStream#read() |
2355 * @since 1.5 |
2360 * @since 1.5 |
2356 */ |
2361 */ |
|
2362 @Override |
2357 public int getReadTimeout() { |
2363 public int getReadTimeout() { |
2358 return readTimeout < 0 ? 0 : readTimeout; |
2364 return readTimeout < 0 ? 0 : readTimeout; |
2359 } |
2365 } |
2360 |
2366 |
|
2367 @Override |
2361 protected void finalize() { |
2368 protected void finalize() { |
2362 // this should do nothing. The stream finalizer will close |
2369 // this should do nothing. The stream finalizer will close |
2363 // the fd |
2370 // the fd |
2364 } |
2371 } |
2365 |
2372 |
2435 * @param readlimit the maximum limit of bytes that can be read before |
2442 * @param readlimit the maximum limit of bytes that can be read before |
2436 * the mark position becomes invalid. |
2443 * the mark position becomes invalid. |
2437 * @see java.io.FilterInputStream#in |
2444 * @see java.io.FilterInputStream#in |
2438 * @see java.io.FilterInputStream#reset() |
2445 * @see java.io.FilterInputStream#reset() |
2439 */ |
2446 */ |
|
2447 @Override |
2440 public synchronized void mark(int readlimit) { |
2448 public synchronized void mark(int readlimit) { |
2441 super.mark(readlimit); |
2449 super.mark(readlimit); |
2442 if (cacheRequest != null) { |
2450 if (cacheRequest != null) { |
2443 marked = true; |
2451 marked = true; |
2444 markCount = 0; |
2452 markCount = 0; |
2464 * @exception IOException if the stream has not been marked or if the |
2472 * @exception IOException if the stream has not been marked or if the |
2465 * mark has been invalidated. |
2473 * mark has been invalidated. |
2466 * @see java.io.FilterInputStream#in |
2474 * @see java.io.FilterInputStream#in |
2467 * @see java.io.FilterInputStream#mark(int) |
2475 * @see java.io.FilterInputStream#mark(int) |
2468 */ |
2476 */ |
|
2477 @Override |
2469 public synchronized void reset() throws IOException { |
2478 public synchronized void reset() throws IOException { |
2470 super.reset(); |
2479 super.reset(); |
2471 if (cacheRequest != null) { |
2480 if (cacheRequest != null) { |
2472 marked = false; |
2481 marked = false; |
2473 inCache += markCount; |
2482 inCache += markCount; |
2474 } |
2483 } |
2475 } |
2484 } |
2476 |
2485 |
|
2486 @Override |
2477 public int read() throws IOException { |
2487 public int read() throws IOException { |
2478 try { |
2488 try { |
2479 byte[] b = new byte[1]; |
2489 byte[] b = new byte[1]; |
2480 int ret = read(b); |
2490 int ret = read(b); |
2481 return (ret == -1? ret : (b[0] & 0x00FF)); |
2491 return (ret == -1? ret : (b[0] & 0x00FF)); |
2485 } |
2495 } |
2486 throw ioex; |
2496 throw ioex; |
2487 } |
2497 } |
2488 } |
2498 } |
2489 |
2499 |
|
2500 @Override |
2490 public int read(byte[] b) throws IOException { |
2501 public int read(byte[] b) throws IOException { |
2491 return read(b, 0, b.length); |
2502 return read(b, 0, b.length); |
2492 } |
2503 } |
2493 |
2504 |
|
2505 @Override |
2494 public int read(byte[] b, int off, int len) throws IOException { |
2506 public int read(byte[] b, int off, int len) throws IOException { |
2495 try { |
2507 try { |
2496 int newLen = super.read(b, off, len); |
2508 int newLen = super.read(b, off, len); |
2497 int nWrite; |
2509 int nWrite; |
2498 // write to cache |
2510 // write to cache |
2563 written = 0; |
2576 written = 0; |
2564 closed = false; |
2577 closed = false; |
2565 error = false; |
2578 error = false; |
2566 } |
2579 } |
2567 |
2580 |
|
2581 @Override |
2568 public void write (int b) throws IOException { |
2582 public void write (int b) throws IOException { |
2569 checkError(); |
2583 checkError(); |
2570 written ++; |
2584 written ++; |
2571 if (expected != -1 && written > expected) { |
2585 if (expected != -1 && written > expected) { |
2572 throw new IOException ("too many bytes written"); |
2586 throw new IOException ("too many bytes written"); |
2573 } |
2587 } |
2574 out.write (b); |
2588 out.write (b); |
2575 } |
2589 } |
2576 |
2590 |
|
2591 @Override |
2577 public void write (byte[] b) throws IOException { |
2592 public void write (byte[] b) throws IOException { |
2578 write (b, 0, b.length); |
2593 write (b, 0, b.length); |
2579 } |
2594 } |
2580 |
2595 |
|
2596 @Override |
2581 public void write (byte[] b, int off, int len) throws IOException { |
2597 public void write (byte[] b, int off, int len) throws IOException { |
2582 checkError(); |
2598 checkError(); |
2583 written += len; |
2599 written += len; |
2584 if (expected != -1 && written > expected) { |
2600 if (expected != -1 && written > expected) { |
2585 out.close (); |
2601 out.close (); |
2738 byte[] b = new byte[1]; |
2756 byte[] b = new byte[1]; |
2739 int ret = read(b); |
2757 int ret = read(b); |
2740 return (ret == -1? ret : (b[0] & 0x00FF)); |
2758 return (ret == -1? ret : (b[0] & 0x00FF)); |
2741 } |
2759 } |
2742 |
2760 |
|
2761 @Override |
2743 public int read(byte[] b) throws IOException { |
2762 public int read(byte[] b) throws IOException { |
2744 return read(b, 0, b.length); |
2763 return read(b, 0, b.length); |
2745 } |
2764 } |
2746 |
2765 |
|
2766 @Override |
2747 public int read(byte[] b, int off, int len) throws IOException { |
2767 public int read(byte[] b, int off, int len) throws IOException { |
2748 int rem = buffer.remaining(); |
2768 int rem = buffer.remaining(); |
2749 if (rem > 0) { |
2769 if (rem > 0) { |
2750 int ret = rem < len? rem : len; |
2770 int ret = rem < len? rem : len; |
2751 buffer.get(b, off, ret); |
2771 buffer.get(b, off, ret); |