1 /* 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 4636331 27 * @summary Check that URLClassLoader doesn't create excessive http 28 * connections 29 */ 30 import java.net.*; 31 import java.io.*; 32 import java.util.*; 33 34 public class HttpTest { 35 36 /* 37 * Simple http server to service http requests. Auto shutdown 38 * if "idle" (no requests) for 10 seconds. Forks worker thread 39 * to service persistent connections. Work threads shutdown if 40 * "idle" for 5 seconds. 41 */ 42 static class HttpServer implements Runnable { 43 44 private static HttpServer svr = null; 45 private static Counters cnts = null; 46 private static ServerSocket ss; 47 48 private static Object counterLock = new Object(); 49 private static int getCount = 0; 50 private static int headCount = 0; 51 52 class Worker extends Thread { 53 Socket s; Worker(Socket s)54 Worker(Socket s) { 55 this.s = s; 56 } 57 run()58 public void run() { 59 InputStream in = null; 60 try { 61 in = s.getInputStream(); 62 for (;;) { 63 64 // read entire request from client 65 byte b[] = new byte[1024]; 66 int n, total=0; 67 68 // max 5 seconds to wait for new request 69 s.setSoTimeout(5000); 70 try { 71 do { 72 n = in.read(b, total, b.length-total); 73 // max 0.5 seconds between each segment 74 // of request. 75 s.setSoTimeout(500); 76 if (n > 0) total += n; 77 } while (n > 0); 78 } catch (SocketTimeoutException e) { } 79 80 if (total == 0) { 81 s.close(); 82 return; 83 } 84 85 boolean getRequest = false; 86 if (b[0] == 'G' && b[1] == 'E' && b[2] == 'T') 87 getRequest = true; 88 89 synchronized (counterLock) { 90 if (getRequest) 91 getCount++; 92 else 93 headCount++; 94 } 95 96 // response to client 97 PrintStream out = new PrintStream( 98 new BufferedOutputStream( 99 s.getOutputStream() )); 100 out.print("HTTP/1.1 200 OK\r\n"); 101 102 out.print("Content-Length: 75000\r\n"); 103 out.print("\r\n"); 104 if (getRequest) { 105 for (int i=0; i<75*1000; i++) { 106 out.write( (byte)'.' ); 107 } 108 } 109 out.flush(); 110 111 } // for 112 113 } catch (Exception e) { 114 unexpected(e); 115 } finally { 116 if (in != null) { try {in.close(); } catch(IOException e) {unexpected(e);} } 117 } 118 } 119 } 120 HttpServer()121 HttpServer() throws Exception { 122 ss = new ServerSocket(0); 123 } 124 run()125 public void run() { 126 try { 127 // shutdown if no request in 10 seconds. 128 ss.setSoTimeout(10000); 129 for (;;) { 130 Socket s = ss.accept(); 131 (new Worker(s)).start(); 132 } 133 } catch (Exception e) { 134 } 135 } 136 unexpected(Exception e)137 void unexpected(Exception e) { 138 System.out.println(e); 139 e.printStackTrace(); 140 } 141 create()142 public static HttpServer create() throws Exception { 143 if (svr != null) 144 return svr; 145 cnts = new Counters(); 146 svr = new HttpServer(); 147 (new Thread(svr)).start(); 148 return svr; 149 } 150 shutdown()151 public static void shutdown() throws Exception { 152 if (svr != null) { 153 ss.close(); 154 svr = null; 155 } 156 } 157 port()158 public int port() { 159 return ss.getLocalPort(); 160 } 161 162 public static class Counters { reset()163 public void reset() { 164 synchronized (counterLock) { 165 getCount = 0; 166 headCount = 0; 167 } 168 } 169 getCount()170 public int getCount() { 171 synchronized (counterLock) { 172 return getCount; 173 } 174 } 175 headCount()176 public int headCount() { 177 synchronized (counterLock) { 178 return headCount; 179 } 180 } 181 toString()182 public String toString() { 183 synchronized (counterLock) { 184 return "GET count: " + getCount + "; " + 185 "HEAD count: " + headCount; 186 } 187 } 188 } 189 counters()190 public Counters counters() { 191 return cnts; 192 } 193 194 } 195 main(String args[])196 public static void main(String args[]) throws Exception { 197 boolean failed = false; 198 199 // create http server 200 HttpServer svr = HttpServer.create(); 201 202 // create class loader 203 URL urls[] = 204 { new URL("http://localhost:" + svr.port() + "/dir1/"), 205 new URL("http://localhost:" + svr.port() + "/dir2/") }; 206 URLClassLoader cl = new URLClassLoader(urls); 207 208 // Test 1 - check that getResource does single HEAD request 209 svr.counters().reset(); 210 URL url = cl.getResource("foo.gif"); 211 System.out.println(svr.counters()); 212 213 if (svr.counters().getCount() > 0 || 214 svr.counters().headCount() > 1) { 215 failed = true; 216 } 217 218 // Test 2 - check that getResourceAsStream does at most 219 // one GET request 220 svr.counters().reset(); 221 InputStream in = cl.getResourceAsStream("foo2.gif"); 222 in.close(); 223 System.out.println(svr.counters()); 224 if (svr.counters().getCount() > 1) { 225 failed = true; 226 } 227 228 // Test 3 - check that getResources only does HEAD requests 229 svr.counters().reset(); 230 Enumeration e = cl.getResources("foos.gif"); 231 try { 232 for (;;) { 233 e.nextElement(); 234 } 235 } catch (NoSuchElementException exc) { } 236 System.out.println(svr.counters()); 237 if (svr.counters().getCount() > 1) { 238 failed = true; 239 } 240 241 // shutdown http server 242 svr.shutdown(); 243 244 if (failed) { 245 throw new Exception("Excessive http connections established - Test failed"); 246 } 247 } 248 249 } 250