1 /*
   2  * Copyright (c) 2009, 2017, 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 4167874
  27  * @modules java.logging
  28  *          jdk.httpserver
  29  *          jdk.compiler
  30  * @library ../../../../com/sun/net/httpserver
  31  *          /lib/testlibrary
  32  *          /test/lib
  33  * @build jdk.test.lib.compiler.CompilerUtils
  34  *        jdk.test.lib.util.FileUtils
  35  *        jdk.test.lib.Utils
  36  *        jdk.test.lib.Asserts
  37  *        jdk.test.lib.JDKToolFinder
  38  *        jdk.test.lib.JDKToolLauncher
  39  *        jdk.test.lib.Platform
  40  *        jdk.test.lib.process.*
  41  *        FileServerHandler JarUtils
  42  * @run main/othervm CloseTest
  43  * @summary URL-downloaded jar files can consume all available file descriptors
  44  */
  45 
  46 import java.io.File;
  47 import java.io.IOException;
  48 import java.lang.reflect.Method;
  49 import java.net.URLClassLoader;
  50 import java.net.InetSocketAddress;
  51 import java.net.URL;
  52 import java.nio.file.Files;
  53 import java.nio.file.Path;
  54 import java.nio.file.Paths;
  55 
  56 import jdk.test.lib.compiler.CompilerUtils;
  57 
  58 import com.sun.net.httpserver.HttpContext;
  59 import com.sun.net.httpserver.HttpServer;
  60 
  61 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  62 
  63 public class CloseTest extends Common {
  64     private static final String WORK_DIR = System.getProperty("user.dir")
  65             + "/";
  66 //
  67 // needs two jar files test1.jar and test2.jar with following structure
  68 //
  69 // com/foo/TestClass
  70 // com/foo/TestClass1
  71 // com/foo/Resource1
  72 // com/foo/Resource2
  73 //
  74 // and a directory hierarchy with the same structure/contents
  75 
  76     public static void main(String args[]) throws Exception {
  77         setup();
  78 
  79         startHttpServer(WORK_DIR + "serverRoot/");
  80 
  81         String testjar = WORK_DIR + "test.jar";
  82         copyFile(WORK_DIR + "test1.jar", testjar);
  83         test(testjar, 1);
  84 
  85         // repeat test with different implementation
  86         // of test.jar (whose TestClass.getValue() returns 2
  87         copyFile(WORK_DIR + "test2.jar", testjar);
  88         test(testjar, 2);
  89 
  90         // repeat test using a directory of files
  91         String testdir = WORK_DIR + "testdir/";
  92         rm_minus_rf(new File(testdir));
  93         copyDir(WORK_DIR + "test1/", testdir);
  94         test(testdir, 1);
  95 
  96         testdir = WORK_DIR + "testdir/";
  97         rm_minus_rf(new File(testdir));
  98         copyDir(WORK_DIR + "test2/", testdir);
  99         test(testdir, 2);
 100         getHttpServer().stop(3);
 101     }
 102 
 103     // create a loader on jarfile (or directory), plus a http loader
 104     // load a class , then look for a resource
 105     // also load a class from http loader
 106     // then close the loader
 107     // check further new classes/resources cannot be loaded
 108     // check jar (or dir) can be deleted
 109     // check existing classes can be loaded
 110     // check boot classes can be loaded
 111 
 112     static void test(String name, int expectedValue) throws Exception {
 113 
 114         URL url = new URL("file", null, name);
 115         URL url2 = getServerURL();
 116         System.out.println("Doing tests with URL: " + url + " and " + url2);
 117         URL[] urls = new URL[2];
 118         urls[0] = url;
 119         urls[1] = url2;
 120         URLClassLoader loader = new URLClassLoader(urls);
 121         Class testclass = loadClass("com.foo.TestClass", loader, true);
 122         Class class2 = loadClass("Test", loader, true); // from http
 123         class2.newInstance();
 124         Object test = testclass.newInstance();
 125         Method method = testclass.getDeclaredMethods()[0]; // int getValue();
 126         int res = (Integer) method.invoke(test);
 127 
 128         if (res != expectedValue) {
 129             throw new RuntimeException("wrong value from getValue() [" + res +
 130                     "/" + expectedValue + "]");
 131         }
 132 
 133         // should find /resource1
 134         URL u1 = loader.findResource("com/foo/Resource1");
 135         if (u1 == null) {
 136             throw new RuntimeException("can't find com/foo/Resource1 in test1.jar");
 137         }
 138         loader.close();
 139 
 140         // should NOT find /resource2 even though it is in jar
 141         URL u2 = loader.findResource("com/foo/Resource2");
 142         if (u2 != null) {
 143             throw new RuntimeException("com/foo/Resource2 unexpected in test1.jar");
 144         }
 145 
 146         // load tests
 147         loadClass("com.foo.TestClass1", loader, false);
 148         loadClass("com.foo.TestClass", loader, true);
 149         loadClass("java.util.ArrayList", loader, true);
 150 
 151         // now check we can delete the path
 152         rm_minus_rf(new File(name));
 153         System.out.println(" ... OK");
 154     }
 155 
 156     static HttpServer httpServer;
 157 
 158     static HttpServer getHttpServer() {
 159         return httpServer;
 160     }
 161 
 162     static URL getServerURL() throws Exception {
 163         int port = httpServer.getAddress().getPort();
 164         String s = "http://127.0.0.1:" + port + "/";
 165         return new URL(s);
 166     }
 167 
 168     static void startHttpServer(String docroot) throws Exception {
 169         httpServer = HttpServer.create(new InetSocketAddress(0), 10);
 170         HttpContext ctx = httpServer.createContext(
 171                 "/", new FileServerHandler(docroot)
 172         );
 173         httpServer.start();
 174     }
 175 
 176     /**
 177      * Prepare jars files for the tests
 178      */
 179     private static void setup () throws IOException {
 180         String[] tests = new String[]{"test1", "test2"};
 181         Path workDir = Paths.get(WORK_DIR);
 182         Path testSrc = Paths.get(System.getProperty("test.src"));
 183         for (String test : tests) {
 184             Path testSrcDir =  testSrc.resolve(test);
 185             Path testTargetDir = workDir.resolve(test);
 186             // Compile sources for corresponding test
 187             CompilerUtils.compile(testSrcDir, testTargetDir);
 188             // Copy all resources
 189             Path packages = Paths.get("com", "foo");
 190             Path copySrcDir = testSrcDir.resolve(packages);
 191             Path copyTargetDir = testTargetDir.resolve(packages);
 192             Files.createDirectories(copyTargetDir);
 193             Path res1 = Paths.get("Resource1");
 194             Path res2 = Paths.get("Resource2");
 195             Files.copy(copySrcDir.resolve(res1), copyTargetDir.resolve(res1),
 196                        REPLACE_EXISTING);
 197             Files.copy(copySrcDir.resolve(res2), copyTargetDir.resolve(res2),
 198                        REPLACE_EXISTING);
 199             // Create jar
 200             JarUtils.createJarFile(workDir.resolve(test + ".jar"), testTargetDir);
 201         }
 202 
 203         // Copy and compile server test class
 204         Path serverRoot = Paths.get("serverRoot");
 205         Path targetDir = workDir.resolve(serverRoot);
 206         Path file = Paths.get("Test.java");
 207         Files.createDirectories(targetDir);
 208         Files.copy(testSrc.resolve(serverRoot).resolve(file),
 209                    targetDir.resolve(file), REPLACE_EXISTING);
 210         CompilerUtils.compile(targetDir, targetDir);
 211     }
 212 }