jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
changeset 74 068494063b1b
parent 2 90ce3da70b43
child 78 65353d0d0e31
equal deleted inserted replaced
73:cf334423502b 74:068494063b1b
    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                     }
   948             }
   939             }
   949 
   940 
   950         } // end of getting cookies
   941         } // end of getting cookies
   951     }
   942     }
   952 
   943 
       
   944     @Override
       
   945     @SuppressWarnings("empty-statement")
   953     public synchronized InputStream getInputStream() throws IOException {
   946     public synchronized InputStream getInputStream() throws IOException {
   954 
   947 
   955         if (!doInput) {
   948         if (!doInput) {
   956             throw new ProtocolException("Cannot read from URLConnection"
   949             throw new ProtocolException("Cannot read from URLConnection"
   957                    + " if doInput=false (call setDoInput(true))");
   950                    + " if doInput=false (call setDoInput(true))");
  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;
  2150 
  2144 
  2151     /**
  2145     /**
  2152      * Gets a header field by name. Returns null if not known.
  2146      * Gets a header field by name. Returns null if not known.
  2153      * @param name the name of the header field
  2147      * @param name the name of the header field
  2154      */
  2148      */
       
  2149     @Override
  2155     public String getHeaderField(String name) {
  2150     public String getHeaderField(String name) {
  2156         try {
  2151         try {
  2157             getInputStream();
  2152             getInputStream();
  2158         } catch (IOException e) {}
  2153         } catch (IOException e) {}
  2159 
  2154 
  2172      * the corresponding field values.
  2167      * the corresponding field values.
  2173      *
  2168      *
  2174      * @return a Map of header fields
  2169      * @return a Map of header fields
  2175      * @since 1.4
  2170      * @since 1.4
  2176      */
  2171      */
       
  2172     @Override
  2177     public Map getHeaderFields() {
  2173     public Map getHeaderFields() {
  2178         try {
  2174         try {
  2179             getInputStream();
  2175             getInputStream();
  2180         } catch (IOException e) {}
  2176         } catch (IOException e) {}
  2181 
  2177 
  2188 
  2184 
  2189     /**
  2185     /**
  2190      * Gets a header field by index. Returns null if not known.
  2186      * Gets a header field by index. Returns null if not known.
  2191      * @param n the index of the header field
  2187      * @param n the index of the header field
  2192      */
  2188      */
       
  2189     @Override
  2193     public String getHeaderField(int n) {
  2190     public String getHeaderField(int n) {
  2194         try {
  2191         try {
  2195             getInputStream();
  2192             getInputStream();
  2196         } catch (IOException e) {}
  2193         } catch (IOException e) {}
  2197 
  2194 
  2203 
  2200 
  2204     /**
  2201     /**
  2205      * Gets a header field by index. Returns null if not known.
  2202      * Gets a header field by index. Returns null if not known.
  2206      * @param n the index of the header field
  2203      * @param n the index of the header field
  2207      */
  2204      */
       
  2205     @Override
  2208     public String getHeaderFieldKey(int n) {
  2206     public String getHeaderFieldKey(int n) {
  2209         try {
  2207         try {
  2210             getInputStream();
  2208             getInputStream();
  2211         } catch (IOException e) {}
  2209         } catch (IOException e) {}
  2212 
  2210 
  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
  2519                 }
  2531                 }
  2520                 throw ioex;
  2532                 throw ioex;
  2521             }
  2533             }
  2522         }
  2534         }
  2523 
  2535 
       
  2536         @Override
  2524         public void close () throws IOException {
  2537         public void close () throws IOException {
  2525             try {
  2538             try {
  2526                 if (outputStream != null) {
  2539                 if (outputStream != null) {
  2527                     if (read() != -1) {
  2540                     if (read() != -1) {
  2528                         cacheRequest.abort();
  2541                         cacheRequest.abort();
  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 ();
  2606          */
  2622          */
  2607         boolean writtenOK () {
  2623         boolean writtenOK () {
  2608             return closed && ! error;
  2624             return closed && ! error;
  2609         }
  2625         }
  2610 
  2626 
       
  2627         @Override
  2611         public void close () throws IOException {
  2628         public void close () throws IOException {
  2612             if (closed) {
  2629             if (closed) {
  2613                 return;
  2630                 return;
  2614             }
  2631             }
  2615             closed = true;
  2632             closed = true;
  2724                 // ioex.printStackTrace();
  2741                 // ioex.printStackTrace();
  2725                 return null;
  2742                 return null;
  2726             }
  2743             }
  2727         }
  2744         }
  2728 
  2745 
       
  2746         @Override
  2729         public int available() throws IOException {
  2747         public int available() throws IOException {
  2730             if (is == null) {
  2748             if (is == null) {
  2731                 return buffer.remaining();
  2749                 return buffer.remaining();
  2732             } else {
  2750             } else {
  2733                 return buffer.remaining()+is.available();
  2751                 return buffer.remaining()+is.available();
  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);
  2757                     return is.read(b, off, len);
  2777                     return is.read(b, off, len);
  2758                 }
  2778                 }
  2759             }
  2779             }
  2760         }
  2780         }
  2761 
  2781 
       
  2782         @Override
  2762         public void close() throws IOException {
  2783         public void close() throws IOException {
  2763             buffer = null;
  2784             buffer = null;
  2764             if (is != null) {
  2785             if (is != null) {
  2765                 is.close();
  2786                 is.close();
  2766             }
  2787             }
  2773  * HEAD method - i.e., stream not dead, but nothing to be read.
  2794  * HEAD method - i.e., stream not dead, but nothing to be read.
  2774  */
  2795  */
  2775 
  2796 
  2776 class EmptyInputStream extends InputStream {
  2797 class EmptyInputStream extends InputStream {
  2777 
  2798 
       
  2799     @Override
  2778     public int available() {
  2800     public int available() {
  2779         return 0;
  2801         return 0;
  2780     }
  2802     }
  2781 
  2803 
  2782     public int read() {
  2804     public int read() {