1 /* 2 * Copyright (c) 2002, 2019, 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 * @library /test/lib 28 * @summary Check that URLClassLoader doesn't create excessive http 29 * connections 30 */ 31 import java.net.*; 32 import java.io.*; 33 import java.util.*; 34 35 import jdk.test.lib.net.URIBuilder; 36 37 public class HttpTest { 38 39 /* 40 * Simple http server to service http requests. Auto shutdown 41 * if "idle" (no requests) for 10 seconds. Forks worker thread 42 * to service persistent connections. Work threads shutdown if 43 * "idle" for 5 seconds. 44 */ 45 static class HttpServer implements Runnable { 46 47 private static HttpServer svr = null; 48 private static Counters cnts = null; 49 private static ServerSocket ss; 50 51 private static Object counterLock = new Object(); 52 private static int getCount = 0; 53 private static int headCount = 0; 54 55 class Worker extends Thread { 56 Socket s; Worker(Socket s)57 Worker(Socket s) { 58 this.s = s; 59 } 60 run()61 public void run() { 62 InputStream in = null; 63 try { 64 in = s.getInputStream(); 65 for (;;) { 66 67 // read entire request from client 68 byte b[] = new byte[1024]; 69 int n, total=0; 70 71 // max 5 seconds to wait for new request 72 s.setSoTimeout(5000); 73 try { 74 do { 75 n = in.read(b, total, b.length-total); 76 // max 0.5 seconds between each segment 77 // of request. 78 s.setSoTimeout(500); 79 if (n > 0) total += n; 80 } while (n > 0); 81 } catch (SocketTimeoutException e) { } 82 83 if (total == 0) { 84 s.close(); 85 return; 86 } 87 88 boolean getRequest = false; 89 if (b[0] == 'G' && b[1] == 'E' && b[2] == 'T') 90 getRequest = true; 91 92 synchronized (counterLock) { 93 if (getRequest) 94 getCount++; 95 else 96 headCount++; 97 } 98 99 // response to client 100 PrintStream out = new PrintStream( 101 new BufferedOutputStream( 102 s.getOutputStream() )); 103 out.print("HTTP/1.1 200 OK\r\n"); 104 105 out.print("Content-Length: 75000\r\n"); 106 out.print("\r\n"); 107 if (getRequest) { 108 for (int i=0; i<75*1000; i++) { 109 out.write( (byte)'.' ); 110 } 111 } 112 out.flush(); 113 114 } // for 115 116 } catch (Exception e) { 117 unexpected(e); 118 } finally { 119 if (in != null) { try {in.close(); } catch(IOException e) {unexpected(e);} } 120 } 121 } 122 } 123 HttpServer()124 HttpServer() throws Exception { 125 ss = new ServerSocket(); 126 ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); 127 } 128 run()129 public void run() { 130 try { 131 // shutdown if no request in 10 seconds. 132 ss.setSoTimeout(10000); 133 for (;;) { 134 Socket s = ss.accept(); 135 (new Worker(s)).start(); 136 } 137 } catch (Exception e) { 138 } 139 } 140 unexpected(Exception e)141 void unexpected(Exception e) { 142 System.out.println(e); 143 e.printStackTrace(); 144 } 145 create()146 public static HttpServer create() throws Exception { 147 if (svr != null) 148 return svr; 149 cnts = new Counters(); 150 svr = new HttpServer(); 151 (new Thread(svr)).start(); 152 return svr; 153 } 154 shutdown()155 public static void shutdown() throws Exception { 156 if (svr != null) { 157 ss.close(); 158 svr = null; 159 } 160 } 161 port()162 public int port() { 163 return ss.getLocalPort(); 164 } 165 166 public static class Counters { reset()167 public void reset() { 168 synchronized (counterLock) { 169 getCount = 0; 170 headCount = 0; 171 } 172 } 173 getCount()174 public int getCount() { 175 synchronized (counterLock) { 176 return getCount; 177 } 178 } 179 headCount()180 public int headCount() { 181 synchronized (counterLock) { 182 return headCount; 183 } 184 } 185 toString()186 public String toString() { 187 synchronized (counterLock) { 188 return "GET count: " + getCount + "; " + 189 "HEAD count: " + headCount; 190 } 191 } 192 } 193 counters()194 public Counters counters() { 195 return cnts; 196 } 197 198 } 199 main(String args[])200 public static void main(String args[]) throws Exception { 201 boolean failed = false; 202 203 // create http server 204 HttpServer svr = HttpServer.create(); 205 206 // create class loader 207 URL urls[] = { 208 URIBuilder.newBuilder().scheme("http").loopback().port(svr.port()) 209 .path("/dir1/").toURL(), 210 URIBuilder.newBuilder().scheme("http").loopback().port(svr.port()) 211 .path("/dir2/").toURL(), 212 }; 213 URLClassLoader cl = new URLClassLoader(urls); 214 215 // Test 1 - check that getResource does single HEAD request 216 svr.counters().reset(); 217 URL url = cl.getResource("foo.gif"); 218 System.out.println(svr.counters()); 219 220 if (svr.counters().getCount() > 0 || 221 svr.counters().headCount() > 1) { 222 failed = true; 223 } 224 225 // Test 2 - check that getResourceAsStream does at most 226 // one GET request 227 svr.counters().reset(); 228 InputStream in = cl.getResourceAsStream("foo2.gif"); 229 in.close(); 230 System.out.println(svr.counters()); 231 if (svr.counters().getCount() > 1) { 232 failed = true; 233 } 234 235 // Test 3 - check that getResources only does HEAD requests 236 svr.counters().reset(); 237 Enumeration e = cl.getResources("foos.gif"); 238 try { 239 for (;;) { 240 e.nextElement(); 241 } 242 } catch (NoSuchElementException exc) { } 243 System.out.println(svr.counters()); 244 if (svr.counters().getCount() > 1) { 245 failed = true; 246 } 247 248 // shutdown http server 249 svr.shutdown(); 250 251 if (failed) { 252 throw new Exception("Excessive http connections established - Test failed"); 253 } 254 } 255 256 } 257