OpenJDK / jdk / jdk
changeset 6685:36f070045e17
6550798: Using InputStream.skip with ResponseCache will cause partial data to be cached
Reviewed-by: chegar
author | michaelm |
---|---|
date | Tue, 28 Sep 2010 11:59:57 +0100 |
parents | 5920fb9d1ebe |
children | 712138e77559 |
files | jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java jdk/test/sun/net/www/protocol/http/6550798/TestCache.java jdk/test/sun/net/www/protocol/http/6550798/test.java |
diffstat | 3 files changed, 255 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Sat Sep 25 12:00:05 2010 -0700 +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Sep 28 11:59:57 2010 +0100 @@ -2825,6 +2825,38 @@ } } + /* skip() calls read() in order to ensure that entire response gets + * cached. same implementation as InputStream.skip */ + + private byte[] skipBuffer; + private static final int SKIP_BUFFER_SIZE = 8096; + + @Override + public long skip (long n) throws IOException { + + long remaining = n; + int nr; + if (skipBuffer == null) + skipBuffer = new byte[SKIP_BUFFER_SIZE]; + + byte[] localSkipBuffer = skipBuffer; + + if (n <= 0) { + return 0; + } + + while (remaining > 0) { + nr = read(localSkipBuffer, 0, + (int) Math.min(SKIP_BUFFER_SIZE, remaining)); + if (nr < 0) { + break; + } + remaining -= nr; + } + + return n - remaining; + } + @Override public void close () throws IOException { try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/net/www/protocol/http/6550798/TestCache.java Tue Sep 28 11:59:57 2010 +0100 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.*; +import java.io.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.PrintStream; +import java.io.InputStream; +import java.io.File; +import java.net.CacheRequest; +import java.net.CacheResponse; +import java.net.ResponseCache; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Iterator; +import java.util.StringTokenizer; +import java.util.jar.JarInputStream; +import java.util.jar.JarFile; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; +import java.security.Principal; +import java.security.cert.Certificate; +import javax.net.ssl.SSLPeerUnverifiedException; + +public class TestCache extends java.net.ResponseCache { + private boolean inCacheHandler = false; + private boolean _downloading = false; + + public static volatile boolean fail = false; + + public static void reset() { + // Set system wide cache handler + System.out.println("install deploy cache handler"); + ResponseCache.setDefault(new TestCache()); + } + + public synchronized CacheResponse get(final URI uri, String rqstMethod, + Map requestHeaders) throws IOException { + System.out.println("get: " + uri); + Thread.currentThread().dumpStack(); + return null; + } + + public synchronized CacheRequest put(URI uri, URLConnection conn) + throws IOException { + System.out.println("put: " + uri); + Thread.currentThread().dumpStack(); + URL url = uri.toURL(); + return new DeployCacheRequest(url, conn); + + } +} + +class DeployByteArrayOutputStream extends java.io.ByteArrayOutputStream { + + private URL _url; + private URLConnection _conn; + + DeployByteArrayOutputStream(URL url, URLConnection conn) { + _url = url; + _conn = conn; + } + + + public void close() throws IOException { + + System.out.println("contentLength: " + _conn.getContentLength()); + System.out.println("byte array size: " + size()); + if ( _conn.getContentLength() == size()) { + System.out.println("correct content length"); + } else { + System.out.println("wrong content length"); + System.out.println("TEST FAILED"); + TestCache.fail = true; + } + super.close(); + } +} + +class DeployCacheRequest extends java.net.CacheRequest { + + private URL _url; + private URLConnection _conn; + private boolean _downloading = false; + + DeployCacheRequest(URL url, URLConnection conn) { + System.out.println("DeployCacheRequest ctor for: " + url); + _url = url; + _conn = conn; + } + + public void abort() { + System.out.println("abort called"); + } + + public OutputStream getBody() throws IOException { + System.out.println("getBody called"); + return new DeployByteArrayOutputStream(_url, _conn); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/net/www/protocol/http/6550798/test.java Tue Sep 28 11:59:57 2010 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6550798 + * @summary Using InputStream.skip with ResponseCache will cause partial data to be cached + * @run main/othervm test + */ + +import java.net.*; +import com.sun.net.httpserver.*; +import java.io.*; + +public class test { + + final static int LEN = 16 * 1024; + + public static void main(String[] args) throws Exception { + + TestCache.reset(); + HttpServer s = HttpServer.create (new InetSocketAddress(0), 10); + s.createContext ("/", new HttpHandler () { + public void handle (HttpExchange e) { + try { + byte[] buf = new byte [LEN]; + OutputStream o = e.getResponseBody(); + e.sendResponseHeaders(200, LEN); + o.write (buf); + e.close(); + } catch (IOException ex) { + ex.printStackTrace(); + TestCache.fail = true; + } + } + }); + s.start(); + + System.out.println("http request with cache hander"); + URL u = new URL("http://127.0.0.1:"+s.getAddress().getPort()+"/f"); + URLConnection conn = u.openConnection(); + + InputStream is = null; + try { + // this calls into TestCache.get + byte[] buf = new byte[8192]; + is = new BufferedInputStream(conn.getInputStream()); + + is.skip(1000); + + while (is.read(buf) != -1) { + } + } finally { + if (is != null) { + // this calls into TestCache.put + // TestCache.put will check if the resource + // should be cached + is.close(); + } + s.stop(0); + } + + if (TestCache.fail) { + System.out.println ("TEST FAILED"); + throw new RuntimeException (); + } else { + System.out.println ("TEST OK"); + } + } +}