--- /dev/null 2016-11-05 03:43:13.806222279 -0700 +++ new/test/java/lang/ClassLoader/securityManager/ClassLoaderTest.java 2017-01-13 01:19:42.047131827 -0800 @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2017, 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 8168423 + * @summary Custom ClassLoader running with(out) SecurityManager and + * (in)valid security policy + * It addresses the following test cases, + * for (policyFile : {"NO_POLICY", "VALID", "MALFORMED"}) { + * for (classLoader : {"SystemClassLoader", "CustomClassLoader"}){ + * for (clientModule : {"NAMED", "AUTOMATIC", "UNNAMED"}) { + * for (classLoaderModule : {"NAMED", "AUTOMATIC", "UNNAMED"}) { + * // Create and run java command line for each possible + * // Test cases and verify result. + * } + * } + * } + * } + * @library /lib/testlibrary + * @modules java.base/jdk.internal.module + * @build JarUtils CompilerUtils + * @run main/timeout=180 ClassLoaderTest + */ +import java.io.File; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Map; +import java.util.HashMap; +import java.lang.module.ModuleDescriptor; +import jdk.internal.module.ModuleInfoWriter; +import jdk.testlibrary.ProcessTools; + +public class ClassLoaderTest { + + private static final String SRC = System.getProperty("test.src"); + private static final Path CL_SRC = Paths.get(SRC, "TestClassLoader.java"); + private static final Path C_SRC = Paths.get(SRC, "TestClient.java"); + private static final Path CL_BIN = Paths.get("classes", "clbin"); + private static final Path C_BIN = Paths.get("classes", "cbin"); + private static final Path ARTIFACT_DIR = Paths.get("jars"); + private static final Path VALID_POLICY = Paths.get(SRC, "valid.policy"); + private static final Path INVALID_POLICY + = Paths.get(SRC, "malformed.policy"); + private static final Path NO_POLICY = null; + private static final String LOCALE = "-Duser.language=en -Duser.region=US"; + /* + * Here is the naming convention followed for each jar. + * cl.jar - Regular custom class loader jar. + * mcl.jar - Modular custom class loader jar. + * c.jar - Regular client jar. + * mc.jar - Modular client jar. + * amc.jar - Modular client referring automated custom class loader jar. + */ + private static final Path CL_JAR = ARTIFACT_DIR.resolve("cl.jar"); + private static final Path MCL_JAR = ARTIFACT_DIR.resolve("mcl.jar"); + private static final Path C_JAR = ARTIFACT_DIR.resolve("c.jar"); + private static final Path MC_JAR = ARTIFACT_DIR.resolve("mc.jar"); + private static final Path AMC_JAR = ARTIFACT_DIR.resolve("amc.jar"); + private static final Map MSG_MAP = new HashMap<>(); + + static { + // This mapping help process finding expected message based + // on the key passed as argument while executing java command. + MSG_MAP.put("MissingModule", "Module cl not found, required by mc"); + MSG_MAP.put("ErrorPolicy", "java.security.policy: error parsing file"); + MSG_MAP.put( + "SystemCL", "jdk.internal.loader.ClassLoaders$AppClassLoader"); + MSG_MAP.put("CustomCL", "cl.TestClassLoader"); + } + + public static void main(String[] args) throws Exception { + + // Generates regular and modular jars before start processing it. + setUp(); + processForEachPolicyFile(); + } + + /** + * Test cases are based on the following logic, + * for (policyFile : {"NO_POLICY", "VALID", "MALFORMED"}) { + * for (classLoader : {"SystemClassLoader", "CustomClassLoader"}){ + * for (clientModule : {"NAMED", "AUTOMATIC", "UNNAMED"}) { + * for (classLoaderModule : {"NAMED", "AUTOMATIC", "UNNAMED"}) { + * Create and run java command for each possible Test case + * } + * } + * } + * } + */ + private static void processForEachPolicyFile() throws Exception { + + final String regCLloc = CL_JAR.toFile().getAbsolutePath(); + final String modCLloc = MCL_JAR.toFile().getAbsolutePath(); + final String regCloc = C_JAR.toFile().getAbsolutePath(); + final String modCloc = MC_JAR.toFile().getAbsolutePath(); + final String autoModCloc = AMC_JAR.toFile().getAbsolutePath(); + final String separator = File.pathSeparator; + + for (Path policy + : new Path[]{NO_POLICY, VALID_POLICY, INVALID_POLICY}) { + final String policyFile = (policy != null) + ? policy.toFile().getAbsolutePath() : null; + final boolean malformedPolicy + = (policy == null) ? false : policy.equals(INVALID_POLICY); + + for (boolean useSCL : new boolean[]{true, false}) { + final String clVmArg = (useSCL) ? "" + : "-Djava.system.class.loader=cl.TestClassLoader"; + final String autoAddModArg + = (useSCL) ? "" : "--add-modules=cl"; + final String addmodArg = (useSCL) ? "" : "--add-modules=mcl"; + final String sMArg = (policy != null) ? String.format( + "-Djava.security.manager -Djava.security.policy=%s", + policyFile) : ""; + final String smMsg = (policy != null) ? "With SecurityManager" + : "Without SecurityManager"; + final String expectedResult = ((!malformedPolicy) + ? ((useSCL) ? "PASS SystemCL" : "PASS CustomCL") + : "FAIL ErrorPolicy"); + + // NAMED-NAMED, NAMED-AUTOMATIC, NAMED-UNNAMED + System.out.printf("Case:- Modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s%s%s %s %s %s -m mc/c.TestClient", + modCloc, separator, modCLloc, LOCALE, clVmArg, sMArg), + expectedResult}); + System.out.printf("Case:- Modular Client and %s %s%n", ((useSCL) + ? "SystemClassLoader" + : "Automatic modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s%s%s %s %s %s -m mc/c.TestClient", + autoModCloc, separator, regCLloc, LOCALE, clVmArg, sMArg), + expectedResult}); + System.out.printf("Case:- Modular Client and %s %s%n", ((useSCL) + ? "SystemClassLoader" + : "Unknown modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s -cp %s %s %s %s -m mc/c.TestClient", + autoModCloc, regCLloc, LOCALE, clVmArg, sMArg), + "FAIL MissingModule"}); + + // AUTOMATIC-NAMED, AUTOMATIC-AUTOMATIC, AUTOMATIC-UNNAMED + System.out.printf("Case:- Automated modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s%s%s %s %s %s %s -m c/c.TestClient", + regCloc, separator, modCLloc, addmodArg, LOCALE, clVmArg, + sMArg), expectedResult}); + System.out.printf("Case:- Automated modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Automatic modular CustomClassLoader"), + smMsg); + execute(new String[]{String.format( + "--module-path %s%s%s %s %s %s %s -m c/c.TestClient", + regCloc, separator, regCLloc, autoAddModArg, LOCALE, + clVmArg, sMArg), expectedResult}); + System.out.printf("Case:- Automated modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Unknown modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s -cp %s %s %s %s -m c/c.TestClient", + regCloc, regCLloc, LOCALE, clVmArg, sMArg), + expectedResult}); + + // UNNAMED-NAMED, UNNAMED-AUTOMATIC, UNNAMED-UNNAMED + System.out.printf("Case:- Unknown modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "-cp %s --module-path %s %s %s %s %s c.TestClient", + regCloc, modCLloc, addmodArg, LOCALE, clVmArg, sMArg), + expectedResult}); + System.out.printf("Case:- Unknown modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Automatic modular CustomClassLoader"), + smMsg); + execute(new String[]{String.format( + "-cp %s --module-path %s %s %s %s %s c.TestClient", + regCloc, regCLloc, autoAddModArg, LOCALE, clVmArg, sMArg), + expectedResult}); + System.out.printf("Case:- Unknown modular Client and %s %s%n", + ((useSCL) ? "SystemClassLoader" + : "Unknown modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "-cp %s%s%s %s %s %s c.TestClient", regCloc, separator, + regCLloc, LOCALE, clVmArg, sMArg), expectedResult}); + + // Regular jars in module-path and Modular jars in class-path. + System.out.printf("Case:- Regular Client and %s " + + "inside --module-path %s.%n", ((useSCL) + ? "SystemClassLoader" + : "Unknown modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "--module-path %s%s%s %s %s %s %s -m c/c.TestClient", + regCloc, separator, regCLloc, autoAddModArg, LOCALE, + clVmArg, sMArg), expectedResult}); + System.out.printf("Case:- Modular Client and %s in -cp %s%n", + ((useSCL) ? "SystemClassLoader" + : "Modular CustomClassLoader"), smMsg); + execute(new String[]{String.format( + "-cp %s%s%s %s %s %s c.TestClient", modCloc, separator, + modCLloc, LOCALE, clVmArg, sMArg), expectedResult}); + } + } + } + + /** + * Execute with command arguments and process the result. + */ + private static void execute(String[] args) throws Exception { + + String status = null; + String msgKey = null; + if ((args != null && args.length > 1)) { + String[] secArgs = args[1].split("\\s+"); + status = (secArgs.length > 0) ? secArgs[0] : null; + msgKey = (secArgs.length > 1) ? secArgs[1] : null; + } + String out = ProcessTools.executeTestJvm(args[0].split("\\s+")) + .getOutput(); + // Handle response. + if ((status != null && "PASS".equals(status) && msgKey != null + && out.contains(MSG_MAP.get(msgKey)))) { + System.out.printf("PASS: Expected Result: %s.%n", + MSG_MAP.get(msgKey)); + } else if ((status != null && "FAIL".equals(status) && msgKey != null + && out.contains(MSG_MAP.get(msgKey)))) { + System.out.printf("PASS: Expected Failure: %s.%n", + MSG_MAP.get(msgKey)); + } else if (out.contains("Exception") || out.contains("Error")) { + System.out.printf("OUTPUT: %s", out); + throw new RuntimeException("FAIL: Unknown Exception."); + } else { + System.out.printf("OUTPUT: %s", out); + throw new RuntimeException("FAIL: Unknown Test case found"); + } + } + + /** + * Creates regular/modular jar files for TestClient and TestClassLoader. + */ + private static void setUp() throws Exception { + + boolean compiled = CompilerUtils.compile(CL_SRC, CL_BIN); + compiled &= CompilerUtils.compile(C_SRC, C_BIN); + if (!compiled) { + throw new RuntimeException("Test Setup failed."); + } + // Generate regular jar files for TestClient and TestClassLoader + JarUtils.createJarFile(CL_JAR, CL_BIN); + JarUtils.createJarFile(C_JAR, C_BIN); + // Generate modular jar files for TestClient and TestClassLoader with + // their corresponding ModuleDescriptor. + Files.copy(CL_JAR, MCL_JAR, StandardCopyOption.REPLACE_EXISTING); + updateModuleDescr(MCL_JAR, ModuleDescriptor.module("mcl") + .exports("cl").requires("java.base").build()); + Files.copy(C_JAR, MC_JAR, StandardCopyOption.REPLACE_EXISTING); + updateModuleDescr(MC_JAR, ModuleDescriptor.module("mc") + .exports("c").requires("java.base").requires("mcl").build()); + Files.copy(C_JAR, AMC_JAR, StandardCopyOption.REPLACE_EXISTING); + updateModuleDescr(AMC_JAR, ModuleDescriptor.module("mc") + .exports("c").requires("java.base").requires("cl").build()); + } + + /** + * Update regular jars and include module-info.class inside it to make + * modular jars. + */ + private static void updateModuleDescr(Path jar, ModuleDescriptor mDescr) + throws Exception { + if (mDescr != null) { + Path dir = Files.createTempDirectory("tmp"); + Path mi = dir.resolve("module-info.class"); + try (OutputStream out = Files.newOutputStream(mi)) { + ModuleInfoWriter.write(mDescr, out); + } + System.out.format("Adding 'module-info.class' to jar '%s'%n", jar); + JarUtils.updateJarFile(jar, dir); + } + } +} --- /dev/null 2016-11-05 03:43:13.806222279 -0700 +++ new/test/java/lang/ClassLoader/securityManager/TestClassLoader.java 2017-01-13 01:19:42.609122757 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, 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. + */ +package cl; + +public class TestClassLoader extends ClassLoader { + + /** + * This constructor is used to set the parent ClassLoader + */ + public TestClassLoader(ClassLoader parent) { + super(parent); + } + +} --- /dev/null 2016-11-05 03:43:13.806222279 -0700 +++ new/test/java/lang/ClassLoader/securityManager/TestClient.java 2017-01-13 01:19:43.150114023 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, 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. + */ +package c; + +public class TestClient { + + public static void main(String[] args) { + + // Initialize policy file. + System.getProperty("test.src"); + System.out.printf("ContextClassLoader: %s%n", + Thread.currentThread().getContextClassLoader().toString()); + } +} --- /dev/null 2016-11-05 03:43:13.806222279 -0700 +++ new/test/java/lang/ClassLoader/securityManager/malformed.policy 2017-01-13 01:19:43.701105129 -0800 @@ -0,0 +1,4 @@ +grant { + xyz; + permission java.util.PropertyPermission "test.src", "read"; +} \ No newline at end of file --- /dev/null 2016-11-05 03:43:13.806222279 -0700 +++ new/test/java/lang/ClassLoader/securityManager/valid.policy 2017-01-13 01:19:44.252096235 -0800 @@ -0,0 +1,4 @@ +grant { + permission java.lang.RuntimePermission "createClassLoader"; + permission java.util.PropertyPermission "test.src", "read"; +}; \ No newline at end of file