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