OpenJDK / jdk / jdk
changeset 1576:b697b141012d
6755625: Add HttpURLConnection.setFixedLengthStreamingMode(long)
Reviewed-by: jccollet
author | chegar |
---|---|
date | Wed, 12 Nov 2008 16:38:17 +0000 |
parents | 9e7e14863b81 |
children | 6773c7793f38 |
files | jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java jdk/src/share/classes/java/net/HttpURLConnection.java jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java jdk/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java |
diffstat | 5 files changed, 101 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Tue Nov 11 09:07:58 2008 +0000 +++ b/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Wed Nov 12 16:38:17 2008 +0000 @@ -497,6 +497,10 @@ delegate.setFixedLengthStreamingMode(contentLength); } + public void setFixedLengthStreamingMode(long contentLength) { + delegate.setFixedLengthStreamingMode(contentLength); + } + public void setChunkedStreamingMode (int chunklen) { delegate.setChunkedStreamingMode(chunklen); }
--- a/jdk/src/share/classes/java/net/HttpURLConnection.java Tue Nov 11 09:07:58 2008 +0000 +++ b/jdk/src/share/classes/java/net/HttpURLConnection.java Wed Nov 12 16:38:17 2008 +0000 @@ -73,11 +73,24 @@ * The fixed content-length when using fixed-length streaming mode. * A value of <code>-1</code> means fixed-length streaming mode is disabled * for output. + * + * <P> <B>NOTE:</B> {@link #fixedContentLengthLong} is recommended instead + * of this field, as it allows larger content lengths to be set. + * * @since 1.5 */ protected int fixedContentLength = -1; /** + * The fixed content-length when using fixed-length streaming mode. + * A value of {@code -1} means fixed-length streaming mode is disabled + * for output. + * + * @since 1.7 + */ + protected long fixedContentLengthLong = -1; + + /** * Returns the key for the <code>n</code><sup>th</sup> header field. * Some implementations may treat the <code>0</code><sup>th</sup> * header field as special, i.e. as the status line returned by the HTTP @@ -109,6 +122,9 @@ * This exception can be queried for the details of the error. * <p> * This method must be called before the URLConnection is connected. + * <p> + * <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended + * instead of this method as it allows larger content lengths to be set. * * @param contentLength The number of bytes which will be written * to the OutputStream. @@ -135,6 +151,52 @@ fixedContentLength = contentLength; } + /** + * This method is used to enable streaming of a HTTP request body + * without internal buffering, when the content length is known in + * advance. + * + * <P> An exception will be thrown if the application attempts to write + * more data than the indicated content-length, or if the application + * closes the OutputStream before writing the indicated amount. + * + * <P> When output streaming is enabled, authentication and redirection + * cannot be handled automatically. A {@linkplain HttpRetryException} will + * be thrown when reading the response if authentication or redirection + * are required. This exception can be queried for the details of the + * error. + * + * <P> This method must be called before the URLConnection is connected. + * + * <P> The content length set by invoking this method takes precedence + * over any value set by {@link #setFixedLengthStreamingMode(int)}. + * + * @param contentLength + * The number of bytes which will be written to the OutputStream. + * + * @throws IllegalStateException + * if URLConnection is already connected or if a different + * streaming mode is already enabled. + * + * @throws IllegalArgumentException + * if a content length less than zero is specified. + * + * @since 1.7 + */ + public void setFixedLengthStreamingMode(long contentLength) { + if (connected) { + throw new IllegalStateException("Already connected"); + } + if (chunkLength != -1) { + throw new IllegalStateException( + "Chunked encoding streaming mode set"); + } + if (contentLength < 0) { + throw new IllegalArgumentException("invalid content length"); + } + fixedContentLengthLong = contentLength; + } + /* Default chunk size (including chunk header) if not specified; * we want to keep this in sync with the one defined in * sun.net.www.http.ChunkedOutputStream @@ -170,7 +232,7 @@ if (connected) { throw new IllegalStateException ("Can't set streaming mode: already connected"); } - if (fixedContentLength != -1) { + if (fixedContentLength != -1 || fixedContentLengthLong != -1) { throw new IllegalStateException ("Fixed length streaming mode set"); } chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Nov 11 09:07:58 2008 +0000 +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Nov 12 16:38:17 2008 +0000 @@ -435,8 +435,14 @@ if (streaming()) { if (chunkLength != -1) { requests.set ("Transfer-Encoding", "chunked"); - } else { - requests.set ("Content-Length", String.valueOf(fixedContentLength)); + } else { /* fixed content length */ + if (fixedContentLengthLong != -1) { + requests.set ("Content-Length", + String.valueOf(fixedContentLengthLong)); + } else if (fixedContentLength != -1) { + requests.set ("Content-Length", + String.valueOf(fixedContentLength)); + } } } else if (poster != null) { /* add Content-Length & POST/PUT data */ @@ -871,11 +877,17 @@ ps = (PrintStream)http.getOutputStream(); if (streaming()) { if (strOutputStream == null) { - if (fixedContentLength != -1) { - strOutputStream = new StreamingOutputStream (ps, fixedContentLength); - } else if (chunkLength != -1) { - strOutputStream = - new StreamingOutputStream (new ChunkedOutputStream (ps, chunkLength), -1); + if (chunkLength != -1) { /* chunked */ + strOutputStream = new StreamingOutputStream( + new ChunkedOutputStream(ps, chunkLength), -1L); + } else { /* must be fixed content length */ + long length = 0L; + if (fixedContentLengthLong != -1) { + length = fixedContentLengthLong; + } else if (fixedContentLength != -1) { + length = fixedContentLength; + } + strOutputStream = new StreamingOutputStream(ps, length); } } return strOutputStream; @@ -895,7 +907,8 @@ } private boolean streaming () { - return (fixedContentLength != -1) || (chunkLength != -1); + return (fixedContentLength != -1) || (fixedContentLengthLong != -1) || + (chunkLength != -1); } /* @@ -2619,8 +2632,8 @@ class StreamingOutputStream extends FilterOutputStream { - int expected; - int written; + long expected; + long written; boolean closed; boolean error; IOException errorExcp; @@ -2631,10 +2644,10 @@ * In the 2nd case, we make sure the expected number of * of bytes are actually written */ - StreamingOutputStream (OutputStream os, int expectedLength) { + StreamingOutputStream (OutputStream os, long expectedLength) { super (os); expected = expectedLength; - written = 0; + written = 0L; closed = false; error = false; } @@ -2643,7 +2656,7 @@ public void write (int b) throws IOException { checkError(); written ++; - if (expected != -1 && written > expected) { + if (expected != -1L && written > expected) { throw new IOException ("too many bytes written"); } out.write (b); @@ -2658,7 +2671,7 @@ public void write (byte[] b, int off, int len) throws IOException { checkError(); written += len; - if (expected != -1 && written > expected) { + if (expected != -1L && written > expected) { out.close (); throw new IOException ("too many bytes written"); } @@ -2691,7 +2704,7 @@ return; } closed = true; - if (expected != -1) { + if (expected != -1L) { /* not chunked */ if (written != expected) { error = true;
--- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Tue Nov 11 09:07:58 2008 +0000 +++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java Wed Nov 12 16:38:17 2008 +0000 @@ -527,6 +527,10 @@ delegate.setFixedLengthStreamingMode(contentLength); } + public void setFixedLengthStreamingMode(long contentLength) { + delegate.setFixedLengthStreamingMode(contentLength); + } + public void setChunkedStreamingMode (int chunklen) { delegate.setChunkedStreamingMode(chunklen); }
--- a/jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java Tue Nov 11 09:07:58 2008 +0000 +++ b/jdk/test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java Wed Nov 12 16:38:17 2008 +0000 @@ -23,7 +23,7 @@ /** * @test - * @bug 6756771 + * @bug 6756771 6755625 * @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig */ @@ -44,34 +44,16 @@ { static final long POST_SIZE = 4L * 1024L * 1024L * 1024L; // 4Gig - /* Remove when CR 6755625 is fixed */ - static final String requestHeaders = ((new StringBuilder()) - .append("POST /flis/ HTTP/1.1\r\n") - .append("User-Agent: Java/1.7.0\r\n") - .append("Host: localhost\r\n") - .append("Accept: text/html, image/gif, image/jpeg,") - .append( " *; q=.2, */*; q=.2\r\n") - .append("Content-Length: 4294967296\r\n\r\n")).toString(); - void test(String[] args) throws IOException { HttpServer httpServer = startHttpServer(); int port = httpServer.getAddress().getPort(); try { - /* Uncomment & when CR 6755625 is fixed, remove socket code URL url = new URL("http://localhost:" + port + "/flis/"); HttpURLConnection uc = (HttpURLConnection)url.openConnection(); uc.setDoOutput(true); uc.setRequestMethod("POST"); uc.setFixedLengthStreamingMode(POST_SIZE); OutputStream os = uc.getOutputStream(); - */ - - Socket socket = new Socket("localhost", port); - OutputStream os = socket.getOutputStream(); - PrintStream ps = new PrintStream(os); - debug("Request: " + requestHeaders); - ps.print(requestHeaders); - ps.flush(); /* create a 32K byte array with data to POST */ int thirtyTwoK = 32 * 1024; @@ -84,18 +66,12 @@ os.write(ba); } - /* Uncomment & when CR 6755625 is fixed, remove socket code os.close(); InputStream is = uc.getInputStream(); while(is.read(ba) != -1); is.close(); - */ - InputStream is = socket.getInputStream(); - is.read(); - socket.close(); - - pass(); + pass(); } finally { httpServer.stop(0); }