/* * Copyright (c) 2002, 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 4636331 * @summary Check that URLClassLoader doesn't create excessive http * connections */ import java.net.*; import java.io.*; import java.util.*; public class HttpTest { /* * Simple http server to service http requests. Auto shutdown * if "idle" (no requests) for 10 seconds. Forks worker thread * to service persistent connections. Work threads shutdown if * "idle" for 5 seconds. */ static class HttpServer implements Runnable { private static HttpServer svr = null; private static Counters cnts = null; private static ServerSocket ss; private static Object counterLock = new Object(); private static int getCount = 0; private static int headCount = 0; class Worker extends Thread { Socket s; Worker(Socket s) { this.s = s; } public void run() { InputStream in = null; try { in = s.getInputStream(); for (;;) { // read entire request from client byte b[] = new byte[1024]; int n, total=0; // max 5 seconds to wait for new request s.setSoTimeout(5000); try { do { n = in.read(b, total, b.length-total); // max 0.5 seconds between each segment // of request. s.setSoTimeout(500); if (n > 0) total += n; } while (n > 0); } catch (SocketTimeoutException e) { } if (total == 0) { s.close(); return; } boolean getRequest = false; if (b[0] == 'G' && b[1] == 'E' && b[2] == 'T') getRequest = true; synchronized (counterLock) { if (getRequest) getCount++; else headCount++; } // response to client PrintStream out = new PrintStream( new BufferedOutputStream( s.getOutputStream() )); out.print("HTTP/1.1 200 OK\r\n"); out.print("Content-Length: 75000\r\n"); out.print("\r\n"); if (getRequest) { for (int i=0; i<75*1000; i++) { out.write( (byte)'.' ); } } out.flush(); } // for } catch (Exception e) { unexpected(e); } finally { if (in != null) { try {in.close(); } catch(IOException e) {unexpected(e);} } } } } HttpServer() throws Exception { ss = new ServerSocket(0); } public void run() { try { // shutdown if no request in 10 seconds. ss.setSoTimeout(10000); for (;;) { Socket s = ss.accept(); (new Worker(s)).start(); } } catch (Exception e) { } } void unexpected(Exception e) { System.out.println(e); e.printStackTrace(); } public static HttpServer create() throws Exception { if (svr != null) return svr; cnts = new Counters(); svr = new HttpServer(); (new Thread(svr)).start(); return svr; } public static void shutdown() throws Exception { if (svr != null) { ss.close(); svr = null; } } public int port() { return ss.getLocalPort(); } public static class Counters { public void reset() { synchronized (counterLock) { getCount = 0; headCount = 0; } } public int getCount() { synchronized (counterLock) { return getCount; } } public int headCount() { synchronized (counterLock) { return headCount; } } public String toString() { synchronized (counterLock) { return "GET count: " + getCount + "; " + "HEAD count: " + headCount; } } } public Counters counters() { return cnts; } } public static void main(String args[]) throws Exception { boolean failed = false; // create http server HttpServer svr = HttpServer.create(); // create class loader URL urls[] = { new URL("http://localhost:" + svr.port() + "/dir1/"), new URL("http://localhost:" + svr.port() + "/dir2/") }; URLClassLoader cl = new URLClassLoader(urls); // Test 1 - check that getResource does single HEAD request svr.counters().reset(); URL url = cl.getResource("foo.gif"); System.out.println(svr.counters()); if (svr.counters().getCount() > 0 || svr.counters().headCount() > 1) { failed = true; } // Test 2 - check that getResourceAsStream does at most // one GET request svr.counters().reset(); InputStream in = cl.getResourceAsStream("foo2.gif"); in.close(); System.out.println(svr.counters()); if (svr.counters().getCount() > 1) { failed = true; } // Test 3 - check that getResources only does HEAD requests svr.counters().reset(); Enumeration e = cl.getResources("foos.gif"); try { for (;;) { e.nextElement(); } } catch (NoSuchElementException exc) { } System.out.println(svr.counters()); if (svr.counters().getCount() > 1) { failed = true; } // shutdown http server svr.shutdown(); if (failed) { throw new Exception("Excessive http connections established - Test failed"); } } }