1 /* 2 * Copyright (c) 2020, 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 8234466 27 * @summary attempt to trigger class loading from the classloader 28 * during JAR file verification 29 * @library /test/lib 30 * @build jdk.test.lib.compiler.CompilerUtils 31 * jdk.test.lib.process.* 32 * jdk.test.lib.util.JarUtils 33 * jdk.test.lib.JDKToolLauncher 34 * MultiThreadLoad FooService 35 * @modules java.base/jdk.internal.access:+open 36 * @run main MultiProviderTest 37 * @run main MultiProviderTest sign 38 */ 39 40 import java.io.File; 41 import java.nio.file.Files; 42 import java.nio.file.Path; 43 import java.nio.file.Paths; 44 import java.util.ArrayList; 45 import java.util.List; 46 47 import jdk.test.lib.JDKToolFinder; 48 import jdk.test.lib.JDKToolLauncher; 49 import jdk.test.lib.Utils; 50 import jdk.test.lib.compiler.CompilerUtils; 51 import jdk.test.lib.process.OutputAnalyzer; 52 import jdk.test.lib.process.ProcessTools; 53 import jdk.test.lib.util.JarUtils; 54 55 import static java.nio.file.StandardOpenOption.CREATE; 56 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 57 import static java.util.Arrays.asList; 58 59 public class MultiProviderTest { 60 61 private static final String METAINFO = "META-INF/services/FooService"; 62 private static String COMBO_CP = Utils.TEST_CLASS_PATH + File.pathSeparator; 63 private static String TEST_CLASS_PATH = System.getProperty("test.classes", "."); 64 private static boolean signJars = false; 65 static final int NUM_JARS = 5; 66 67 68 private static final String KEYSTORE = "keystore.jks"; 69 private static final String ALIAS = "JavaTest"; 70 private static final String STOREPASS = "changeit"; 71 private static final String KEYPASS = "changeit"; 72 main(String[] args)73 public static void main(String[] args) throws Throwable { 74 signJars = args.length >=1 && args[0].equals("sign"); 75 initialize(); 76 List<String> cmds = new ArrayList<>(); 77 cmds.add(JDKToolFinder.getJDKTool("java")); 78 cmds.addAll(asList(Utils.getTestJavaOpts())); 79 cmds.addAll(List.of( 80 "-cp", 81 COMBO_CP, 82 "--add-opens", 83 "java.base/jdk.internal.access=ALL-UNNAMED", 84 "-Djava.util.logging.config.file=" + 85 Path.of(System.getProperty("test.src", "."), "logging.properties").toString(), 86 "MultiThreadLoad", 87 TEST_CLASS_PATH)); 88 89 try { 90 OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(cmds.stream() 91 .filter(t -> !t.isEmpty()) 92 .toArray(String[]::new)) 93 .shouldHaveExitValue(0); 94 System.out.println("Output:" + outputAnalyzer.getOutput()); 95 } catch (Throwable t) { 96 throw new RuntimeException("Unexpected fail.", t); 97 } 98 } 99 initialize()100 public static void initialize() throws Throwable { 101 if (signJars) { 102 genKey(); 103 } 104 for (int i = 0; i < NUM_JARS; i++) { 105 String p = "FooProvider" + i; 106 String jarName = "FooProvider" + i + ".jar"; 107 Path javaPath = Path.of(p + ".java"); 108 Path jarPath = Path.of(p + ".jar"); 109 String contents = "public class FooProvider" + i + " extends FooService { }"; 110 Files.write(javaPath, contents.getBytes()); 111 CompilerUtils.compile(javaPath, Path.of(System.getProperty("test.classes")), "-cp", Utils.TEST_CLASS_PATH); 112 createJar(jarPath, p, List.of(p)); 113 if (signJars) { 114 signJar(TEST_CLASS_PATH + File.separator + jarName); 115 } 116 COMBO_CP += TEST_CLASS_PATH + File.separator + jarName + File.pathSeparator; 117 } 118 } 119 createProviderConfig(Path config, String providerName)120 private static void createProviderConfig(Path config, String providerName) throws Exception { 121 Files.createDirectories(config.getParent()); 122 Files.write(config, providerName.getBytes(), CREATE); 123 } 124 createJar(Path jar, String provider, List<String> files)125 private static void createJar(Path jar, String provider, List<String> files) throws Exception { 126 Path xdir = Path.of(provider); 127 createProviderConfig(xdir.resolve(METAINFO), provider); 128 129 for (String f : files) { 130 Path source = Path.of(Utils.TEST_CLASSES, f + ".class"); 131 Path target = xdir.resolve(source.getFileName()); 132 Files.copy(source, target, REPLACE_EXISTING); 133 } 134 JarUtils.createJarFile(Path.of(TEST_CLASS_PATH, jar.getFileName().toString()), xdir); 135 } 136 genKey()137 private static void genKey() throws Throwable { 138 String keytool = JDKToolFinder.getJDKTool("keytool"); 139 Files.deleteIfExists(Paths.get(KEYSTORE)); 140 ProcessTools.executeCommand(keytool, 141 "-J-Duser.language=en", 142 "-J-Duser.country=US", 143 "-genkey", 144 "-keyalg", "rsa", 145 "-alias", ALIAS, 146 "-keystore", KEYSTORE, 147 "-keypass", KEYPASS, 148 "-dname", "cn=sample", 149 "-storepass", STOREPASS 150 ).shouldHaveExitValue(0); 151 } 152 153 signJar(String jarName)154 private static OutputAnalyzer signJar(String jarName) throws Throwable { 155 List<String> args = new ArrayList<>(); 156 args.add("-verbose"); 157 args.add(jarName); 158 args.add(ALIAS); 159 160 return jarsigner(args); 161 } 162 jarsigner(List<String> extra)163 private static OutputAnalyzer jarsigner(List<String> extra) 164 throws Throwable { 165 JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") 166 .addVMArg("-Duser.language=en") 167 .addVMArg("-Duser.country=US") 168 .addToolArg("-keystore") 169 .addToolArg(KEYSTORE) 170 .addToolArg("-storepass") 171 .addToolArg(STOREPASS) 172 .addToolArg("-keypass") 173 .addToolArg(KEYPASS); 174 for (String s : extra) { 175 if (s.startsWith("-J")) { 176 launcher.addVMArg(s.substring(2)); 177 } else { 178 launcher.addToolArg(s); 179 } 180 } 181 return ProcessTools.executeCommand(launcher.getCommand()); 182 } 183 184 } 185 186